SpringCloud筆記(一)服務註冊與服務發現
目錄
2.2 註冊服務提供者springcloud-producer
2.3 服務消費者 SpringCloud-Consumer
1、Spring Cloud概述
Spring Cloud是一個基於Spring Boot實現的微服務架構開發工具。它為微服務架構中涉及的配置管理、服務治理、斷路器、只能路由、微代理、控制匯流排、全域性鎖、決策競選、分散式會話和叢集狀態管理等操作提供了一種簡單的開發方式。
Spring Cloud包含了多個子專案:
Spring Cloud Config:配置管理工具,支援使用Git儲存配置內容,可以使用它搭建分散式配置中心。
Spring Cloud Netflix:核心元件,對多個Netflix OSS開源套件進行整合。
Eureka:服務治理元件,包含服務註冊中心、服務註冊與發現機制的實現。
Hystrix:容錯管理元件,實現斷路器模式,幫助服務依賴出現的延遲和未故障提供強大的容錯能力。
Ribbon:客戶端負載均衡的服務呼叫元件。
Feign:基於Ribbon和Hystrix的宣告式服務呼叫元件
Zuul:閘道器元件,提供智慧路由、訪問過濾等功能。
Spring Cloud Bus:時間、訊息匯流排,用於傳播叢集中的狀態變化或事件,以觸發後續的處理,比如用來動態重新整理配置等。
Spring Cloud Consul:服務發現與配置管理工具。
Spring Cloud Stream:通過Redis、Rabbit或者Kafka實現的訊息微服務,通過簡單點的宣告式模型來發送和接收訊息。
Spring Cloud Sleuth: Spring Cloud應用的分散式跟蹤實現,可以完美整合Zipkin。
Spring Cloud Starters:Spring Cloud的基礎元件,它是基於Spring Boot風格專案的基礎依賴模組。
……
2、環境搭建
在此部落格中使用Eureka作為註冊中心,實現服務的註冊與發現,專案結構如下:
2.1 搭建註冊中心eureka-server
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.lzj</groupId>
<artifactId>euraker-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>euraker-server</name>
<description>this is a register server</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.M3</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</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>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
application.yml
#埠號
server:
port: 8100
eureka:
instance:
#註冊到本地地址
hostname: 127.0.0.1
client:
serviceUrl:
#客戶端訪問的路徑
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
#自己就是註冊中心,不需要註冊自己
register-with-eureka: false
#自己就是註冊中心,不需要檢索自己
fetch-registry: false
啟動類:
@SpringBootApplication
@EnableEurekaServer //開啟eurekaServer
public class EurakerServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurakerServerApplication.class, args);
}
}
此時將註冊中心執行起來,測試搭建是否成功。
通過訪問:http://localhost:8100 看到如下介面,則表示搭建成功,不過此時並沒有註冊任何服務。
2.2 註冊服務提供者springcloud-producer
pom.xml
<!--pom檔案中主要部分:netflix-eureka-client-->
<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>
application.yml
spring:
application:
name: app-producer
server:
port: 8000
eureka:
client:
service-url:
defaultZone: http://localhost:8100/eureka/
register-with-eureka: true
fetch-registry: true
Controller:
@RestController
public class ProducerController {
@Value("${server.port}")
private String port;
@RequestMapping("/getMember")
public String getMember() {
return "this is a member service" + port;
}
}
啟動類:
@SpringBootApplication
@EnableEurekaClient //啟動會員服務
public class SpringcloudProducerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudProducerApplication.class, args);
}
}
當SpringCloud Producer啟動後,會在註冊中心看到有該服務名稱。
此時可以通過瀏覽器直接訪問該服務:http://localhost:8000/getMember
2.3 服務消費者 SpringCloud-Consumer
現在有了註冊中心,有了服務的提供者,現在再啟動一個服務消費者,在Spring Cloud-Consumer中通過RPC遠端呼叫技術呼叫SpringCloud-Producer中的服務(一個服務既可以當做提供者又可以當做消費者)。
pom.xml
<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>
application.yml
spring:
application:
name: app-consumer
server:
port: 8001
eureka:
client:
service-url:
defaultZone: http://localhost:8100/eureka/ #註冊中心地址
register-with-eureka: true
fetch-registry: true
Controller:
@RestController
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/getorder")
public String getOrder() {
// order 使用rpc 遠端呼叫技術 呼叫 會員服務restTemplate
String memberUrl = "http://app-producer/getMember";
String result = restTemplate.getForObject(memberUrl, String.class);
System.out.println("會員服務呼叫訂單服務,result:" + result);
return result;
}
}
啟動類:
@SpringBootApplication
@EnableEurekaClient
public class SpringcloudConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudConsumerApplication.class, args);
}
@Bean
@LoadBalanced //讓RestTemplate在請求時擁有客戶端負載均衡的能力
public RestTemplate restTemplate() {
return new RestTemplate();
}
//不加@LoadBalanced 將出現無法解析app-producer地址的錯誤:java.net.UnknownHostException
}
在進行遠端呼叫時,採用了RestTemplate方式,這種方式底層採用的是Ribbon本地負載均衡,(還有一個Feign遠端呼叫技術更常用,在以後的部落格中會介紹到Feign客戶端呼叫方式)。當使用RestTemplate時,需要自己注入一個bean物件,並且在該物件上面加上@LoadBalance開啟本地負載均衡,否則會造成服務名稱無法解析的錯誤:java.net.UnknownHostException
當兩個服務都啟動時,此時註冊中心資訊如下:
現在訪問springcloud-consumet的getOrder介面,以此進行遠端呼叫。
瀏覽器訪問:http://localhost:8001/getorder
說明底層通過RestTemplate完成了遠端呼叫。
3、負載均衡測試
修改springcloud-producer的埠號為8002,重新再啟動一個,模擬一個服務的叢集。
可以看到APP-PRODUCER有兩個服務例項,分別執行在8000埠和8002埠。
當訪問http://localhost:8001/getorder時,Ribbon底層會自動實現負載均衡。
4、服務註冊與發現原理
a、首先啟動eureka註冊中心
b、啟動springcloud-producer或springcloud-consumer後,會將服務別名、服務所在的地址和埠號以鍵值對的形式註冊到eureka註冊中心,如:
key:APP-PRODUCER value:127.0.0.1:8000, 127.0.0.1:8002
並且每隔一段時間傳送心跳包維持連線
c、當通過springcloud-consumer進行遠端呼叫時,首先通過服務別名(APP-PRODUCER)去註冊中心查詢對應的鍵,獲取對應的值(value:127.0.0.1:8000, 127.0.0.1:8002),當獲取到值的時候,首先快取在本地JVM中,並且快取的值預設每隔30s重新整理一次。之後通過本地負載均衡選取一個服務,底層通過HttpClient技術進行遠端呼叫。
專案原始碼:https://github.com/liuzhoujian/springcloud-eureka