Spring Cloud系列教程(六):服务注册与发现Consul(Finchley版本)

一、前言

在微服务领域,服务注册与发现是其中很重要的一个模块,主要用于服务治理问题;在分布式Dubbo中常用的服务发现与注册中心是ZookeeperCosul与其类似,在SpringCloud刚占领市场的时候,SpringCloud微服务框架默认使用的注册中心组建是Eureka,总所周知,Eureka已经开始闭源了,那么可以替代Eureka的有:ConsulZookeeper ,这两种比较常用,同样可以很好的与SpringCloud集成,用于替代Eureka,本篇就主要实现SpringCloud整合Consul实现服务注册与发现。

二、Consul是什么

Consul是一个支持多数据中心分布式高可用的服务发现和配置共享的服务软件,采用 Go 语言开发。Consul内置了服务注册与发现框 架、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方案。由于出现得晚些,Consul具有功能完善、部署简单、使用方便等特点。

1. 使用Consul 的优势

  • 使用 Raft 算法来保证一致性, 比 ZooKeeper 的 Paxos 算法更简单直接。
  • 支持多数据中心,内外网的服务采用不同的端口进行监听。 ZooKeeper 和 etcd 均不提供多数据中心功能的- 支持。
  • 支持健康检查,etcd 不提供此功能。
  • 支持 http 和 dns 协议接口。ZooKeeper 的集成较为复杂,etcd 只支持 http 协议。
  • 官方提供 web 管理界面,etcd 无此功能。
  • Consul 1.2 新增 Service Mesh 解决方案。

2. Consul默认支持Ribbon负载均衡

Spring Cloud系列教程(六):服务注册与发现Consul(Finchley版本)_第1张图片

三、Consul的安装

1. 下载安装

ConsulGo语言开发,因此也继承了Go语言跨平台,易安装的特点,支持WindwosLinuxmacOS,解压即可运行使用;以Windwos为例,去官网下载: https://www.consul.io/downloads.html , 解压后只有一个.exe文件。
Spring Cloud系列教程(六):服务注册与发现Consul(Finchley版本)_第2张图片

2. 运行Consul

a. 启动Consul命令:

consul agent -dev -ui -node=cy

-dev开发服务器模式启动,-node结点名为cy-ui可以用界面访问,默认能访问。
Spring Cloud系列教程(六):服务注册与发现Consul(Finchley版本)_第3张图片

b. 起始访问地址:
访问地址: http://localhost:8500
Spring Cloud系列教程(六):服务注册与发现Consul(Finchley版本)_第4张图片

四、实现思路

启动Consul后,创建两个基于Consul的客户端服务工程,一个服务提供者和一个服务消费者,使用Feign进行服务消费,客户端配置连接运行的Consul服务,这里先贴一下项目完整结构图;
Spring Cloud系列教程(六):服务注册与发现Consul(Finchley版本)_第5张图片

五、搭建服务提供者springcloud-consul-provider

1.引入pom依赖

  <!--SpringBoot依赖版本-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/>
    </parent>

    <!--项目编码、jdk版本、SpringCloud版本定义-->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
    </properties>

    <!--声明管理SpringCloud版本依赖信息-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- SpringBootWeb组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--springcloud整合consul组件-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

        <!-- 引入Feign接口公共层-->
        <!--<dependency>-->
            <!--<groupId>com.thinkingcao</groupId>-->
            <!--<artifactId>springcloud-feign-interface</artifactId>-->
            <!--<version>0.0.1-SNAPSHOT</version>-->
        <!--</dependency>-->

    </dependencies>

    <!--maven插件-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

2. 启动类上加@EnableDiscoveryClient注解

package com.thinkingcao.api;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class AppMemerProvider {

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

3. @EnableDiscoveryClient 与@EnableEurekaClient区别

  • @EnableDiscoveryClient注解是基于spring-cloud-commons依赖,并且在classpath中实现; 适合于consulzookeeper注册中心
  • @EnableEurekaClient注解是基于spring-cloud-netflix依赖,只能为eureka作用;

4. 修改application.yml

##=========服务生产者-会员服务配置========
##服务在7777端口暴露出来
server:
  port: 8764

##配置Spring相关
spring:
  ##应用服务名称,切记不能为下划线consul_member_provider,因为Feign不支持
  application:
    name: consul-member-provider
  ##consul注册中心地址
  cloud:
    consul:
      ##Consul所在主机ip
      host: localhost
      ##Consul监听的端口
      port: 8500
      discovery:
        ##配置开启服务注册到Consul上
        register: true
        ##配置注册到Consul的服务实例名称(Consul里Feign是通过此名称调用,而非spring.application.name)
        service-name: member-provider
        ##配置服务健康检查地址,供Consul调用
        healthCheckPath: /health
        ##Consul 健康检查频率
        healthCheckInterval: 15s

5. 提供会员接口ApiConsulMemberController

package com.thinkingcao.api.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @desc:  服务生产者(会员服务)
 * @author: cao_wencao
 * @date: 2020-02-22 23:44
 */
@RestController
public class ApiConsulMemberController {

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

    @RequestMapping(value="/getMember", method = RequestMethod.GET)
    private String getMember(@RequestParam("userName") String userName){
        return "我是会员服务,订单服务调用会员服务成功啦, 姓名为: " + userName + ", 端口为: " + serverPort;
    }
}

6. Consul健康检查接口HealthCheckController

package com.thinkingcao.api.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @desc: 提供给Consul健康检查的controller
 * @auth: cao_wencao
 * @date: 2020/2/23 0:08
 */
@RestController
public class HealthCheckController {

    //RequestMapping中的url地址需和配置文件中保持一致
    @RequestMapping("/health")
    public String healthCheck() {
        return "ok";
    }
}

7. 启动会员服务

启动springcloud-consul-provider项目,会发现项目实例 member-provider 注册到了 consul 中

Spring Cloud系列教程(六):服务注册与发现Consul(Finchley版本)_第6张图片

六、搭建服务消费者springcloud-feign-consumer

1.引入pom依赖

 <!--SpringBoot依赖版本-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>com.thinkingcao</groupId>
    <artifactId>springcloud-feign-consumer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springcloud-feign-consumer</name>
    <description>SpringCloud整合Feign客户端组件消费服务</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
    </properties>

    <!--声明管理SpringCloud版本依赖信息-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    <dependencies>
        <!-- SpringBootWeb组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- springcloud整合Feign客户端组件   -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <!-- 引入Feign接口公共层-->
        <!--<dependency>-->
            <!--<groupId>com.thinkingcao</groupId>-->
            <!--<artifactId>springcloud-feign-interface</artifactId>-->
            <!--<version>0.0.1-SNAPSHOT</version>-->
        <!--</dependency>-->

        <!--springcloud整合consul组件-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

        <!-- 健康检查 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!--lombok代码简化工具-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

2. 启动类添加注解

  • 在启动类添加@EnableFeignClients@EnableDiscoveryClient注解,表示启用Feign客户端调用和Consul服务注册与发现功能
package com.thinkingcao.api;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
public class AppOrderConsumer {

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

3. 编辑application.yml

##=========服务消费者-订单服务配置========
#服务端口号
server:
  port: 8787

##配置Spring相关
spring:
  ##服务名称
  application:
    name: consul-order_consumer
  ##consul注册中心地址
  cloud:
    consul:
      ##Consul所在主机ip
      host: localhost
      ##Consul监听的端口
      port: 8500
      discovery:
        ##配置注册到Consul的服务实例名称(Consul里Feign是通过此名称调用,而非spring.application.name)
        service-name: order-consumer
        ##配置服务健康检查地址,供Consul调用
        healthCheckPath: /health
        ##Consul 健康检查频率
        healthCheckInterval: 15s

4. 定义 Feign 接口IFeignClientService

  • 定义Feign接口时,其中@FeignClientvalueprovide 注册在 consul中的服务名。RequestMapping 对应 provider的具体映射。
package com.thinkingcao.api.Feign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * @desc: Feign声明式客户端调用工具
 * @author: cao_wencao
 * @date: 2020-02-22 12:23
 */
@FeignClient(value = "member-provider")
public interface IFeignClientService {

    //通过userId查询会员信息数据
    @RequestMapping("/getMember")
    public String getOrderToMemberInfo(@RequestParam("userName") String userName);
}

5. 定义Controller调用Feign接口

package com.thinkingcao.api.controller;

import com.thinkingcao.api.Feign.IFeignClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @desc:  服务消费者(订单服务)
 * @author: cao_wencao
 * @date: 2020-02-22 12:30
 */
@RestController
public class ApiFeignOrderController {

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @Autowired
    private DiscoveryClient discoveryClient;

    // @Autowired
    // private OrderService orderService;

    @Autowired(required = false)
    private IFeignClientService feignClientService;

    //基于Feign实现订单调用会员 ,并且实现本地负载均衡
    @RequestMapping(value ="/getMemberInfo",method = RequestMethod.GET)
    public String getMemberInfo(@RequestParam("userName") String userName) {
        String memberInfo = feignClientService.getOrderToMemberInfo(userName);
        return memberInfo;
    }

     /**
     * 获取服务实例
     */
    @RequestMapping(value = "/discover",method = RequestMethod.GET)
    public String discover(){
        String instance = loadBalancerClient.choose("member-provider").getUri().toString();
        return instance;
    }

    /**
     * 获取所有服务
     */
    @RequestMapping("/services")
    public Object services() {
        return discoveryClient.getInstances("member-provider");
    }
}

6. Consul健康检查接口HealthCheckController

package com.thinkingcao.api.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @desc: 提供给Consul健康检查的controller
 * @auth: cao_wencao
 * @date: 2020/2/23 0:08
 */
@RestController
public class HealthCheckController {

    //RequestMapping中的url地址需和配置文件中保持一致
    @RequestMapping("/health")
    public String healthCheck() {
        return "ok";
    }
}

7. 启动订单服务

启动springcloud-feign-consumer项目,会发现项目实例 order-consumer注册到了 consul 中,这时候有两个服务都注册其中

Spring Cloud系列教程(六):服务注册与发现Consul(Finchley版本)_第7张图片

七、测试

实现订单调用会员服务接口,为了测试Feign+Ribbon+Cosul实现负载均衡效果,需要启动两个会员提供者服务实例;启动会员服务两个实例后,稍等片刻。
Spring Cloud系列教程(六):服务注册与发现Consul(Finchley版本)_第8张图片

  • 访问接口: http://127.0.0.1:8787/getMemberInfo?userName=“Thinkingcao”

这是浏览器交替显示结果:

我是会员服务,订单服务调用会员服务成功啦, 姓名为: “Thinkingcao”, 端口为: 8764
我是会员服务,订单服务调用会员服务成功啦, 姓名为: “Thinkingcao”, 端口为: 8765

Spring Cloud系列教程(六):服务注册与发现Consul(Finchley版本)_第9张图片
Spring Cloud系列教程(六):服务注册与发现Consul(Finchley版本)_第10张图片

  • 访问接口: http://127.0.0.1:8787/services ,获取服务列表信息Spring Cloud系列教程(六):服务注册与发现Consul(Finchley版本)_第11张图片

八、项目源码

1. 项目源码: https://github.com/Thinkingcao/SpringCloudLearning/tree/master/springcloud-consul

七、SpringCloud系列教程

1.Spring Cloud系列教程(七): Spring Cloud系列教程(七):服务注册与发现ZooKeeper(Finchley版本)

SpringCloud教程汇总: Spring Cloud系列教程(汇总篇):专栏汇总篇(持续更新中)

你可能感兴趣的:(Spring,Cloud2.x系列教程)