SpringCloud學習筆記【五】:Zookeeper代替Eureka實現服務註冊與發現
Zookeeper的服務註冊與發現
安裝Zookeeper環境
Zookeeper的3.4.9
Windows和Linux環境皆可,這裡介紹一下使用Docker啟動Zookeeper。
直接看這篇文章就好了:Docker安裝Zookeeper以及Zk常用命令
建立Zk服務提供者模組
引入依賴
<!--SpringBoot整合zookeeper客戶端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency>
配置yml
#8004表示註冊到zookeeper伺服器的支付服務提供者埠號 server: port: 8004 #服務別名----註冊zookeeper到註冊中心名稱 spring: application: name: cloud-provider-payment cloud: zookeeper: connect-string: 121.199.16.31:2181
添加註解@EnableDiscoveryClient
/** * @author summerday * * //@EnableDiscoveryClient該註解用於向使用consul或者zookeeper作為註冊中心時註冊服務 */ @SpringBootApplication @EnableDiscoveryClient public class Payment8004Application { public static void main(String[] args) { SpringApplication.run(Payment8004Application.class, args); } }
編寫Controller
@RestController
@Slf4j
public class PaymentController {
@Value("${server.port}")
private String serverPort;
@GetMapping("/payment/zk")
public String paymentZk() {
return "spring cloud with zookeeper: " + serverPort + "\t" + UUID.randomUUID().toString();
}
}
我們希望將這個模組註冊進Zookeeper註冊中心。
測試,發現jar包衝突
啟動程式,我們發現程式直接報錯,並且戛然而止。
經過排查,可以發現是jar包發生了衝突,原來我們引入的依賴自帶著一個zookeeper-3.5.3-beta.jar
,而我們的zookeeper是3.4.9的。
解決jar包衝突
zookeeper版本
方法一、解除安裝現有的zookeeper,安裝3.5.3版本的即可
當然,這個方法可以解決衝突,但是好好地把已安裝的zk解除安裝了,不夠妥當。
方法二、排除jar包依賴,引入3.4.9包
<!--SpringBoot整合zookeeper客戶端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<!--先排除自帶的zookeeper3.5.3-->
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--新增zookeeper3.4.9版本-->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.9</version>
</dependency>
日誌框架多繫結
如果這樣你以為就成功了,非也,因為還有存在衝突的情況,如日誌衝突:
SLF4J: Class path contains multiple SLF4J bindings.
同理,我們排除掉slf4j-log4j12
就行了。
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.9</version>
<!--排除slf4j-log4j12-->
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
繼續測試
在zookeeper中執行命令:
[zk: localhost:2181(CONNECTED) 7] ls / # 檢視根目錄下的節點
[services, zookeeper]
[zk: localhost:2181(CONNECTED) 8] ls /services # 檢視/services目錄下的節點,成功入駐
[cloud-provider-payment] # yml中配置的spring.application.name
[zk: localhost:2181(CONNECTED) 9] ls /services/cloud-provider-payment
[b780fc19-2823-4420-9937-3959de87720b] # 流水號
[zk: localhost:2181(CONNECTED) 10] get /services/cloud-provider-payment/b780fc19-2823-4420-9937-3959de87720b # 獲取znode結構
{"name":"cloud-provider-payment","id":"b780fc19-2823-4420-9937-3959de87720b","address":"DESKTOP-QFK0MBG","port":8004,"sslPort":null,"payload":{"@class":"org.springframework.cloud.zookeeper.discovery.ZookeeperInstance","id":"application-1","name":"cloud-provider-payment","metadata":{"instance_status":"UP"}},"registrationTimeUTC":1605873188009,"serviceType":"DYNAMIC","uriSpec":{"parts":[{"value":"scheme","variable":true},{"value":"://","variable":false},{"value":"address","variable":true},{"value":":","variable":false},{"value":"port","variable":true}]}}
cZxid = 0x31
ctime = Fri Nov 20 11:53:09 GMT 2020
mZxid = 0x31
mtime = Fri Nov 20 11:53:09 GMT 2020
pZxid = 0x31
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x175e40811430010
dataLength = 558
numChildren = 0
此時,我們的服務已經成功註冊進zookeeper註冊中心。
Zookeeper註冊的服務是臨時節點
我們直到Eureka預設是開啟自我保護機制的:寧可同時保留錯誤的服務註冊資訊,也不盲目登出任何可能健康的服務例項。
而Zookeeper不同,一旦你服務停止,在下一次心跳的時候,服務會被剔除,服務可以再次連線,但流水號會發生改變。
建立Zk服務消費者模組
pom,yml,啟動類註解差不太多,這裡就不贅述了,感興趣可以檢視倉庫程式碼:https://gitee.com/tqbx/spring-cloud-learning,以標籤的形式詳細區分每個步驟。
@RestController
@Slf4j
public class OrderZKController
{
public static final String INVOKE_URL = "http://cloud-provider-payment";
@Resource
private RestTemplate restTemplate;
@LoadBalanced // 不加該註解,會導致:java.net.UnknownHostException: cloud-provider-payment
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
@GetMapping(value = "/consumer/payment/zk")
public String paymentInfo()
{
return restTemplate.getForObject(INVOKE_URL+"/payment/zk",String.class);
}
}
當我們同時啟動消費者和提供者,zookeeper中就會註冊進兩個service。消費者訪問localhost/consumer/payment/zk
,將會呼叫提供者的介面,完成需求。
原始碼下載
本系列文章為《尚矽谷SpringCloud教程》的學習筆記【版本稍微有些不同,後續遇到bug再做相關說明】,主要做一個長期的記錄,為以後學習的同學提供示例,程式碼同步更新到Gitee:https://gitee.com/tqbx/spring-cloud-learning,並且以標籤的形式詳細區分每個步驟,這個系列文章也會同步更新。