1. 程式人生 > 實用技巧 >SpringCloud學習筆記【五】:Zookeeper代替Eureka實現服務註冊與發現

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,並且以標籤的形式詳細區分每個步驟,這個系列文章也會同步更新。