一篇文章概括Spring Cloud微服務教程
現在流行的是Spring Cloud基於NetFlix解決方案提供的解決方案。那麼讓我們來演示如何使用它。原文來自tomask79,點選標題見原文!
1. 註冊中心
基於Spring Cloud的MicroServices的Hearth是Eureka Server。也稱為Discovery Server。因為該伺服器儲存有關您的系統可以在其執行位置,健康狀況和其他方面使用的所有微服務的資訊。很明顯,在生產中,這個伺服器需要具有高可用性。使用Spring Cloud,您可以透過將EnableEurekaServer註釋新增到Spring Boot應用程式的啟動類來建立此伺服器。
@SpringBootApplication @EnableEurekaServer public class SpringMicroserviceRegistryApplication { public static void main(String args) { SpringApplication.run(SpringMicroserviceRegistryApplication.class, args); } } |
只需要這一行程式碼就可以啟動eureka伺服器了,預設在http://localhost:8761可訪問註冊中心,可以在application.properties/yaml中配置埠等特定配置:
server.port=9761 eureka.client.register-with-eureka=false eureka.client.fetch-registry=false logging.level.com.netflix.eureka=OFF logging.level.com.netflix.discovery=OFF |
在除錯環境可以配置關閉一些引數:
- eureka.client.register-with-eureka和eureka.client.fetch-registr引數設定為false表示註冊伺服器不向自己註冊服務。
- 對logging.level.com.netflix.eureka和logging.level.com.netflix.discovery的設定OFF,關閉了“沒有用於註冊伺服器的副本節點”的警告資訊。
微服務註冊到Discovery Server
現在讓我們實現我們的微服務。首先,Spring Boot應用程式需要知道在哪裡註冊您的微服務:
spring.application.name=personsService eureka.client.serviceUrl.defaultZone=http://localhost:9761/eureka |
還要注意微服務名為“ personsService ”。現在編碼微服務,是一個簡單的REST控制器返回一些JSON:
@RestController public class PersonsController { @RequestMapping("/persons") public Persons getPersonById() { final Persons persons = new Persons(); final Person person = new Person(); person.setName("Tomas"); person.setSurname("Kloucek"); person.setDepartment("Programmer"); persons.getPersons().add(person); return persons; } } |
Spring Cloud MicroService的客戶端
現在你可以訪問http://localhost:8080/persons ,也可以使用使用RestTemplate 直接訪問這個微服務, 但這樣做是愚蠢的。更聰明的是讓您的客戶端透過MicroService id(在我的情況下是personService)首先訪問註冊伺服器,詢問Ribbon loadbalancer負載平衡器來獲取微服務的URL,然後呼叫該服務。檢視客戶端程式碼:
首先,我們需要讓我們的客戶端成為發現伺服器客戶端。因此EnableDiscoveryClient註釋。(Spring Boot 2以後可不需要此註釋)
@SpringBootApplication @EnableDiscoveryClient public class SpringMicroserviceClientApplication { public static void main(String args) { SpringApplication.run(SpringMicroserviceClientApplication.class, args); } } |
然後我們需要讓Ribbon loadbalancer透過提供服務ID來選擇微服務的一個例項。
@Component public class MicroServiceClient implements CommandLineRunner { @Autowired private LoadBalancerClient loadBalancer; @Override public void run(String... arg0) throws Exception { final RestTemplate restTemplate = new RestTemplate(); final ServiceInstance serviceInstance = loadBalancer.choose("personsService"); if (serviceInstance != null) { System.out.println("Invoking instance at URL: "+serviceInstance.getUri()); System.out.println( restTemplate.getForObject(serviceInstance.getUri()+"/persons", String.class)); } else { System.out.println("Didn't find any running instance of personsService at DiscoveryServer!"); } } } |
LoadBalancerClient將在Discovery伺服器上選擇註冊的一個正在執行的微服務例項!(banq注:通常需要透過Feign實現JSON物件轉換的方式訪問遠端微服務)
執行演示
下載演示
執行發現伺服器
- mvn clean install(在帶有pom.xml的spring-microservice-registry目錄下)
- java -jar target / demo-0.0.1-SNAPSHOT.war
- 訪問http:// localhost:9761
執行MicroService
- mvn clean install(在帶有pom.xml的spring-microservice-service目錄下)
- java -jar target/demo-0.0.1-SNAPSHOT.war
- 現在重新重新整理http:// localhost:9761頁面,您應該看到MicroService已在發現伺服器上註冊。
執行客戶端
- mvn clean install(在帶有pom.xml的spring-microservice-client目錄下)
- java -jar target/demo-0.0.1-SNAPSHOT.war
2. 在Spring Cloud 微服務中使用斷路器Circuit-Breaker
在編寫微服務時,如果無法訪問特定微服務,需要告訴微服務要執行什麼操作。也就是說當被訪問的微服務不可用時,有幾個選項:
- 呼叫另一個備份微服務。
- 返回一些快取的結果。
- 返回不可用的頁面...
用於實現此目的的廣泛使用的模式是斷路器模式。在你繼續閱讀之前,一定要閱讀Martin Fowler定義的這個描述。
無論如何,簡而言之。斷路器的作用是將MicroService呼叫方法包裝在代理監控MicroService呼叫失敗中。如果失敗將達到某個閾值,則所有其他呼叫將以異常結束,或者如果您使用備份計劃呼叫來定義... Spring Cloud具有出色的實現,稱為Hystrix。
使用Hystrix斷路器
使用之前的personsService這個微服務,使用以下規則向呼叫者新增容錯邏輯:
每20秒(metrics.rollingStats.timeInMilliseconds)從6個請求(收集統計資料circuitBreaker.requestVolumeThreshold),如果所有的人都用崩潰(截至circuitBreaker.errorThresholdPercentage)然後重定向呼叫到後備邏輯。每隔5秒嘗試一次這個微服務是否可用(circuitBreaker.sleepWindowInMilliseconds)。
提到的MicroService呼叫元件將如下所示:
@Component public class MicroServiceInvoker { @Autowired private LoadBalancerClient loadBalancer; @HystrixCommand(fallbackMethod = "invokeMicroServiceFallback", commandProperties = { @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "100"), @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "20000"), @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "6"), @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000") } ) public void invokeMicroService() { final RestTemplate restTemplate = new RestTemplate(); final ServiceInstance serviceInstance = loadBalancer.choose("personsService"); if (serviceInstance != null) { System.out.println("Invoking instance at URL: "+serviceInstance.getUri()); System.out.println("Result :"+ restTemplate.getForObject(serviceInstance.getUri()+"/persons", String.class)); } else { System.out.println("Service is down..."); throw new IllegalStateException("PersonsService is not running!"); } } public void invokeMicroServiceFallback() { System.out.println("Waiting for circuit-breaker to close again..."); } } |
測試斷路器
下載原始碼
執行發現伺服器:
mvn clean install (in the spring-microservice-registry directory with pom.xml) java -jar target/demo-0.0.1-SNAPSHOT.war |
執行微服務
mvn clean install (in the spring-microservice-service directory with pom.xml) java -jar target/demo-0.0.1-SNAPSHOT.war |
在http://localhost:9761確認微服務已經註冊。
執行另外一個微服務,它是上面微服務客戶端,呼叫者:
mvn clean install (in the spring-microservice-client directory with pom.xml) java -jar target/demo-0.0.1-SNAPSHOT.war |
啟動客戶端你會看到:
Invocation number :16 Invoking instance at URL: http://192.168.1.112:8080 Result :{"persons":[{"name":"Tomas","surname":"Kloucek","department":"Programmer"}]} Invocation number :17 Invoking instance at URL: http://192.168.1.112:8080 Result :{"persons":[{"name":"Tomas","surname":"Kloucek","department":"Programmer"}]} Invocation number :18 Invoking instance at URL: http://192.168.1.112:8080 Result :{"persons":[{"name":"Tomas","surname":"Kloucek","department":"Programmer"}]} Invocation number :19 |
關閉personService微服務 20秒, 你會看到輸出:
Invocation number :18 Invoking instance at URL: http://192.168.1.112:8080 Waiting for circuit-breaker to close again... Invocation number :19 Invoking instance at URL: http://192.168.1.112:8080 Waiting for circuit-breaker to close again... |
一會兒看到輸出:
Invocation number :78 Waiting for circuit-breaker to close again... Invocation number :79 Waiting for circuit-breaker to close again... |
每隔5秒改變到:
Invoking instance at URL: http://192.168.1.112:8080 Waiting for circuit-breaker to close again... |
當Hystrix測試微服務例項是否再次正常執行時,在你執行微服務之後,斷路器應該是關閉的,微服務客戶端在啟動執行時就能發現這個情況...總而言之,斷路器有以下狀態:
- OPEN:微服務呼叫時發生異常,呼叫回退邏輯
- CLOSED:沒有錯誤。正確呼叫MicroService。
- HALF-OPENED:當circuitBreakerSleepWindowInMilliseconds時間發生時,Hystrix將允許請求呼叫微服務來測試它是否處於活動狀態=半開狀態。
3. 使用Netlix Feign作為呼叫微服務
之前展示了一個微服務客戶端如何在Ribbon的幫助下使用RestTemplate呼叫另外一個微服務的:
@Component public class MicroServiceClient implements CommandLineRunner { @Autowired private LoadBalancerClient loadBalancer; @Override public void run(String... arg0) throws Exception { final RestTemplate restTemplate = new RestTemplate(); final ServiceInstance serviceInstance = loadBalancer.choose("personsService"); if (serviceInstance != null) { System.out.println("Invoking instance at URL: "+serviceInstance.getUri()); System.out.println( restTemplate.getForObject(serviceInstance.getUri()+"/persons", String.class)); } else { System.out.println("Didn't find any running instance of personsService at DiscoveryServer!"); } } } |
老實說,這裡有太多的樣板程式碼,在大型系統中會經常重複。這是引入Feign的理由:
Feign為您帶來以下好處:
- 呼叫程式碼是在執行時根據註釋建立的。
- 無需使用任何負載平衡器來呼叫其他微服務。
- 微服務呼叫系統更易於維護。
使用Feign的先前程式碼將如下所示:
遠端微服務呼叫返回的是原始JSON,那麼大多數時候你都想要的是Java POJO。因此,讓我們建立另一個呼叫相同MicroService的Feign客戶端宣告:
@Component @FeignClient("personsService") public interface JacksonMicroServiceFeignClient { @RequestMapping(method = RequestMethod.GET, value = "/persons") ClientPersonsTO invokePersonsMicroService(); } |
只要呼叫上面這個介面就可以實現遠端微服務的呼叫,比如:
@Autowired private JacksonMicroServiceFeignClient jacksonMicroServiceFeignClient; . . final ClientPersonsTO clientPersonsTO = jacksonMicroServiceFeignClient. invokePersonsMicroService(); |
而遠端微服務的程式碼是這個樣子:
@RestController public class PersonsController { @RequestMapping("/persons") public Persons getPersonById() { final Persons persons = new Persons(); final Person person = new Person(); person.setName("Tomas"); person.setSurname("Kloucek"); person.setDepartment("Programmer"); persons.getPersons().add(person); return persons; } } |
遠端微服務返回的是Persons物件,這個Persons是透過轉換成JSON到達你的客戶端的,你的Feign客戶端將這個JSON字串又轉換為ClientPersonsTO,兩者名稱可以不同,但是內部資料結構應該相同額。
將Feign與Hystrix結合起來
在具有maven依賴關係的類路徑中包含Hystrix:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> |
當然你也應該包含進Feign等元件,這些配置可以透過Idea等Spring 導航選擇相應元件後自動生成pom.xml配置。
從現在開始,Feign將用Hystrix封裝每個MS微服務呼叫。您可以透過以下設定禁用它:feign.hystrix.enabled = false應用程式屬性。您的Feign客戶端介面方法也可以返回HystrixCommand以允許呼叫者使用帶有Observable Java的反應模式。那麼讓我們建立Feign Hystrix客戶端:
@Component @FeignClient(value = "personsService", fallback = MicroServiceHystrixFallback.class) public interface HystrixMicroServiceFeignClient { @RequestMapping(method = RequestMethod.GET, value = "/persons") ClientPersonsTO getPersonsWithHystrix(); } |
如果斷路器開啟,我在這裡定義了後備也就是快速失敗或回退返回。順便說一句,當返回HystrixCommand時,還不支援fallback 。現在,使用archaius配置Feign Hystrix,它使用方法名作為command鍵,因此application.properties中的配置將是:
server.port=8888 eureka.client.serviceUrl.defaultZone=http://localhost:9761/eureka hystrix.command.getPersonsWithHystrix.fallback.enabled=true hystrix.command.getPersonsWithHystrix.metrics.rollingStats.timeInMilliseconds=35000 hystrix.command.getPersonsWithHystrix.circuitBreaker.sleepWindowInMilliseconds=5000 hystrix.command.getPersonsWithHystrix.circuitBreaker.requestVolumeThreshold=6 hystrix.command.getPersonsWithHystrix.circuitBreaker.errorThresholdPercentage=100 hystrix.command.getPersonsWithHystrix.execution.isolation.strategy=THREAD |
測試
下載原始碼
執行Eureka:
mvn clean install (in the spring-microservice-registry directory with pom.xml) java -jar target/demo-0.0.1-SNAPSHOT.war |
執行被呼叫微服務:
mvn clean install (in the spring-microservice-service directory with pom.xml) java -jar target/demo-0.0.1-SNAPSHOT.war verify with http://localhost:9761 that MicroService is registered. |
執行呼叫微服務:
mvn clean install (in the spring-microservice-client directory with pom.xml) java -jar target/demo-0.0.1-SNAPSHOT.war [0-2] |
點選標題見原文。
下一篇:Spring Cloud配置和閘道器代理
更多:Spring Cloud微服務雲應用教程
相關文章
- Spring Cloud微服務運營配置教程SpringCloud微服務
- spring cloud 微服務實戰SpringCloud微服務
- spring cloud 和 阿里微服務spring cloud AlibabaSpringCloud阿里微服務
- 微服務Spring Cloud17_Spring Cloud概述3微服務SpringCloud
- Spring Cloud 微服務視訊教程-百度雲SpringCloud微服務
- Spring Cloud教程 第九彈 微服務閘道器ZuulSpringCloud微服務Zuul
- spring cloud分散式微服務:Spring Cloud ConfigSpringCloud分散式微服務
- 微服務:spring-cloud-archaius 起步微服務SpringCloudAI
- [譯] JWT 與 Spring Cloud 微服務JWTSpringCloud微服務
- spring cloud微服務分散式雲架構Spring Cloud ZuulSpringCloud微服務分散式架構Zuul
- spring cloud微服務分散式雲架構-Spring Cloud BusSpringCloud微服務分散式架構
- 微服務 | Spring Cloud(一):從單體SSM 到 Spring Cloud微服務SpringCloudSSM
- Spring Cloud構建微服務架構-spring cloud服務監控中心SpringCloud微服務架構
- Spring Cloud 微服務開發系列整理SpringCloud微服務
- Spring Cloud Stream微服務訊息框架SpringCloud微服務框架
- 微服務閘道器 Spring Cloud Gateway微服務SpringCloudGateway
- 微服務 Spring cloud 各元件介紹微服務SpringCloud元件
- Spring Cloud Alibaba微服務實戰SpringCloud微服務
- 微服務架構:Dubbo VS Spring Cloud微服務架構SpringCloud
- spring cloud微服務架構設計SpringCloud微服務架構
- Spring Cloud 微服務的那點事SpringCloud微服務
- Spring Cloud 微服務架構進階SpringCloud微服務架構
- 理解Spring Cloud微服務框架核心元件SpringCloud微服務框架元件
- 部署Azure Spring Cloud微服務應用SpringCloud微服務
- 基於Spring Cloud的微服務落地SpringCloud微服務
- 【docker&spring cloud】微服務化改造DockerSpringCloud微服務
- spring cloud微服務分散式雲架構 - Spring Cloud簡介SpringCloud微服務分散式架構
- java版電子商務spring cloud分散式微服務-大話Spring CloudJavaSpringCloud分散式微服務
- spring cloud微服務分散式雲架構-Spring Cloud NetflixSpringCloud微服務分散式架構
- (一)spring cloud微服務分散式雲架構-Spring Cloud簡介SpringCloud微服務分散式架構
- (一)spring cloud微服務分散式雲架構 - Spring Cloud簡介SpringCloud微服務分散式架構
- Spring Cloud-honghu Cloud分散式微服務雲系統SpringCloud分散式微服務
- Spring Cloud微服務(一):公共模組的搭建SpringCloud微服務
- Spring Cloud微服務基礎元件實戰SpringCloud微服務元件
- 微服務Spring Cloud Alibaba之我見微服務SpringCloud
- Spring Cloud 微服務架構解決方案SpringCloud微服務架構
- 學習Spring Cloud與微服務之路三SpringCloud微服務
- Spring Cloud微服務分散式雲架構SpringCloud微服務分散式架構