SpringCloud 服務注冊和消費實現(xiàn)過程
系統(tǒng)架構
在沒有微服務之前有已經有跨服務調用了,比如ServiceB去調用ServiceA中的服務 , 傳統(tǒng)模式可以直接在ServiceB中寫ServiceA中的服務但是這樣是寫死了的,不夠靈活。
下圖就是傳統(tǒng)的調用
微服務下的跨系統(tǒng)調用應該是這樣的:
此時服務的調用應該是分兩個步驟的:
ServiceB 去服務中心拿到ServiceA的地址,如果ServiceA是單機部署,那么這個地址就只有一個,如果ServiceA是集群是集群環(huán)境部署,那么發(fā)現(xiàn)的地址就是多個。
拿到了ServiceA的地址后,ServiceB再去調用ServiceA的相關服務了。
這樣做其實是有很多好處的,首先互相調用的地址可以不用寫死,需要的時候直接去服務中心獲取,并且服務之間也可以很方便的部署、集群等。
服務注冊與消費搭建
1.首先我們創(chuàng)建一個ServiceRegister的普通maven項目,然后在創(chuàng)建一個Eureka的SpringBoot項目作為子項目
下面是Eureka項目的pom.xml 配置
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
下面是application.yml 配置文件
# 別名 spring: application: name: eureka #端口 server: port: 1111 # eureka config eureka: client: register-with-eureka: false fetch-registry: false
注意 這里配置好了后需要在Eureka這個子項目的啟動類上加入下面這個注解
@EnableEurekaServer
這個注解的意義是代表這個項目成為一個注冊中心
2.創(chuàng)建一個Provider
創(chuàng)建一個叫Provider的SpringBoot項目作為子項目,pom.xml配置
<properties> <spring-cloud.version>Greenwich.SR1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
下面是application.yml 配置文件
# 別名 spring: application: name: provider #端口 server: port: 4001 # provider config eureka: client: service-url: defaultZone: http://localhost:1111/eureka
spring.application.name 是服務的名稱,你可以理解成是別名,其他的服務調用的時候需要使用這個name來調用
server.port 是端口號
eureka.client.service-url.defaultZone 是這個服務需要注冊到服務中心地址,這里需要注意的是,如果服務中心是一個集群,這里也可以只寫服務中心的一個節(jié)點,eureka會自動集群對服務進行同步。
在微服務中,你的項目的pom.xml 中如果存在 spring-cloud-starter-netflix-eureka-client的依賴,并且提供了eureka注冊中心的地址那么會默認注冊到 Eureka Server 中。
然后我們在 provider 中提供一個簡單的服務
@RestController public class SayHelloController { @GetMapping("/sayHello") public String SayHello(String name) { return "sayHello" + name + "!"; } }
這樣我們就創(chuàng)建好我們的服務提供者,并且提供了一個簡單的服務接口了。
3.創(chuàng)建consumer
創(chuàng)建好了服務提供者,那么我們就來創(chuàng)建服務消費者consumer,創(chuàng)建一個SpringBoot的子項目工程 pom依賴如下
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
這個配置和provider 配置幾乎是一樣的,下面是consumer的application.yml 配置文件
# 別名 spring: application: name: consumer #端口 server: port: 4002 # provider config eureka: client: service-url: defaultZone: http://localhost:1111/eureka
唯一變了就是服務的名稱。
配置好了后,我們在consumer的啟動類中添加一個RestTemplate的實例,RestTemplate是Spring提供的一個Http請求工具,下面是這個RestTemplate實例的代碼
@SpringBootApplication public class ConsumerApplication { public static void main(String[] args) { SpringApplication.run(ConsumerApplication.class, args); } @Bean RestTemplate restTemplate() { return new RestTemplate(); } }
然后我們在consumer 中添加一個UserSayHelloController,在這里去調用provider 提供的服務。
@RestController public class SayUserHelloController { @Autowired DiscoveryClient discoveryClient; @Autowired RestTemplate restTemplate; @GetMapping("/sayHello") public String hello(String name) { List<ServiceInstance> list = discoveryClient.getInstances("provider"); ServiceInstance instance = list.get(0); String host = instance.getHost(); int port = instance.getPort(); String s = restTemplate.getForObject("http://" + host + ":" + port + "/hello?name={1}", String.class, name); return s; } }
上面代碼的意思是解釋如下:
首先我們在這個Controller中注入了一個DiscoveryClient ,DiscoveryClient可以從Eureka或者從Consul上根據服務名查詢一個服務的詳細信息,注意DiscoveryClient是下面這個包中的
org.springframework.cloud.client.discovery.DiscoveryClient
@Autowired RestTemplate restTemplate;
RestTemplate 就是Spring 給我們提供用來發(fā)送Http請求的,這個大多數人應該都是知道的。
List<ServiceInstance> list = discoveryClient.getInstances("provider");
discoveryClient.getInstances 就是調用服務的名稱,為什么用List去接受? 那是因為有可能provider 是單機部署 也有可能是集群部署,如果是集群部署的話,那么provider的實例就有多個
ServiceInstance 保存了provider 中 詳細的信息、如主機地址、端口號、實例id等。ServiceInstance是一個接口,它有很多給實現(xiàn)類,我們本次的這個項目使用的是EurekaServiceInstance。
ServiceInstance instance = list.get(0);
因為我們只有一個provider 實例,所以我們就用list.get(0) 來獲取實例了
獲取主機地址
String host = instance.getHost();
獲取端口號
int port = instance.getPort();
RestTemplate 的 getForObject 方法接收三個參數。第一個參數是請求地址,請求地址中的 {1} 表示一個參數占位符,第一個參數 String.class 表示返回的參數類型,第三個參數則是一個第一個占位符的具體值。
String s = restTemplate.getForObject("http://" + host + ":" + port + "/hello?name={1}", String.class, name);
最后我們返回這個s 就完成了consumer的編寫
下面我們依次的啟動Eureka(注冊中心)和 服務提供者(provider) 以及 消費者(consumer)
然后在瀏覽器上輸入:
localhost:4002/sayHello?name=jishu
結果如下圖所示:
這樣我們就順利的從consumer 去調用了provider 的服務了
DiscoveryClient是哪里來的
歸根結底 DiscoveryClient作用就是可以從Eureka 或者Consul 中查詢服務的實例,不過DiscoveryClient就是一個接口而已,但是還是有一個實現(xiàn)類, 這個具體的實現(xiàn)類就是CompositeDiscovery,當我們的微服務啟動的時候,就會在CompositeDiscoveryClientAutoConfiguration類中配置一個CompositeDiscovery的實例,下面這個就是大名鼎鼎的CompositeDiscoveryClientAutoConfiguration的源碼
//這里就是DiscoveryClient的源碼了 @Configuration @AutoConfigureBefore(SimpleDiscoveryClientAutoConfiguration.class) public class CompositeDiscoveryClientAutoConfiguration { //這里返回的是一個實例 @Bean @Primary public CompositeDiscoveryClient compositeDiscoveryClient( List<DiscoveryClient> discoveryClients) { return new CompositeDiscoveryClient(discoveryClients); } }
其實真正調用的是CompositeDiscoveryClient類中的discoveryClients 屬性提供的 DiscoveryClient,而discoveryClients 屬性默認集合中只有一條數據,就是EurekaDiscoveryClient,最終在EurekaDiscoveryClient類中,通過EurekaClient來獲取一個微服務的實例信息了
總結
在不用微服務調用,服務之間的調用是相當繁瑣的,并且地址是寫死了,那么部署的話是非常的不方便,但是我們提供了注冊中心的話,那么我們讓服務注冊到我們的注冊中心中,然后在從注冊中心去獲取我們的服務信息,這樣就有大大的好處,降低了調用的難度。
項目地址
到此這篇關于SpringCloud 服務注冊和消費實現(xiàn)過程的文章就介紹到這了,更多相關SpringCloud 服務注冊 消費內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot集成SpirePDF實現(xiàn)文本替換功能
SpirePDF是一個用于.NET平臺的高級PDF文檔處理庫,它提供了一套完整的API,允許開發(fā)者創(chuàng)建、編輯、轉換、合并、分割和解析PDF文件本文給大家介紹了SpringBoot集成SpirePDF實現(xiàn)文本替換功能,需要的朋友可以參考下2024-09-09Spring init-method與destroy-method屬性的用法解析
這篇文章主要介紹了Spring init-method與destroy-method屬性的用法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08Maven發(fā)布封裝到中央倉庫時候報錯:no default secret key
這篇文章主要介紹了Maven發(fā)布封裝到中央倉庫時候報錯:no default secret key,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-12-12