SpringCloud微服務(wù)的調(diào)用與遠程調(diào)用測試示例
微服務(wù)相關(guān)簡述
微服務(wù)架構(gòu)中的重要角色
- 服務(wù)調(diào)用者:可以暫時認為是與用戶交互的角色(因為存在微服務(wù)之間的調(diào)用),可以根據(jù)該用戶的類型將其賦予不同的服務(wù)調(diào)用權(quán)限,通過一次http請求訪問調(diào)用對應(yīng)的微服務(wù)獲取想要的數(shù)據(jù)。
- 微服務(wù):你可以將一個具備對外開放接口的springboot項目作為一個服務(wù),當(dāng)然這個服務(wù)最基本的功能必須要能夠具備數(shù)據(jù)庫數(shù)據(jù)交換與持久的能力。這樣的一個springboot項目可以將其稱之為一個微服務(wù)。通常在一個微服務(wù)架構(gòu)中,微服務(wù)A可能會存在多個(為了保證軟件系統(tǒng)的可用性)。
- 服務(wù)注冊中心:相當(dāng)于一個微服務(wù)架構(gòu)中的組件通訊錄,不僅可以保存注冊信息,還可以進行服務(wù)的心跳監(jiān)聽(健康檢測)。
- 熔斷:當(dāng)下游微服務(wù)業(yè)務(wù)訪問量劇增的時候,為了防止上層微服務(wù)收到其影響,采用熔斷器對其進行強行熔斷。
- 鏈路追蹤:為了記錄復(fù)雜的微服務(wù)之間調(diào)用的過程,采用鏈路的追蹤確保能夠清晰的看到微服務(wù)之間調(diào)用的過程可以很好的排查和治理微服務(wù)。
- API服務(wù)網(wǎng)關(guān):統(tǒng)一管理微服務(wù)的接口。
微服務(wù)架構(gòu)
優(yōu)點:通過服務(wù)的原子化拆分,以及微服務(wù)的獨立打包、部署和升級,小團隊的交付周期將縮短,運維成本也將大幅度下降,微服務(wù)遵循單一原則。微服務(wù)之間采用Restful等輕量協(xié)議傳輸。
缺點:微服務(wù)過多,服務(wù)治理成本高,不利于系統(tǒng)維護。分布式系統(tǒng)開發(fā)的技術(shù)成本高(容錯、分布式事務(wù)等)。
分布式遠程調(diào)用
我們知道,兩個springboot項目如果放在同一臺主機上運行,那么我們可以通過HttpClient或者Okhttp等等方式去創(chuàng)建一個Http客戶端實現(xiàn)由這一個springboot項目去訪問另一個springboot項目的過程,那么如果這兩個項目不在同一個主機上呢?在局域網(wǎng)中?在公網(wǎng)中?其實大同小異,只要我們能夠通過http協(xié)議的方式遠程訪問到對應(yīng)的API接口就可以實現(xiàn)兩個項目之間的調(diào)用。這就是一次遠程調(diào)用,當(dāng)然這里指的是基于Http的遠程調(diào)用方式。
在微服務(wù)架構(gòu)中,通常存在多個服務(wù)之間的遠程調(diào)用的需求。遠程調(diào)用通常包含兩個部分:序列化和通信協(xié)議。常見的序列化協(xié)議包括json、xml、hession、protobuf、thrift、text、bytes等,目前主流的遠程調(diào)用技術(shù)有基于HTTP的RESTFUL接口以及基于TCP的RPC協(xié)議。
RESTFUL接口
REST,即Representational State Transfer的縮寫,如果一個架構(gòu)符合REST原則,就稱它為RESTful架構(gòu)。
資源
所謂"資源",就是網(wǎng)絡(luò)上的一個實體,或者說是網(wǎng)絡(luò)上的一個具體信息。它可以是一段文本、一張圖片、一首歌曲、一種服務(wù),總之就是一個具體的實在。你可以用一個URI(統(tǒng)一資源定位符)指向它,每種資源對應(yīng)一個特定的URI。要獲取這個資源,訪問它的URI就可以,因此URI就成了每一個資源的地址或獨一無二的識別符。REST的名稱"表現(xiàn)層狀態(tài)轉(zhuǎn)化"中,省略了主語。"表現(xiàn)層"其實指的是"資 源"(Resources)的"表現(xiàn)層"。
表現(xiàn)層
"資源"是一種信息實體,它可以有多種外在表現(xiàn)形式。我們把"資源"具體呈現(xiàn)出來的形式,叫做它的"表現(xiàn)層"(Representation)。比如,文本可以用txt格式表現(xiàn),也可以用HTML格式、XML格式、JSON格式表現(xiàn),甚至可以采用二進制格式;圖片可以用JPG格式表現(xiàn),也可以用PNG格式表現(xiàn)。URI只代表資源的實體,不代表它的形式。嚴格地說,有些網(wǎng)址最后的".html"后綴名是不必要的,因為這個后綴名表示格式,屬于"表現(xiàn)層"范疇,而URI應(yīng)該只代表"資源"的位置。
狀態(tài)轉(zhuǎn)化
訪問一個網(wǎng)站,就代表了客戶端和服務(wù)器的一個互動過程。在這個過程中,勢必涉及到數(shù)據(jù)和狀態(tài)的變化?;ヂ?lián)網(wǎng)通信協(xié)議HTTP協(xié)議,是一個無狀態(tài)協(xié)議。這意味著,所有的狀態(tài)都保存在服務(wù)器端。因此,如果客戶端想要操作服務(wù)器,必須通過某種手段,讓服務(wù)器端發(fā)生"狀態(tài)轉(zhuǎn)化"(State Transfer)??蛻舳擞玫降氖侄?,只能是HTTP協(xié)議。具體來說,就是HTTP協(xié)議里面,四個表示操作方式的動詞:GET、POST、PUT、DELETE。它們分別對應(yīng)四種基本操作:GET用來獲取資源,POST用來新建資源(也可以用于更新資源),PUT用來更新資源,DELETE用來刪除資源。綜合上面的解釋,我們總結(jié)一下什么是RESTful架構(gòu):每一個URI代表一種資源;客戶端和服務(wù)器之間,傳遞這種資源的某種表現(xiàn)層;客戶端通過四個HTTP動詞,對服務(wù)器端資源進行操作,實現(xiàn)"表現(xiàn)層狀態(tài)轉(zhuǎn)化"。
RPC
RPC(Remote Procedure Call ) 一種進程間通信方式。允許像調(diào)用本地服務(wù)一樣調(diào)用遠程服務(wù)。RPC框架的主要目標就是讓遠程服務(wù)調(diào)用更簡單、透明。RPC框架負責(zé)屏蔽底層的傳輸方式(TCP或者UDP)、序列化方式(XML/JSON/二進制)和通信細節(jié)。開發(fā)人員在使用的時候只需要了解誰在什么位置提供了什么樣的遠程服務(wù)接口即可,并不需要關(guān)心底層通信細節(jié)和調(diào)用過程。RPC 框架作為架構(gòu)微服務(wù)化的基礎(chǔ)組件,它能大大降低架構(gòu)微服務(wù)化的成本,提高調(diào)用方與服務(wù)提供方的研發(fā)效率,屏蔽跨進程調(diào)用函數(shù)(服務(wù))的各類復(fù)雜細節(jié)。讓調(diào)用方感覺就像調(diào)用本地函數(shù)一樣調(diào)用遠端函數(shù)、讓服務(wù)提供方感覺就像實現(xiàn)一個本地函數(shù)一樣來實現(xiàn)服務(wù)。
CAP原理
- Consistency(一致性):數(shù)據(jù)一致更新,所有數(shù)據(jù)的變化都是同步的
- Availability(可用性):在集群中一部分節(jié)點故障后,集群整體是否還能響應(yīng)客戶端的讀寫請求
- Partition tolerance(分區(qū)容忍性):某個節(jié)點的故障,并不影響整個系統(tǒng)的運行
任何情況下一個分布式架構(gòu)系統(tǒng)下CAP三者只能滿足其中兩個。
springCloud簡述
springcloud是常見的微服務(wù)框架之一,作為spring家族的金字塔尖,它并不是一項新的項目,而是集成市面上大部分的分布式微服務(wù)工程中優(yōu)質(zhì)的項目,具備各種優(yōu)秀的組件使得在一個微服務(wù)工程中程序員可以直接通過springcloud這一個包去調(diào)用各種優(yōu)質(zhì)的jar包。
服務(wù)注冊與發(fā)現(xiàn)
服務(wù)注冊:服務(wù)實例將自身服務(wù)信息注冊到注冊中心。這部分服務(wù)信息包括服務(wù)所在主機IP和提供服務(wù)的Port,以及暴露服務(wù)自身狀態(tài)以及訪問協(xié)議等信息。
服務(wù)發(fā)現(xiàn):服務(wù)實例請求注冊中心獲取所依賴服務(wù)信息。服務(wù)實例通過注冊中心,獲取到注冊到其中的服務(wù)實例的信息,通過這些信息去請求它們提供的服務(wù)。
負載均衡
負載均衡是高可用網(wǎng)絡(luò)基礎(chǔ)架構(gòu)的關(guān)鍵組件,通常用于將工作負載分布到多個服務(wù)器來提高網(wǎng)站、應(yīng)用、數(shù)據(jù)庫或其他服務(wù)的性能和可靠性
熔斷
熔斷這一概念來源于電子工程中的斷路器(Circuit Breaker)。在互聯(lián)網(wǎng)系統(tǒng)中,當(dāng)下游服務(wù)因訪問壓力過大而響應(yīng)變慢或失敗,上游服務(wù)為了保護系統(tǒng)整體的可用性,可以暫時切斷對下游服務(wù)的調(diào)用。這種犧牲局部,保全整體的措施就叫做熔斷。
鏈路追蹤
隨著微服務(wù)架構(gòu)的流行,服務(wù)按照不同的維度進行拆分,一次請求往往需要涉及到多個服務(wù)?;ヂ?lián)網(wǎng)應(yīng)用構(gòu)建在不同的軟件模塊集上,這些軟件模塊,有可能是由不同的團隊開發(fā)、可能使用不同的編程語言來實現(xiàn)、有可能布在了幾千臺服務(wù)器,橫跨多個不同的數(shù)據(jù)中心。因此,就需要對一次請求涉及的多個服務(wù)鏈路進行日志記錄,性能監(jiān)控即鏈路追蹤
API網(wǎng)關(guān)
隨著微服務(wù)的不斷增多,不同的微服務(wù)一般會有不同的網(wǎng)絡(luò)地址,而外部客戶端可能需要調(diào)用多個服務(wù)的接口才能完成一個業(yè)務(wù)需求,如果讓客戶端直接與各個微服務(wù)通信可能出現(xiàn):
- 客戶端需要調(diào)用不同的url地址,增加難度
- 在一定的場景下,存在跨域請求的問題
- 每個微服務(wù)都需要進行單獨的身份認證
針對這些問題,API網(wǎng)關(guān)順勢而生。API網(wǎng)關(guān)直面意思是將所有API調(diào)用統(tǒng)一接入到API網(wǎng)關(guān)層,由網(wǎng)關(guān)層統(tǒng)一接入和輸出。一個網(wǎng)關(guān)的基本功能有:統(tǒng)一接入、安全防護、協(xié)議適配、流量管控、長短鏈接支持、容錯能力。有了網(wǎng)關(guān)之后,各個API服務(wù)提供團隊可以專注于自己的的業(yè)務(wù)邏輯處理,而API網(wǎng)關(guān)更專注于安全、流量、路由等問題。
測試模擬遠程調(diào)用
構(gòu)想一下思路:我們建立同一個父工程remote_call下的兩個子模塊server_a與server_b,要將兩個子模塊跑起來,之后利用server_b模塊去調(diào)用server_a的一個API接口并獲取它的返回信息展示在頁面上,server_b 去通信 server_a 的方法不限,我這里采取RestTemplate這個spring為我們封裝好的Http客戶端工具。
創(chuàng)建父工程remote_call模塊
只需要配置它的pom文件即可,這里我的remote_call模塊的父工程已經(jīng)將用到的SpringBoot依賴都導(dǎo)入且統(tǒng)一管理了。
remote_call
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>spring_cloud</artifactId> <groupId>org.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>remote_call</artifactId> <packaging>pom</packaging> <modules> <module>server_a</module> </modules> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties> </project>
spring_cloud(后面的測試都是要用這個作為父模塊)
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>spring_cloud</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>product</module> <module>eureka</module> <module>order</module> <module>remote_call</module> </modules> <!-- 管理版本統(tǒng)一管理和spring相關(guān)的依賴--> <parent> <artifactId>spring-boot-starter-parent</artifactId> <groupId>org.springframework.boot</groupId> <version>2.6.7</version> </parent> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> <scope>provided</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2021.0.3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <repositories> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>http://repo.spring.io/libs-snapshot-local</url> <snapshots> <enabled>true</enabled> </snapshots> </repository> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>http://repo.spring.io/libs-milestone-local</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> <repository> <id>spring-releases</id> <name>Spring Releases</name> <url>http://repo.spring.io/libs-release-local</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>http://repo.spring.io/libs-snapshot-local</url> <snapshots> <enabled>true</enabled> </snapshots> </pluginRepository> <pluginRepository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>http://repo.spring.io/libs-milestone-local</url> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> </pluginRepositories> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
創(chuàng)建子模塊server_a
1、pom文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>remote_call</artifactId> <groupId>org.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>server_a</artifactId> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties> </project>
2、application.yml
server:
port: 9001
spring:
application:
name: server_a
3、啟動類
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class server_a_ApplicationStarter { public static void main(String[] args) { SpringApplication.run(server_a_ApplicationStarter.class,args); } }
4、controller
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("server_a") public class controller { @RequestMapping(value = "sendMessageToServerB",method = RequestMethod.GET) @ResponseBody public String sendMessage(){ return "hello,server_b! i am server_a"; } }
創(chuàng)建子模塊server_b
1、pom文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>remote_call</artifactId> <groupId>org.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>server_b</artifactId> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties> </project>
2、application.yml
server:
port: 9002
spring:
application:
name: server_b
3、啟動類
@SpringBootApplication public class server_b_ApplicationStarter { @Bean public RestTemplate RestTemplate(){ return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(server_b_ApplicationStarter.class,args); } }
4、controller
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController @RequestMapping("server_b") public class controller { @Autowired private RestTemplate restTemplate; @RequestMapping(value = "remote_server_a",method = RequestMethod.GET) public String remoteCallServerA(){ return restTemplate.getForObject("http://127.0.0.1:9001/server_a/sendMessageToServerB",String.class); } }
4、測試結(jié)果:
訪問http://localhost:9002/server_b/remote_server_a得到結(jié)果如下:
5、總結(jié):
成功實現(xiàn)兩個模塊之間的遠程調(diào)用,那么這種方式我是通過這樣一行代碼實現(xiàn)的:
restTemplate.getForObject("http://127.0.0.1:9001/server_a/sendMessageToServerB",String.class);
我們不難發(fā)現(xiàn)其中的地址信息是硬編碼,后續(xù)如果server_a這個模塊掛掉了,就算它有別的結(jié)點服務(wù),我也訪問不到了,能不能有一個通訊錄記錄這個微服務(wù)的電話呢?因為我們知道分布式架構(gòu)的多結(jié)點特性是它高可用性的體現(xiàn)依賴,那么一個微服務(wù)可能出現(xiàn)在多個主機結(jié)點中運行,掛了一個我們還能夠使用別的結(jié)點中的這一塊微服務(wù)。但是如果沒有一個中間的通訊錄,采取硬編碼的方式,顯然無法實現(xiàn)這樣一個系統(tǒng)的需求。于是,優(yōu)質(zhì)的程序員們設(shè)計出了服務(wù)注冊中心這一個概念。
到此這篇關(guān)于SpringCloud微服務(wù)的調(diào)用與遠程調(diào)用測試示例的文章就介紹到這了,更多相關(guān)SpringCloud微服務(wù)調(diào)用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot整合mybatis-plus實現(xiàn)多表分頁查詢的示例代碼
這篇文章主要介紹了springboot整合mybatis-plus實現(xiàn)多表分頁查詢的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03Spring AOP手動實現(xiàn)簡單動態(tài)代理的代碼
今天小編就為大家分享一篇關(guān)于Spring AOP手動實現(xiàn)簡單動態(tài)代理的代碼,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-03Java 遞歸遍歷實現(xiàn)linux tree命令方式
這篇文章主要介紹了Java 遞歸遍歷實現(xiàn)linux tree命令方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09MyBatis limit分頁設(shè)置的實現(xiàn)
這篇文章主要介紹了MyBatis limit分頁設(shè)置的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04使用遞歸刪除樹形結(jié)構(gòu)的所有子節(jié)點(java和mysql實現(xiàn))
下面小編就為大家?guī)硪黄褂眠f歸刪除樹形結(jié)構(gòu)的所有子節(jié)點(java和mysql實現(xiàn))。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10Spring Boot項目添加外部Jar包以及配置多數(shù)據(jù)源的完整步驟
這篇文章主要給大家介紹了關(guān)于Spring Boot項目添加外部Jar包以及配置多數(shù)據(jù)源的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06聊一聊jdk1.8中的ArrayList 底層數(shù)組是如何擴容的
這篇文章主要介紹了聊一聊jdk1.8中的ArrayList 底層數(shù)組是如何擴容的,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08詳解Java的Hibernat框架中的Map映射與SortedMap映射
這篇文章主要介紹了Java的Hibernat框架中的Map映射與SortedMap映射,Hibernat是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下2015-12-12