SpringCloud 服務(wù)注冊和消費實現(xiàn)過程
系統(tǒng)架構(gòu)
在沒有微服務(wù)之前有已經(jīng)有跨服務(wù)調(diào)用了,比如ServiceB去調(diào)用ServiceA中的服務(wù) , 傳統(tǒng)模式可以直接在ServiceB中寫ServiceA中的服務(wù)但是這樣是寫死了的,不夠靈活。
下圖就是傳統(tǒng)的調(diào)用

微服務(wù)下的跨系統(tǒng)調(diào)用應(yīng)該是這樣的:

此時服務(wù)的調(diào)用應(yīng)該是分兩個步驟的:
ServiceB 去服務(wù)中心拿到ServiceA的地址,如果ServiceA是單機部署,那么這個地址就只有一個,如果ServiceA是集群是集群環(huán)境部署,那么發(fā)現(xiàn)的地址就是多個。
拿到了ServiceA的地址后,ServiceB再去調(diào)用ServiceA的相關(guān)服務(wù)了。
這樣做其實是有很多好處的,首先互相調(diào)用的地址可以不用寫死,需要的時候直接去服務(wù)中心獲取,并且服務(wù)之間也可以很方便的部署、集群等。
服務(wù)注冊與消費搭建
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 是服務(wù)的名稱,你可以理解成是別名,其他的服務(wù)調(diào)用的時候需要使用這個name來調(diào)用
server.port 是端口號
eureka.client.service-url.defaultZone 是這個服務(wù)需要注冊到服務(wù)中心地址,這里需要注意的是,如果服務(wù)中心是一個集群,這里也可以只寫服務(wù)中心的一個節(jié)點,eureka會自動集群對服務(wù)進行同步。
在微服務(wù)中,你的項目的pom.xml 中如果存在 spring-cloud-starter-netflix-eureka-client的依賴,并且提供了eureka注冊中心的地址那么會默認(rèn)注冊到 Eureka Server 中。
然后我們在 provider 中提供一個簡單的服務(wù)
@RestController
public class SayHelloController {
@GetMapping("/sayHello")
public String SayHello(String name) {
return "sayHello" + name + "!";
}
}
這樣我們就創(chuàng)建好我們的服務(wù)提供者,并且提供了一個簡單的服務(wù)接口了。
3.創(chuàng)建consumer
創(chuàng)建好了服務(wù)提供者,那么我們就來創(chuàng)建服務(wù)消費者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
唯一變了就是服務(wù)的名稱。
配置好了后,我們在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,在這里去調(diào)用provider 提供的服務(wù)。
@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上根據(jù)服務(wù)名查詢一個服務(wù)的詳細(xì)信息,注意DiscoveryClient是下面這個包中的
org.springframework.cloud.client.discovery.DiscoveryClient
@Autowired RestTemplate restTemplate;
RestTemplate 就是Spring 給我們提供用來發(fā)送Http請求的,這個大多數(shù)人應(yīng)該都是知道的。
List<ServiceInstance> list = discoveryClient.getInstances("provider");
discoveryClient.getInstances 就是調(diào)用服務(wù)的名稱,為什么用List去接受? 那是因為有可能provider 是單機部署 也有可能是集群部署,如果是集群部署的話,那么provider的實例就有多個
ServiceInstance 保存了provider 中 詳細(xì)的信息、如主機地址、端口號、實例id等。ServiceInstance是一個接口,它有很多給實現(xiàn)類,我們本次的這個項目使用的是EurekaServiceInstance。
ServiceInstance instance = list.get(0);
因為我們只有一個provider 實例,所以我們就用list.get(0) 來獲取實例了
獲取主機地址
String host = instance.getHost();
獲取端口號
int port = instance.getPort();
RestTemplate 的 getForObject 方法接收三個參數(shù)。第一個參數(shù)是請求地址,請求地址中的 {1} 表示一個參數(shù)占位符,第一個參數(shù) String.class 表示返回的參數(shù)類型,第三個參數(shù)則是一個第一個占位符的具體值。
String s = restTemplate.getForObject("http://" + host + ":" + port + "/hello?name={1}", String.class, name);
最后我們返回這個s 就完成了consumer的編寫
下面我們依次的啟動Eureka(注冊中心)和 服務(wù)提供者(provider) 以及 消費者(consumer)
然后在瀏覽器上輸入:
localhost:4002/sayHello?name=jishu
結(jié)果如下圖所示:

這樣我們就順利的從consumer 去調(diào)用了provider 的服務(wù)了
DiscoveryClient是哪里來的
歸根結(jié)底 DiscoveryClient作用就是可以從Eureka 或者Consul 中查詢服務(wù)的實例,不過DiscoveryClient就是一個接口而已,但是還是有一個實現(xiàn)類, 這個具體的實現(xiàn)類就是CompositeDiscovery,當(dāng)我們的微服務(wù)啟動的時候,就會在CompositeDiscoveryClientAutoConfiguration類中配置一個CompositeDiscovery的實例,下面這個就是大名鼎鼎的CompositeDiscoveryClientAutoConfiguration的源碼
//這里就是DiscoveryClient的源碼了
@Configuration
@AutoConfigureBefore(SimpleDiscoveryClientAutoConfiguration.class)
public class CompositeDiscoveryClientAutoConfiguration {
//這里返回的是一個實例
@Bean
@Primary
public CompositeDiscoveryClient compositeDiscoveryClient(
List<DiscoveryClient> discoveryClients) {
return new CompositeDiscoveryClient(discoveryClients);
}
}
其實真正調(diào)用的是CompositeDiscoveryClient類中的discoveryClients 屬性提供的 DiscoveryClient,而discoveryClients 屬性默認(rèn)集合中只有一條數(shù)據(jù),就是EurekaDiscoveryClient,最終在EurekaDiscoveryClient類中,通過EurekaClient來獲取一個微服務(wù)的實例信息了
總結(jié)
在不用微服務(wù)調(diào)用,服務(wù)之間的調(diào)用是相當(dāng)繁瑣的,并且地址是寫死了,那么部署的話是非常的不方便,但是我們提供了注冊中心的話,那么我們讓服務(wù)注冊到我們的注冊中心中,然后在從注冊中心去獲取我們的服務(wù)信息,這樣就有大大的好處,降低了調(diào)用的難度。
項目地址
到此這篇關(guān)于SpringCloud 服務(wù)注冊和消費實現(xiàn)過程的文章就介紹到這了,更多相關(guān)SpringCloud 服務(wù)注冊 消費內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot使用ApplicationEvent&Listener完成業(yè)務(wù)解耦
這篇文章主要介紹了SpringBoot使用ApplicationEvent&Listener完成業(yè)務(wù)解耦示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05
Java 線程池核心參數(shù)、執(zhí)行流程與實戰(zhàn)建議全解析
主要介紹了 Java 線程池:核心參數(shù)、執(zhí)行流程與實戰(zhàn)建議,我將用最通俗的方式帶你搞懂 Java 線程池,從構(gòu)造函數(shù)開始,講透執(zhí)行機制、參數(shù)配置,再結(jié)合我在真實項目中的使用經(jīng)驗,總結(jié)出一套實戰(zhàn)建議,需要的朋友可以參考下2025-04-04
Java web實現(xiàn)賬號單一登錄,防止同一賬號重復(fù)登錄(踢人效果)
這篇文章主要介紹了Java web實現(xiàn)賬號單一登錄,防止同一賬號重復(fù)登錄,有點類似于qq登錄踢人效果,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2019-10-10
Spring?Retry?實現(xiàn)樂觀鎖重試實踐記錄
本文介紹了在秒殺商品SKU表中使用樂觀鎖和MybatisPlus配置樂觀鎖的方法,并分析了測試環(huán)境和生產(chǎn)環(huán)境的隔離級別對樂觀鎖的影響,通過簡單驗證,展示了在可重復(fù)讀和讀已提交隔離級別下的不同行為,感興趣的朋友一起看看吧2025-03-03
Spring SpringMVC,Spring整合MyBatis 事務(wù)配置的詳細(xì)流程
這篇文章給大家介紹SSM整合詳細(xì)流程步驟 Spring SpringMVC,Spring整合MyBatis 事務(wù)配置,本文通過實例圖文相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2020-10-10
Java?數(shù)據(jù)結(jié)構(gòu)與算法系列精講之貪心算法
我們可能在好多地方都會聽到貪心算法這一概念,并且它的算法思想也比較簡單就是說算法只保證局部最優(yōu),進而達到全局最優(yōu)。但我們實際編程的過程中用的并不是很多,究其原因可能是貪心算法使用的條件比較苛刻,所要解決的問題必須滿足貪心選擇性質(zhì)2022-02-02

