1. 程式人生 > >三. SpringCloud服務註冊與發現

三. SpringCloud服務註冊與發現

#### 1. Eureka ##### 1.1 Eureka理解 **什麼是服務治理** Spring Cloud封裝了`Netflix`公司開發的Eurkeka模組來實現服務治理 在傳統的`rpc遠端呼叫`框架中,管理每個服務與服務之間依賴關係比較複雜。管理比較複雜服務之間的依賴關係可以實現服務呼叫,負載均衡,容錯等,實現服務發現與註冊。 **什麼是服務註冊與發現** Eureka採用了CS的設計架構,`Eureka Server`作為服務註冊功能的伺服器,它是服務註冊中心,而系統中的其他微服務,使用Eureka的客戶端連線到Eureka Server並維持 **心跳連結** 。這樣系統的維護人員就可以通過Eureka Server來監控系統中各個微服務是否正常執行。 在服務註冊與發現中,有一個註冊中心。當伺服器啟動的時候會把當前自己伺服器的資訊(比如:服務地址、通訊地址等)以別名方式註冊到註冊中心中。另一方(消費者/服務提供者)以該別名的方式去註冊中心上獲取到實際的服務通訊地址,然後再實現本地RPC呼叫。RPC遠端呼叫框架核心設計思想:在於註冊中心,因為使用註冊中心管理每個服務與服務之間的依賴關係(服務治理概念)。在任何RPC遠端框架中,都會有一個註冊中心(存放服務地址相關資訊(介面地址)) 下圖左邊是Eureka系統架構,右邊是Dubbo系統架構 **Eureka包含兩個元件:Eureka Server 和 Eureka Client** - `Eureka Server` 提供服務註冊中心 各個微服務節點通過配置啟動後,會在EurekaServer中進行註冊,這樣EurekaServer中的服務登錄檔中將儲存所有可用服務節點的資訊,服務節點的資訊可以在介面中直觀看到。 - `Eureka Client` 通過註冊中心進行訪問 是一個Java客戶端,用於簡化Eureka Server的互動,客戶端同時也具備一個內建的、使用輪詢(round-robin)負載演算法的負載均衡器。在應用啟動後將會向Eureka Server傳送心跳(預設週期為30秒)。如果Eureka Server在多個心跳週期內沒有接收到某個節點的心跳,Eureka Server將會從服務登錄檔中表把這個服務節點移除(預設90秒) ##### 1.2 單機Eureka構建步驟 **IDEA生成EurekaServer端服務註冊中心** >
類似物業公司 - 建Module cloud-eureka-server7001 - pom.xml ```xml org.springframework.cloud spring-cloud-starter-netflix-eureka-server com.polaris cloud-api-common ${project.version} org.springframework.boot spring-boot-starter-web
org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test
``` > SpringBoot 1x 和 SpringBoot 2x對比 ```xml org.springframework.cloud spring-cloud-starter-eureka org.springframework.cloud spring-cloud-starter-netflix-eureka-server ``` - yml配置檔案 ```yml server: port: 7001 eureka: instance: hostname: localhost # eureka服務端的例項名稱 client: # false表示不向註冊中心註冊自己 register-with-eureka: false # false表示自己端就是註冊中心,我的職責就是維護服務例項,並不需要去檢索服務 fetch-registry: false service-url: # 設定與Eureka Server互動的地址查詢服務和註冊服務都需要依賴這個地址 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ ``` - 主啟動類 ```java @SpringBootApplication @EnableEurekaServer // 宣告我是服務註冊中心 public class EurekaMain7001 { public static void main(String[] args) { SpringApplication.run(EurekaMain.class); } } ``` - 測試 > 執行該Eureka Server主啟動類,訪問 localhost:7001,就會看到下面的服務註冊中心,可以發現目前還沒有任何服務入駐進服務註冊中心中,在應用中顯示:No instances available **EurekaClient端 服務提供者cloud-provider-payment8001修改** - pom.xml新增依賴 ```xml org.springframework.cloud spring-cloud-starter-netflix-eureka-client ``` - yml配置檔案新增配置 ```yml spring: application: name: cloud-payment-service # 入駐Eureka服務註冊中心的服務名稱 eureka: client: # 表示是否將自己註冊進EurekaServer預設為true。 register-with-eureka: true # 是否從EurekaServer抓取已有的註冊資訊,預設為true。 # 單節點無所謂,叢集必須設定為true才能配合ribbon使用負載均衡 fetchRegistry: true service-url: # 單機版 defaultZone: http://localhost:7001/eureka # 入駐的服務註冊中心地址 ``` - 主啟動類添加註解 ```java @SpringBootApplication @EnableEurekaClient public class PaymentMain { public static void main(String[] args) { SpringApplication.run(PaymentMain.class,args); } } ``` - 測試 > 注意先要啟動EurekaServer,因為有了服務註冊中心具體的服務提供者才能後向其中註冊自己的服務 > > 可以發現註冊到服務註冊中心的服務名(圖中藍框)即為我們在yml配置檔案中設定的服務名,下面頁面中出現的 紅字 是Eureka的 自我保護機制 **EurekaClient端 服務消費者cloud-sonsumer-order80修改** > 與服務提供者cloud-provider-payment8001修改差不多,不再贅述 ```yml spring: application: name: cloud-order-service # 入駐Eureka服務註冊中心的服務名稱 eureka: client: # 表示是否將自己註冊進EurekaServer預設為true。 register-with-eureka: true # 是否從EurekaServer抓取已有的註冊資訊,預設為true。 # 單節點無所謂,叢集必須設定為true才能配合ribbon使用負載均衡 fetchRegistry: true service-url: # 單機 defaultZone: http://localhost:7001/eureka ``` **總結** 此時再回看最開始的Eureka系統架構,在服務註冊中心和服務提供者沒有叢集的情況下,7001埠的微服務就對應了服務註冊中心,而該服務不需要向服務註冊中心註冊自己,8001埠的微服務作為服務提供方入住到服務註冊中心,8002埠的微服務作為服務消費方也同樣註冊到服務註冊中心 ##### 1.3 叢集Eureka構建步驟 **叢集Eureka原理** 服務註冊中心Eureka Server中分為 `服務註冊` 和 `服務發現`,服務註冊過程將服務資訊註冊進服務註冊中心,服務發現過程從服務註冊中心上獲取服務資訊,而這個過程的實質就是:將服務名作為key儲存,然後根據value取得服務的呼叫地址。 整個Eureka的過程如下: - 先啟動Eureka註冊中心 - 啟動服務提供者服務 - 服務提供者服務將自身資訊(比如服務地址)以別名方式註冊到Eureka註冊中心 - 消費者服務在需要呼叫介面時,使用服務別名到註冊中心獲取實際的RPC遠端呼叫地址 - 消費者獲得呼叫地址後,底層實際是利用 HttpClient 技術實現遠端呼叫 - 消費者獲得服務地址後會快取字本地JVM記憶體中,預設每間隔30秒更新一次服務呼叫地址 那麼微服務RPC遠端服務呼叫最核心的是什麼呢? 高可用!如果註冊中心只有一個,而這個註冊中心出現了故障那麼整個微服務就直接GG了,整個微服務環境就不可用了,所以應該搭建Eureka註冊中心叢集, 實現 負載均衡 + 故障容錯 那怎麼實現Eureka註冊中心的叢集呢?用一句話總結就是 - 互相註冊,相互守望。如下圖所示,服務註冊中心實現相互註冊讓彼此都知道對方的存在,也就是註冊中心叢集中的每一個註冊中心都知道整個叢集中的其他註冊中心,比如如果有三個註冊服務中心7001,7002,7003,那麼就將7002和7003註冊給7001, 將7002和7001註冊給7003, 將7003和7001註冊給7002, 以此類推,而這些個註冊服務中心 作為一個整體對外看做一個註冊服務中心。 **Eureaka叢集環境構建** > 參考cloud-eureka-server7001新建一個服務註冊中心cloud-eureka-server7002 - 修改pom.xml > copy複製cloud-eureka-server7001的POM檔案即可 - 修改對映配置(域名對映),用不同的埠號來對映同一個地址 > 找到C:\Windows\System32\drivers\etc路徑下的hosts檔案,將其內容修改成如下內容: ```shell # learn-spring-cloud 127.0.0.1 eureka7001.com 127.0.0.1 eureka7002.com ``` - yml配置檔案,7001與7002都修改一下(以前是單機) > 以前是單機版配置,而現在已經有兩個註冊中心可以看做兩臺機器,顯然 hostname 不能再叫localhost > > 更改了服務端的例項名稱後,最重要的是在defaultZone中將自己註冊給其他註冊中心 ```yml server: port: 7001 eureka: instance: hostname: eureka7001.com # eureka服務端的例項名稱 client: register-with-eureka: false fetch-registry: true service-url: # 互相註冊,相互守望 defaultZone: http://eureka7002.com:7002/eureka/ ``` ```yml server: port: 7002 eureka: instance: hostname: eureka7002.com client: register-with-eureka: false fetch-registry: true service-url: # 互相註冊,相互守望 defaultZone: http://eureka7001.com:7001/eureka/ ``` - 測試 > 兩個服務中心已經完成了互相註冊。主頁面DS Replicas下面的資訊就表示是這個Eureka Server相鄰節點且這些節點加上自己互為一個叢集。 - 將服務提供者8001和服務消費者80釋出到2臺Eureka叢集配置中 修改其配置檔案即可,就是將自己的微服務註冊到每一個服務註冊中心裡去,見配置檔案中的defaultZone。 ```yml eureka: client: # 表示是否將自己註冊進EurekaServer預設為true。 register-with-eureka: true # 是否從EurekaServer抓取已有的註冊資訊,預設為true。 # 單節點無所謂,叢集必須設定為true才能配合ribbon使用負載均衡 fetchRegistry: true service-url: # 叢集版 defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka ``` - 測試 **服務提供者叢集環境構建** - 參考8001服務新建8002服務 - pom.xml > 8002和8001的POM檔案一樣 - yml配置檔案 > 將埠改為8002,其他和8001相同,兩個微服務 對外暴露的服務名相同均為cloud-payment-service 從而構成叢集。 ```yml server: port: 8002 spring: application: name: cloud-payment-service datasource: type: com.alibaba.druid.pool.DruidDataSource # 當前資料來源操作型別 driver-class-name: org.gjt.mm.mysql.Driver # mysql驅動包 url: jdbc:mysql://mpolaris.top:3306/cloud-test?useUnicode=true&characterEncoding=utf-8&useSSL=false username: root password: 123456 eureka: client: # 表示是否將自己註冊進EurekaServer預設為true。 register-with-eureka: true # 是否從EurekaServer抓取已有的註冊資訊,預設為true。 # 單節點無所謂,叢集必須設定為true才能配合ribbon使用負載均衡 fetchRegistry: true service-url: # 叢集版 defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka mybatis: mapperLocations: classpath:mapper/*.xml type-aliases-package: com.polaris.springcloud.entities # 所有Entity別名類所在包 ``` - 主啟動類與業務類與8001基本一致 > 主啟動類名字分別為PaymentMain8001與PaymentMain8002 - controller > 修改controller,新增埠號以區分這兩個具體的微服務:讀取配置檔案中設定的埠號。8002的修改同8001。 ```java @RestController @Slf4j @RequestMapping("/payment") public class PaymentController { @Resource private PaymentService paymentService; @Value("${server.port}") private String serverPort; @PostMapping("/save") public CommonResult save(@RequestBody Payment payment) { int result = paymentService.save(payment); log.info("===> result: " + result); if(result > 0) { return new CommonResult(200, "儲存到資料庫成功,埠號:" + serverPort,result); } return new CommonResult(400,"儲存到資料庫失敗",null); } @GetMapping("/get/{id}") public CommonResult save(@PathVariable("id") Long id) { Payment paymentById = paymentService.getPaymentById(id); log.info("===> payment: " + paymentById); if(paymentById != null) { return new CommonResult(200, "查詢成功,埠號:" + serverPort,paymentById); } return new CommonResult(400,"查詢失敗",null); } } ``` - 測試 > 如圖可以看到此時服務註冊中心構成叢集,而相同名字的服務提供方的實際提供者已經出現了兩個,分別是8001和8002,也就是說服務提供方微服務也實現了叢集。 **負載均衡** - 發現問題:通過服務消費者80訪問,只能訪問到服務提供者8001 - 也就是說每次訪問的具體微服務都是8001埠的CLOUD-PAYMENT-SERVICE服務,這明顯是不符合業務邏輯的,原因就是在消費方程式碼中我們將服務訪問地址寫死了,沒有實現負載均衡,這顯然是不對的,所以我們應該讓80訪問服務名而不是具體的服務,即應該將其改為服務提供者 微服務名稱! - 同時在配置檔案中通過 `@LoadBalanced` 註解賦予RestTemplate負載均衡能力,該負載均衡預設為輪詢方式。所以將80服務的配置檔案修改如下: ```java @Configuration public class ApplicationContextConfig { @Bean @LoadBalanced //使用該註解賦予RestTemplate負載均衡的能力 public RestTemplate getRestTemplate() { return new RestTemplate(); } } ``` - 然後重啟80埠,發現每次訪問 `CLOUD-PAYMENT-SERVICE` 服務時,具體的微服務在8001和8002之間進行輪詢切換。 - 當然此時負載均衡我們還沒有用到`Ribbon`,在Ribbon和Eureka整合後,消費者可以直接呼叫服務而不用再關心地址和埠號,且該服務還有負載功能。 **總結** ##### 1.4 actuator微服務資訊完善 **主機名稱:服務名稱修改** 發現問題:在註冊中心顯示的微服務中,我們發現服務名含有主機名稱,這顯然不是我們希望看到的 怎麼能解決這個問題呢,只需要修改服務提供方(8001和8002)的配置檔案,向其中的eureka部分加入`instance例項`即可配置該服務顯示的服務名稱 ```yml instance: instance-id: payment8001 ``` 最終的整體配置檔案如下: ```yml server: port: 8001 spring: application: name: cloud-payment-service datasource: type: com.alibaba.druid.pool.DruidDataSource # 當前資料來源操作型別 driver-class-name: org.gjt.mm.mysql.Driver # mysql驅動包 url: jdbc:mysql://mpolaris.top:3306/cloud-test?useUnicode=true&characterEncoding=utf-8&useSSL=false username: root password: 1234321 eureka: client: # 表示是否將自己註冊進EurekaServer預設為true。 register-with-eureka: true # 是否從EurekaServer抓取已有的註冊資訊,預設為true。 # 單節點無所謂,叢集必須設定為true才能配合ribbon使用負載均衡 fetchRegistry: true service-url: # 叢集版 defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 單機版 # defaultZone: http://localhost:7001/eureka instance: instance-id: payment8001 mybatis: mapperLocations: classpath:mapper/*.xml type-aliases-package: com.polaris.springcloud.entities ``` 8002服務的修改同上,此時再訪問註冊中心,看到的服務具體名稱中就沒有主機名了,而是我們配置好的服務名稱: **訪問資訊有IP資訊提示** 發現問題:我們在滑鼠移動到具體服務時,提示的地址資訊中並沒有服務所在具體主機的IP地址,這在開發中不方便定位具體微服務。 解決方式仍然是通過配置檔案,在配置檔案中向其中的eureka部分加入`優先ip地址`即可配置該服務訪問路徑可以顯示IP地址: ```yml instance: prefer-ip-address: true # 訪問路徑可以顯示IP地址 ``` 最終的配置檔案如下: ```yml eureka: client: # 表示是否將自己註冊進EurekaServer預設為true。 register-with-eureka: true # 是否從EurekaServer抓取已有的註冊資訊,預設為true。 # 單節點無所謂,叢集必須設定為true才能配合ribbon使用負載均衡 fetchRegistry: true service-url: # 叢集版 defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka instance: instance-id: payment8001 prefer-ip-address: true #訪問路徑可以顯示IP地址 ``` ##### 1.5 服務發現Discovery 對於註冊進Eureka服務註冊中心的微服務,可以`通過服務發現來獲取該服務的資訊`。 **修改微服務的Controller** > 向其中注入DiscoveryClient,並編寫相應Controller方法 DiscoveryClient物件中的 `getServices` 方法用於獲取服務列表的資訊,也就是有哪些服務,如cloud-payment-service服務, `getInstances` 方法用於獲取服務列表對應的具體服務例項,如cloud-payment-service服務對應的8001和8002服務。 ```java import org.springframework.cloud.client.discovery.DiscoveryClient; //... @RestController @Slf4j @RequestMapping("/payment") public class PaymentController { //... @Resource private DiscoveryClient discoveryClient; @GetMapping("/discovery") public Object discovery() { //獲取服務列表的資訊 List services = discoveryClient.getServices(); for (String service : services) { log.info("===> service:" + service); } //根據微服務名稱獲取具體服務例項 List instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE"); for (ServiceInstance instance : instances) { log.info("===> " + instance.getServiceId() + "\t" + instance.getHost() + "\t" + instance.getPort() + "\t" + instance.getUri()); } return this.discoveryClient; } //... } ``` **修改主啟動類** 只需要在主啟動類上添加註解`@EnableDiscoveryClient`,修改後的主啟動類: ```java @SpringBootApplication @EnableEurekaClient @EnableDiscoveryClient public class PaymentMain8001 { public static void main(String[] args) { SpringApplication.run(PaymentMain8001.class,args); } } ``` **測試** 訪問地址http://localhost:8001/payment/discovery,我們可以看到獲取的服務資訊,即完成了服務發現: 後臺也對服務列表進行了日誌列印: ##### 1.6 Eureka自我保護(屬於CAP裡面的AP分支) **自我保護機制** 保護模式主要用於一組客戶端和EurekaServer之間存在網路分割槽場景下的保護。一旦進入保護模式,Eureka Server將會嘗試保護其服務登錄檔中的資訊,不再刪除服務登錄檔中的資料,也就是不會登出任何微服務。換句話說就是,某時刻某一個微服務不可用了,Eureka不會立刻清理,而是依舊會對該微服務的資訊進行儲存。 如果在Eureka Server的首頁看到以下提示,說明Eureka進入了保護模式 **產生原因** 為什麼會產生Eureka自我保護機制? => 為了防止 EurekaClient可以正常執行,但是與EurekaServer網路不通情況下,EurekaServer不會立刻將EurekaClient服務剔除。 什麼是自我保護模式? => 預設情況下,如果EurekaServer在一定時間內沒有接收到某個微服務例項的心跳,EurekaServer將會登出該例項(預設90秒)。但是當網路分割槽故障發生(延時、卡頓、擁擠)時,微服務與EurekaServer之前無法正常通訊,以上行為可能變得非常危險 - **因為微服務本身是健康的,只是由於網路問題連結不到EurekaServer,此時本不應該登出這個微服務**。Eureka通過“自我保護模式”來解決這個問題 :當EurekaServer節點在短時間內丟失過多客戶端時(可能發生了網路分割槽故障,網路延時),那麼這個節點就會進入自我保護模式。在自我保護模式中,EurekaServer會保護服務登錄檔中的資訊,不再登出任何服務例項,寧可保留錯誤的服務註冊資訊,也不盲目登出任何可能健康的服務例項。使用自我保護模式,可以讓Eureka叢集更加的健壯、穩定。 **怎麼禁止自我保護** 先在EurekaServer端修改配置檔案即可設定關閉自我保護機制 ```yml eureka: server: # 關閉自我保護機制,保證不可用服務被及時剔除。預設為true開啟 enable-self-preservation: false # 時間間隔,單位ms eviction-interval-time-in-ms: 2000 ``` 然後在EurekaClient端修改配置檔案 ```yml eureka: instance: instance-id: payment8001 # Eureka客戶單向服務端傳送心跳的時間間隔,默然是30秒,這裡改成1秒 lease-renewal-interval-in-seconds: 1 # Eureka服務端在收到最後一次心跳後等待時間上限,默然為90秒,超時將剔除服務,這裡改成2秒 lease-expiration-duration-in-seconds: 2 ``` 這樣就會使EurekaClient客戶端的微服務很快死亡。 #### 2. Zookeeper ##### 2.1 Eureka停止更新 > https://github.com/Netflix/eureka/wiki 我們可以使用SpringCloud整合Zookeeper替代Eureka ##### 2.2 Zookeeper理解 Zookeeper是一個分散式協調工具,可以實現註冊中心功能 **安裝Zookeeper** ```shell # 關閉Linux伺服器防火牆(關閉預設埠2181也行) # 2181 對Client端提供服務的埠 # 3888 選舉Leader # 2888 叢集內的機器通訊使用。(Leader使用此埠) systemctl stop firewalld systemctl status firewalld # 我這裡使用的是zookeeper-3.4.11.tar.gz,解壓即可 # bin目錄下啟動zookeeper伺服器 ./zkServer.sh start # 連線zookeeper客戶端 # 如果是連線同一臺主機上的zk程序,那麼直接執行bin/目錄下的kCli.sh,即可連線上zk。 # 直接執行zkCli.sh命令預設以主機號 127.0.0.1,埠號 2181 來連線zk # 如果要連線不同機器上的zk,可以使用 -server 引數,例如: ./zkCli.sh -server 192.168.0.1:2181 # 啟動報錯? # grep: /usr/local/zookeeper-3.4.11/bin/../conf/zoo.cfg: No such file or directory # 這裡的原因是因為下載下來的zoo.cfg名字是zoo_sample.cfg,只需要改名字即可 mv zoo_sample.cfg zoo.cfg ``` Zookeeper伺服器取代Eureka伺服器,zk作為服務註冊中心 ##### 2.3 服務提供者 **新建cloud-provider-payment8004** **pom.xml** ```xml com.polaris cloud-api-common ${project.version} org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-actuator org.springframework.cloud spring-cloud-starter-zookeeper-discovery org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test ``` **yml配置檔案** ```yml server: # 8004表示註冊到zookeeper伺服器的支付服務提供者埠號 port: 8004 spring: application: # 服務別名 - 註冊zookeeper到註冊中心的名稱 name: cloud-provider-payment cloud: zookeeper: # zookeeper訪問地址 connect-string: mpolaris.top:2181 ``` **主啟動類** ```java @SpringBootApplication //該註解用於向使用consul或zookeeper作為註冊中心時註冊服務 @EnableDiscoveryClient public class PaymentMain8004 { public static void main(String[] args) { SpringApplication.run(PaymentMain8004.class,args); } } ``` **controller** ```java @RestController @Slf4j @RequestMapping("/payment") public class PaymentController { @Value("${server.port}") private String serverPort; @RequestMapping(value = "/zk") public String paymentZk() { return "===> SpringCloud with zookeeper:" + serverPort + "\t" + UUID.randomUUID().toString(); } } ``` **啟動8004註冊進zookeeper** - 啟動zk: zkServer.sh start - 啟動8004後報錯 - why? - 解決zookeeper版本jar包衝突問題 - 排除zk衝突後的新pom.xml ```xml org.springframework.cloud spring-cloud-starter-zookeeper-discovery org.apache.zookeeper zookeeper org.apache.zookeeper zookeeper 3.4.11 ``` **驗證測試1** 訪問 http://localhost:8004/payment/zk **驗證測試2** 獲得json串後用線上工具檢視如下 **思考** 服務節點是臨時節點還是持久節點? => 臨時節點 ##### 2.4 服務消費者 **新建cloud-consumerzk-order80** **pom.xml** ```xml com.polaris cloud-api-common ${project.version} org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-starter-zookeeper-discovery org.apache.zookeeper zookeeper org.apache.zookeeper zookeeper 3.4.11 org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test ``` **yml配置檔案** ```yml server: port: 80 spring: application: # 服務別名 name: cloud-consumer-order cloud: zookeeper: # 註冊到zookeeper地址 connect-string: mpolaris.top:2181 ``` **主啟動類** ```java @SpringBootApplication @EnableDiscoveryClient public class OrderZkMain80 { public static void main(String[] args) { SpringApplication.run(OrderZkMain80.class, args); } } ``` **業務類** 配置類注入RestTemplate ```java @Configuration public class ApplicationContextConfig { @Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); } } ``` controller ```java @RestController @Slf4j @RequestMapping("/consumer") public class OrderZkController { public static final String INVOKE_URL = "http://cloud-provider-payment"; @Resource private RestTemplate restTemplate; /** * http://localhost/consumer/payment/zk * @return */ @GetMapping("/payment/zk") public String paymentInfo() { return restTemplate.getForObject(INVOKE_URL + "/payment/zk", String.class); } } ``` **測試驗證** > 訪問地址 http://localhost/consumer/payment/zk #### 3. Consul ##### 3.1 理解 **什麼是Consul** Consul是一套開源的`分散式服務發現`和`配置管理`系統,由HashiCorp公司用`Go語言`開發。提供了微服務系統中的 `服務治理` 、`配置中心` 、`控制匯流排 `等功能。這些功能中的每一個都可以根據單獨需要使用,也可以一起使用以構建全方位的服務網路,總之Consul提供了一種完整的服務網路解決方案。其官方介紹見[Consul官網](https://www.consul.io/intro)。 它具有很多優點。包括`基於raft協議`,比較簡潔;支援`健康檢查`,同時支援`HTTP`和`DNS`協議,支援跨資料中心的`WAN叢集`,提供圖形介面,跨平臺,支援Linux/Mac/Windows。 **Consul作用** - `服務發現Service Discovery`:提供HTTP和DNS兩種發現方式。 - `健康監測Health Checking`:支援多張方式,HTTP、TCP、Docker、Shell指令碼定製化 - `KV儲存`:Key、Value的儲存方式 - `多資料中心`:Consul支援多資料中心 - `視覺化Web介面` ##### 3.2 安裝並執行Consul 在[官網下載](https://www.consul.io/downloads)Windows的64位版本Consul後下載的是zip壓縮包,將壓縮包解壓后里面只有一個`consul.exe`檔案。在該路徑下雙擊其exe檔案就可以執行Consul,進入cmd命令列執行,輸入以下命令檢視Consul的版本號資訊,我用的是1.7.3版本: ```shell consul --version ``` 當然也可以不用有點low的雙擊Consul啟動,可以在命令列中用開發模式啟動,輸入以下命令 ```shell consul agent -dev ``` 啟動後我們訪問 localhost:8500 ,就可以看到Consul和Eureka一樣,有一個前端視覺化Web介面。這樣的話Consul服務註冊中心就已經啟動了,且執行在8500埠 ##### 3.3 服務提供者 **新建cloud-provider-consul-payment8006** **pom.xml** 在Eureka的服務提供方中我們引入瞭如下的依賴: ```xml org.springframework.cloud spring-cloud-starter-netflix-eureka-client ``` 而我們現在服務註冊中心用的不再是Eureka而是Consul,只需要被Eureka Client的依賴更改為如下依賴,這樣引入了讓Consul服務註冊中心發現自己微服務的相關jar包。 ```xml org.springframework.cloud spring-cloud-starter-consul-discovery ``` **yml配置檔案** ```yml server: port: 8006 # consul服務埠號 spring: application: name: consul-provider-payment # consul註冊中心地址 cloud: consul: host: localhost port: 8500 discovery: #hostname: 127.0.0.1 service-name: ${spring.application.name} ``` **主啟動類** ```java @SpringBootApplication @EnableDiscoveryClient public class PaymentMain8006 { public static void main(String[] args) { SpringApplication.run(PaymentMain8006.class); } } ``` **業務類Controller** ```java @RestController @Slf4j @RequestMapping("/payment") public class PaymentController { @Value("${server.port}") private String serverPort; @RequestMapping("/consul") public String paymentConsul() { return "springcloud with consul: " + serverPort + "\t" + UUID.randomUUID().toString(); } } ``` **測試** 經過以上配置,我們會在Consul服務註冊中心中發現入駐的 consul-provider-payment 服務 ##### 3.4 服務消費者 **新建cloud-consumer-consul-order80** **pom.xml** 為了可以將自己註冊到Consul服務註冊中心,和服務提供方一樣,仍然是引入如下依賴: ```xml org.springframework.cloud spring-cloud-starter-consul-discovery ``` **yml配置檔案** 和服務提供方几乎完全相同,只需要修改下自己的埠號和自己的服務名稱 ```yml # consul服務埠號 server: port: 80 spring: application: name: cloud-consumer-order # consul註冊中心地址 cloud: consul: host: localhost port: 8500 discovery: # hostname: 127.0.0.1 service-name: ${spring.application.name} ``` **主啟動類** ```java @SpringBootApplication @EnableDiscoveryClient //用於向使用Consul或Zookeeper作為註冊中心時註冊服務 public class OrderConsulMain80 { public static void main(String[] args) { SpringApplication.run(OrderConsulMain80.class); } } ``` **配置類注入RestTemplate** ```java @Configuration public class ApplicationContextConfig { @Bean @LoadBalanced //使用該註解賦予RestTemplate負載均衡的能力 public RestTemplate getRestTemplate() { return new RestTemplate(); } } ``` **業務類Controller** ```java @RestController @Slf4j public class OrderConsulController { //要訪問的服務提供方的微服務名稱 public static final String INVOKE_URL = "http://consul-provider-payment"; @Resource private RestTemplate restTemplate; @GetMapping("/consumer/payment/consul") public String paymentInfo() { return restTemplate.getForObject(INVOKE_URL + "/payment/consul", String.class); } } ``` **測試** 將服務消費方微服務啟動後,在Consul服務註冊中心我們可以發現同時有了提供者和消費者 服務提供方自測是沒有問題的,下面我們通過服務消費方來訪問提供方服務,發現也可以正常訪問 #### 4. 三者異同 ##### 4.1 比較 | 元件名 | 編寫語言 | CAP | 服務健康檢查 | 對外暴露介面 | SpringCloud整合 | | --------- | -------- | ---- | ------------ | ------------ | --------------- | | Eureka | Java | AP | 可配支援 | HTTP | 已整合 | | Consul | Go | CP | 支援 | HTTP/DNS | 已整合 | | Zookeeper | Java | CP | 支援 | 客戶端 | 已整合 | ##### 4.2 什麼是CAP > CAP理論:首先我們要知道CAP對應的都是什麼。 | C | A | P | | ----------- | --------- | ------------------- | | Consistency | Available | Partition tolerance | | 強一致性 | 可用性 | 分割槽容錯性 | 所謂**CAP原則**又稱CAP定理,指的是在一個分散式系統中,一致性、可用性、分割槽容錯性。CAP 原則指的是這三個要素 最多隻能同時實現兩點,不可能三者兼顧。在分散式架構中,P永遠要求被保證,所以當前的分散式架構只有AP和CP兩種。因此根據CAP原理將NoSQL資料庫分成了滿足CA原則、滿足CP原則和滿足AP原則三大類: - `CA`:單點叢集,滿足一致性、可用性的系統,通長在可擴充套件性上不太強大。 - `CP`:滿足一致性、分許容錯性的系統,通常效能不是特別高。 - `AP`:滿足可用性、分割槽容錯性的系統,通常可能對一致性要求低一些。

相關推薦

. SpringCloud服務註冊發現

#### 1. Eureka ##### 1.1 Eureka理解 **什麼是服務治理** Spring Cloud封裝了`Netflix`公司開發的Eurkeka模組來實現服務治理 在傳統的`rpc遠端呼叫`框架中,管理每個服務與服務之間依賴關係比較複雜。管理比較複雜服務之間的依賴關係可以實現服務呼

springcloud服務註冊發現(二)

com 1.8 負載 private host wired 負載均衡 sco .class Spring Cloud Eureka是Spring Cloud Netflix項目下的服務治理模塊。而Spring Cloud Netflix項目是Spring Cloud的子項目

Spring Cloud(服務註冊發現

Spring Cloud(三)服務註冊與發現 案例中有三個角色:服務註冊中心、服務提供者、服務消費者,其中服務註冊中心就是eureka單機版啟動既可,流程是首先啟動註冊中心,服務提供者生產服務並註冊到服務中心中,消費者從服務中心中獲取服務並執行。 這裡新建兩個spring boo

SpringCloud服務註冊發現Eureka

一、建立Eureka Server作為服務註冊中心 二、新增pom.xml檔案依賴 <!--eureka server --> <dependency> <groupId>org.springframework.cloud&l

springcloud~服務註冊發現Eureka的使用

服務註冊與發現是微服務裡的概念,也是一個基本的元件,負責服務元件的認證,即實現『你是誰』的功能,在服務註冊與發現裡,存在兩種模式,即服務端發現和客戶端發現,咱們今天說的eureka屬於客戶端發現! 下面概念來自文章:https://blog.csdn.net/forezp/article/details/7

SpringCloud 服務註冊發現Eureka

個人學習SpringCloud系列 Eureka篇 Github Link: https://github.com/panjianlong13/SpringBoot-SpringCloud/tree/master/spring-cloud-eureka Spring Cloud簡介

SpringCloud-Eureka服務註冊發現之開發小技巧()

1.如何為服務起別名,即修改下面紅色部分 解決方案:在yml配置檔案中加入以下資訊 測試: 2.如何設定服務端的ip地址 解決方案: 在yml配置檔案中加入以下資訊

SpringCloud)Eureka服務註冊發現《2》(actuatorEureka自我保護)

1、actuator與註冊微服務資訊完善 1.1、主機名稱:服務名稱修改 1.當前問題:含有主機名或主機ip。 2.修改microservice-provider-dept-8001yml檔案: eureka:   client:&nbs

SpringCloud服務註冊服務發現之Eureka

sco utf-8 info 都沒有 轉移 .org 只需要 1.4 AI   Eureka是SpringCloud Netflix的子模塊之一,用於雲端的服務發現,服務定位,實現雲端中間層服務發現和故障轉移。服務註冊與發現對於微服務系統來說十分的重要,有了服務註冊與發現,

springcloud服務系列之服務註冊發現組件Eureka

顯示 功能 depend mod 其他 瀏覽器 使用 空間 之間 一、Eurake的簡介二、使用Eureka進行服務的註冊消費1、創建一個服務註冊中心2、創建服務的提供者3、創建服務的消費者總結 一、Eurake的簡介 今天我們來介紹下springcloud的核心組件Eur

SpringCloud(二) 服務註冊發現Eureka

圖片 borde 引入 vat red images .cn epo round 1.eureka是幹什麽的? 上篇說了,微服務之間需要互相之間通信,那麽通信就需要各種網絡信息,我們可以通過使用硬編碼的方式來進行通信,但是這種方式

SpringCloud(3)---Eureka服務註冊發現

sta 檢索 消費 能夠 曾經 pri local cloud ava Eureka服務註冊與發現 一、Eureka概述 1、Eureka特點 (1) Eureka是一個基於REST的服務,用於定位服務,以實現雲端中間層服務發現和故障轉移。 (2)

SpringCloud服務註冊發現Eureka

Eureka是Netflix開源的一款提供服務註冊和發現的產品,它提供了完整的Service Registry(註冊登記)和Service Discovery(發現)實現。也是springcloud體系中最重要最核心的元件之一。   服務中心:   服務中心又稱註冊中心,管理各種服務功能包括服務的註冊、發

4--SpringCloud搭建高可用的服務註冊中心 1--SpringCloud服務註冊發現Eureka 1--SpringCloud服務註冊發現Eureka 1--SpringCloud服務註冊發現Eureka

  我們已經介紹了1--SpringCloud的服務註冊與發現Eureka,其中,主要演示瞭如何構建和啟動服務註冊中心Eureka Server,以及如何將服務註冊到Eureka Server中,但是在之前的示例中,這個服務註冊中心是單點的,顯然這並不適合應用於線上生產環境,那麼下面在前文的基礎上,我們來看看

SpringCloud進擊 | 一淺出:服務註冊發現(Eureka)【Finchley版本】

1.前言 Spring Cloud 已經幫我們實現了服務註冊中心,我們只需要很簡單的幾個步驟就可以完成。關於理論知識,我想大家都已經有不同程度上的瞭解和認識,這裡,我們最後再進行總結。本系列 Spring Cloud 介紹基於 Spring Boot 2.0.5 版本和 Spring C

springcloud (一) Eureka服務註冊發現

http://blog.didispace.com/springcloud1/   Spring Cloud簡介 Spring Cloud是一個基於Spring Boot實現的雲應用開發工具,它為基於JVM的雲應用開發中的配置管理、服務發現、斷路器、智慧路由、微代理、控制匯流排

SpringCloud-Eureka服務註冊發現(二)

背景: 傳統的服務之間的呼叫是客戶端直接向服務端傳送請求,在單機服務時代,服務並不是很多時,服務之間直接呼叫並不存在很大問題,但隨著微服務架構的興起,服務之間的呼叫越來越頻繁,再像以前一樣服務間直接呼叫,耦合性太大,並不利用維護服務,所以Eureka 應運而生,它將所有服務納入到自己的服務中心

SpringCloud-Eureka服務註冊發現之叢集配置(五)

1.構建多個Eureka服務端,具體步驟參考單機版的Eureka服務端構建步驟 2.修改每個Eureka服務端yml檔案,將對外暴露的註冊介面地址由一個變成多 個,自身的暴露地址除外

SpringCloud-Eureka服務註冊發現之自我保護機制(四)

當我們進行SpringCloud微服務開發的時候,有可能會出現如下的一些紅色提示資訊。這個是Eureka的自我保護機制。 自我保護機制 :預設情況下,如果Eureka Server在一定時間內沒有接收到某個微服務例項的心跳,Eureka S

SpringCloud入門 ――服務註冊發現(Eureka)

  前言 Oracle轉讓Java,各種動態語言的曝光率上升,Java工程師的未來在哪裡?我覺得Spring Cloud讓未來有無限可能。拖了半年之久的Spring Cloud學習就從今天開始了。中文教材不多,而且大多都是簡單的離散的資訊,想要找到企業級的一體化解決方案很少。不過,