微服務註冊中心之Eureka、Zookeeper、Consul

在微服務架構中,註冊中心是必不可少的一部分,其主要實現了服務治理功能,本文主要講述如何使用Eureka、Zookeeper、Consul來作爲註冊中心,來實現服務治理功能。

1.Eureka

服務發現是基於微服務的體系結構的關鍵部分之一。嘗試手動配置每個客戶端或某種形式的約定可能很難做到,而且很可能出問題。Eureka是Netflix服務發現服務器和客戶端。可以將服務器配置和部署爲高可用性,每個服務器將註冊服務的狀態複製到其他服務器。

1.1 使用Eureka編寫註冊中心服務

創建一個maven項目,項目名爲eureka-server,在pom文件添加Eureka依賴。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.alias</groupId>
        <artifactId>springcloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>com.alias</groupId>
    <artifactId>eureka-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka-server</name>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>
	
    ......
</project>

項目啓動類添加@EnableEurekaServer註解

package com.alias.eureka.server;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }

}

編輯配置文件application,yml

spring:
  application:
    name: eureka-server
server:
  port: 8761

eureka:
  server:
    #自我保護機制關閉
    enable-self-preservation: false
  client:
  	# 由於該應用爲註冊中心,所以設置爲false,就是不向註冊中心註冊自己
    register-with-eureka: false
    # 由於註冊中心是維護服務實例,並不需要檢索服務,所以設置爲false
    fetch-registry: false
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  instance:
    hostname: localhost

接下來我們運行EurekaServerApplication就可以啓動我們的註冊中心了,我們在application.yml配置文件配置的端口是8761,在瀏覽器訪問http://localhost:8761便可以看到Eureka提供的Web控制檯。

在這裏插入圖片描述

1.2 編寫服務提供者

創建一個maven項目alias-user,在pom文件中添加相關依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.alias</groupId>
        <artifactId>springcloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>com.alias</groupId>
    <artifactId>alias-user</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>alias-pay</name>
    <description>Demo project for Spring Boot</description>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-eureka-client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

編寫項目啓動類,添加@EnableEurekaClient註解

@SpringBootApplication
@EnableDiscoveryClient
public class AliasOrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(AliasOrderApplication.class, args);
    }

}

創建application.yml文件

server:
  port: 8083
#eureka註冊中心配置  eureka.client.service-url.defaultZone地址是我們註冊中心的地址。
eureka:
  client:
    service-url:
     defaultZone: http://localhost:8761/eureka/
spring:
  application:
    name: alias-order


添加一個controller類,提供給其他服務調用

@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private OrderService orderService;

    @GetMapping("/getOrder")
    public OrderVO getOrder(String userNo) {
        return orderService.getOrder(userNo);
    }
}

/**
 * @author alias
 * @date 2020/3/16 16:26
 */
public interface OrderService {

    /**
     * 通過用戶id獲取用戶
     * @param orderNo
     * @return
     */
    OrderVO getOrder(String orderNo);
}

@Service
public class OrderServiceImpl implements OrderService {

    @Value("${server.port}")
    private String port;

    @Override
    public OrderVO getOrder(String orderNo) {
        OrderVO orderVO = new OrderVO();
        orderVO.setOrderNo(orderNo);
        orderVO.setOrderName("order服務端口:" + port);
        return orderVO;
    }
}

啓動AliasOrderApplication服務,可以在控制檯看到註冊到註冊中心的日誌:

DiscoveryClient_ALIAS-ORDER/H37BVIYLDSGMOGU:alias-order:8083 - registration status: 204

在eureka的web控制檯我們也可以看到新註冊的服務信息

eureka服務註冊信息

1.3 編寫服務消費者

創建服務消費者maven項目alias-pay,pom文件依賴添加和配置文件內容和服務提供者alias-order差不多,只是配置文件的端口和應用名修改了。

這裏使用RestTemlpate調用遠程http服務。這裏我們添加RestTemplate配置。

@Configuration
public class WebConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

便希望controller類,在業務中調用order服務接口(此處只是模擬調用,至於業務合不合邏輯就不管了,我們只看如果調用其他服務就行了)

@RestController
@RequestMapping("/pay")
public class PayController {

    @Autowired
    private PayService payService;

    @GetMapping("/payOrder")
    public String payOrder(String orderNo, double payMoney) {
        return payService.payOrder(orderNo, payMoney);
    }
}

public interface PayService {

    /**
     * 支付訂單
     * @param orderNo
     * @param payMoney
     * @return
     */
    String payOrder(String orderNo, double payMoney);
}

@Service
public class PayServiceImpl implements PayService {

    private static final String INVOKE_URL = "http://ALIAS-ORDER/";
    @Value("${server.port}")
    private String port;

    @Autowired
    private RestTemplate restTemplate;

    @Override
    public String payOrder(String orderNo, double payMoney) {
        OrderVO orderVO = restTemplate.getForObject(INVOKE_URL + "order/getOrder?orderNo=12020222", OrderVO.class);

        return "支付訂單:" + orderVO.getOrderName() + ",服務端口:" + port;
    }
}

執行AliasOrderApplication啓動消費服務,調用/pay/payOrder接口,看到返回支付訂單:order服務端口:8083,服務端口:8081說明調用成功。

至於Eureka健康檢查、高可用部署等功能,可自行查閱官方文檔

2.Zookeeper

ZooKeeper是用於分佈式應用程序的分佈式,開放源代碼協調服務。它公開了一組簡單的原語,分佈式應用程序可以基於這些原語來實現用於同步,配置維護以及組和命名的更高級別的服務。它的設計易於編程,並使用了按照文件系統熟悉的目錄樹結構樣式的數據模型

2.1 安裝Zookeeper

請參閱安裝文檔以獲取有關如何安裝Zookeeper的說明。

2.2 使用Zookeeper進行服務發現

服務發現是基於微服務的體系結構的關鍵原則之一。嘗試手動配置每個客戶端或某種形式的約定可能很困難並且很容易出問題。Curator(Zookeeper的Java庫)通過Service Discovery Extension提供服務發現。Spring Cloud Zookeeper使用此擴展進行服務註冊和發現。

我們基於上面的項目,修改項目的pom文件依賴、還有配置。

  		<!--註釋掉spring-cloud-starter-netflix-eureka-client的依賴,添加spring-cloud-starter-zookeeper-discovery依賴-->
		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-eureka-client -->
<!--        <dependency>-->
<!--            <groupId>org.springframework.cloud</groupId>-->
<!--            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>-->
<!--        </dependency>-->

application.yml配置文件修改

#eureka註冊中心配置
#eureka:
#  client:
#    service-url:
#      defaultZone: http://localhost:8761/eureka/

spring:
  application:
    name: alias-pay
    #zookeeper註冊中心配置
    cloud:
      zookeeper:
        connect-string: localhost:2181

項目啓動類去掉@EnableEurekaClient註解,使用@EnableDiscoveryClient註解。

啓動項目,我這裏使用zkUI查看註冊到zookeeper的節點信息,至於zkUI安裝可參考zookeeper可視化工具zkui搭建

kui微服務節點

同樣的,我們按照上面的方式修改alias-order配置,啓動項目,查看zk節點信息。

zkui多個服務啓動節點查看

調用http://localhost:8081/pay/payOrder接口,看到返回支付訂單:order服務端口:8083,服務端口:8081說明調用成功。

注意,在pay服務使用RestTemplate調用order服務的時候,我們使用的是服務名來發現服務,這裏註冊到zookeeper的服務名是小寫。自己編寫調用時,要注意服務實例名稱,否則調用接口時會找不到服務而報錯

3.Consul

Consul是一個服務網格解決方案,是一個一個分佈式的,高度可用的系統。它提供了一個功能齊全的控制平面,提供服務發現、健康檢查、鍵值存儲、安全服務通信、多數據中心等功能。

3.1 安裝Consul

安裝指南可以參考官方文檔,也可以查看本人寫的Linux上安裝Consul

3.2 啓動Consul代理

這裏用開發模式下啓動consul代理。

$ consul agent -dev
==> Starting Consul agent...
           Version: 'v1.7.2'
           Node ID: '58b5abd3-4071-f5d5-bf6d-d87e0e7fb079'
         Node name: 'alias'
        Datacenter: 'dc1' (Segment: '<all>')
            Server: true (Bootstrap: false)
       Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, gRPC: 8502, DNS: 8600)
      Cluster Addr: 127.0.0.1 (LAN: 8301, WAN: 8302)
           Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false, Auto-Encrypt-TLS: false

==> Log data will now stream in as it occurs:

    2020-03-18T20:14:44.575+0800 [DEBUG] agent: Using random ID as node ID: id=58b5abd3-4071-f5d5-bf6d-d87e0e7fb079
    2020-03-18T20:14:44.575+0800 [DEBUG] agent.tlsutil: Update: version=1
    2020-03-18T20:14:44.576+0800 [DEBUG] agent.tlsutil: OutgoingRPCWrapper: version=1
    2020-03-18T20:14:44.576+0800 [INFO]  agent.server.raft: initial configuration: index=1 servers="[{Suffrage:Voter ID:58b5abd3-4071-f5d5-bf6d-d87e0e7fb079 Address:127.0.0.1:8300}]"
    2020-03-18T20:14:44.576+0800 [INFO]  agent.server.serf.wan: serf: EventMemberJoin: alias.dc1 127.0.0.1
    2020-03-18T20:14:44.576+0800 [INFO]  agent.server.serf.lan: serf: EventMemberJoin: alias 127.0.0.1
    2020-03-18T20:14:44.577+0800 [INFO]  agent: Started DNS server: address=127.0.0.1:8600 network=udp
    2020-03-18T20:14:44.577+0800 [INFO]  agent.server.raft: entering follower state: follower="Node at 127.0.0.1:8300 [Follower]" leader=
    2020-03-18T20:14:44.579+0800 [INFO]  agent.server: Adding LAN server: server="alias (Addr: tcp/127.0.0.1:8300) (DC: dc1)"
    2020-03-18T20:14:44.579+0800 [INFO]  agent.server: Handled event for server in area: event=member-join server=alias.dc1 area=wan
    2020-03-18T20:14:44.580+0800 [INFO]  agent: Started DNS server: address=127.0.0.1:8600 network=tcp
    2020-03-18T20:14:44.581+0800 [INFO]  agent: Started HTTP server: address=127.0.0.1:8500 network=tcp
    2020-03-18T20:14:44.581+0800 [INFO]  agent: started state syncer
==> Consul agent running!
    2020-03-18T20:14:44.581+0800 [INFO]  agent: Started gRPC server: address=127.0.0.1:8502 network=tcp
    2020-03-18T20:14:44.614+0800 [WARN]  agent.server.raft: heartbeat timeout reached, starting election: last-leader=
    2020-03-18T20:14:44.614+0800 [INFO]  agent.server.raft: entering candidate state: node="Node at 127.0.0.1:8300 [Candidate]" term=2
    2020-03-18T20:14:44.615+0800 [DEBUG] agent.server.raft: votes: needed=1
    2020-03-18T20:14:44.615+0800 [DEBUG] agent.server.raft: vote granted: from=58b5abd3-4071-f5d5-bf6d-d87e0e7fb079 term=2 tally=1
    2020-03-18T20:14:44.615+0800 [INFO]  agent.server.raft: election won: tally=1
    2020-03-18T20:14:44.615+0800 [INFO]  agent.server.raft: entering leader state: leader="Node at 127.0.0.1:8300 [Leader]"
    2020-03-18T20:14:44.615+0800 [INFO]  agent.server: cluster leadership acquired

3.3 Consul註冊發現服務

服務發現是基於微服務的體系結構的關鍵原則之一。嘗試手動配置每個客戶端或某種形式的約定可能非常困難,也很容易出問題。Consul通過HTTP API和DNS提供服務發現服務。Spring Cloud Consul利用HTTP API進行服務註冊和發現。這並不妨礙非spring雲應用程序利用DNS接口。Consul代理服務器運行在一個集羣中,該集羣通過gossip協議進行通信,並使用Raft consensus協議。

我們基於上面的項目進行修改,修改項目的pom文件依賴

<dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-consul-discovery -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

        <!--        &lt;!&ndash; https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-zookeeper-discovery &ndash;&gt;-->
<!--        <dependency>-->
<!--            <groupId>org.springframework.cloud</groupId>-->
<!--            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>-->
<!--        </dependency>-->

        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-eureka-client -->
<!--        <dependency>-->
<!--            <groupId>org.springframework.cloud</groupId>-->
<!--            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>-->
<!--        </dependency>-->

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-actuator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

application.yml配置文件修改

#eureka註冊中心配置
#eureka:
#  client:
#    service-url:
#      defaultZone: http://localhost:8761/eureka/

spring:
  application:
    name: alias-pay
    #zookeeper註冊中心配置
#  cloud:
#    zookeeper:
#      connect-string: 122.51.160.240:2181
  cloud:
    consul:
      port: 8500
      host: localhost
      discovery:
        service-name: ${spring.application.name}
        heartbeat:
          enabled: true
        healthCheckPath: ${management.server.servlet.context-path}/health
        healthCheckInterval: 15s
        health-check-critical-timeout: 20s
        enabled: true

項目啓動類去掉@EnableEurekaClient註解,使用@EnableDiscoveryClient註解

啓動order、pay項目,在瀏覽器輸入localhost:8500,打開consul ui管理控制檯。可以看到我們的服務已啓動

consul控制檯
調用http://localhost:8081/pay/payOrder接口,看到返回支付訂單:order服務端口:8083,服務端口:8081說明調用成功。

至於consul的健康檢查、鍵值存儲、安全服務通信、多數據中心等功能可參考Consul文檔Spring Cloud Consul文檔

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章