Spring Boot + Spring Cloud 构建微服务系统(一):服务注册和发现(Consul)

使用Consul提供注册和发现服务

什么是 Consul

Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置。与其它分布式服务注册与发现的方案,Consul 的方案更“一站式”,内置了服务注册与发现框架、分布一致性协议实现、健康检查、Key/Value 存储、多数据中心方案,再也不须要依赖其它工具(好比 ZooKeeper 等)。使用起来也较为简单。Consul 使用 Go 语言编写,所以具备自然可移植性(支持Linux、windows和Mac OS X);安装包仅包含一个可执行文件,方便部署,与 Docker 等轻量级容器可无缝配合。html

Consul 安装

访问 Consul 官网 ,根据操做系统类型,选择下载 Consul 的最新版本。我这里选择windows版本。java

下载下来是一个zip压缩包,解压以后,是一个exe可执行文件。git

 打开CMD终端,进入consul.exe所在目录,执行以下命令启动Consul服务。web

cd C:\consul_1.3.0_windows_amd64  # 进入consul.exe所在目录
consul agent
-dev # 启动服务, -dev 表示开发模式运行,另外还有 -server 表示服务模式运行

启动过程信息以下图所示。spring

启动成功以后,访问 http://localhost:8500 , 能够查看 Consul 管理界面。windows

 

Consul 服务提供者

服务注册发现中心有了,如今咱们来开发服务提供者。浏览器

新建项目 spring-cloud-consul-producer,添加如下依赖。app

pom.xml负载均衡

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-consul-discovery</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

说明:框架

spring-boot-starter-actuator 健康检查依赖于此包。

spring-cloud-starter-consul-discovery Spring Cloud Consul 的支持。

注意添加Spring Cloud的依赖配置,完整内容参见源码pom文件。

  <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>

添加配置

在配置文件添加内容以下。

application.yml

server:
  port: 8511
spring:
  application:
    name: spring-cloud-consul-producer
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        serviceName: service-producer    # 注册到consul的服务名称

Consul 的地址和端口号默认是 localhost:8500 ,若是不是这个地址能够自行配置,consul服务会占用8502接口,因此不要用850一、8502。
spring.cloud.consul.discovery.serviceName 是指注册到 Consul 的服务名称,后期客户端会根据这个名称来进行服务调用。

修改启动类

 修改启动器类,添加 @EnableDiscoveryClient 注解,开启服务发现支持。

package com.louis.spring.cloud.consul.producer;

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

@EnableDiscoveryClient
@SpringBootApplication
public class ConsuleProducerApplication {

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

添加服务

新建 HelloController,提供 hello 接口, 返回 hello consul 字符串。

package com.louis.spring.cloud.consul.producer.controller;

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

@RestController
public class HelloController {

    @RequestMapping("/hello")
    public String hello() {
        return "hello consul.";
    }
}

为了模拟注册均衡负载,复制一份上面的项目,重命名为 spring-cloud-consul-producer2 ,修改对应的端口为 8512,修改 hello 方法的返回值为:"helle consul two",修改完成后依次启动两个项目,启动成功以后刷新Consul管理界面,发现咱们注册的service-producer服务,并有2个节点实例。

点击进入节点详情页面,能够看到咱们注册的8511和8512两个服务提供者节点实例。

Consul 消费者

服务注册发现中心有了,服务提供者也有了,如今咱们来开发服务消费者。

新建项目 spring-cloud-consul-comsumer,依赖同提供者。

添加配置

修改配置文件以下。

application.yml

server:
  port: 8521
spring:
  application:
    name: spring-cloud-consul-consumer
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        register: false    #设置不须要注册到 consul 中

客户端能够设置是否注册到 Consul 中,具体须要根据咱们的业务来选择,通常在须要对外提供服务时进行注册。

启动器类

ConsuleConsumerApplication.java

package com.louis.spring.cloud.consul.producer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ConsuleConsumerApplication {

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

服务消费者

添加消费服务测试类,添加两个接口,一个查询全部咱们注册的服务,另外一个从咱们注册的服务中选取一个服务,采用轮询的方式。

ServiceController.java

package com.louis.spring.cloud.consul.producer.controller;

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.RestController;

@RestController
public class ServiceController {

    @Autowired
    private LoadBalancerClient loadBalancerClient;
    @Autowired
    private DiscoveryClient discoveryClient;

   /**
     * 获取全部服务
     */
    @RequestMapping("/services")
    public Object services() {
        return discoveryClient.getInstances("service-producer");
    }

    /**
     * 从全部服务中选择一个服务(轮询)
     */
    @RequestMapping("/discover")
    public Object discover() {
        return loadBalancerClient.choose("service-producer").getUri().toString();
    }
}

添加完成以后,启动项目, 访问 http://localhost:8521/services,返回两个服务,分别是咱们注册的8511和8512。

[{
    "serviceId": "service-producer",
    "host": "GG20J1G2E.logon.ds.ge.com",
    "port": 8511,
    "secure": false,
    "metadata": {
        "secure": "false"
    },
    "uri": "http://GG20J1G2E.logon.ds.ge.com:8511",
    "scheme": null
}, {
    "serviceId": "service-producer",
    "host": "GG20J1G2E.logon.ds.ge.com",
    "port": 8512,
    "secure": false,
    "metadata": {
        "secure": "false"
    },
    "uri": "http://GG20J1G2E.logon.ds.ge.com:8512",
    "scheme": null
}]

反复访问 http://localhost:8521/discover,结果交替返回服务8511和8512,由于默认的负载均衡器是采用轮询的方式。

http://GG20J1G2E.logon.ds.ge.com:8511
http://GG20J1G2E.logon.ds.ge.com:8512
...

8511 和 8512 两个服务会交替出现,从而实现了获取服务端地址的均衡负载。

大多数状况下咱们但愿使用均衡负载的形式去获取服务端提供的服务,所以使用第二种方法来模拟调用服务端提供的 hello 方法。

建立 CallHelloController.java

package com.louis.spring.cloud.consul.producer.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class CallHelloController {

    @Autowired
    private LoadBalancerClient loadBalancer;

    @RequestMapping("/call")
    public String call() {
        ServiceInstance serviceInstance = loadBalancer.choose("service-producer");
        System.out.println("服务地址:" + serviceInstance.getUri());
        System.out.println("服务名称:" + serviceInstance.getServiceId());

        String callServiceResult = new RestTemplate().getForObject(serviceInstance.getUri().toString() + "/hello", String.class);
        System.out.println(callServiceResult);
        return callServiceResult;
    }

}

使用 RestTemplate 进行远程调用。添加完以后重启 spring-cloud-consul-consumer 项目。

在浏览器中访问地址:http://localhost:8521/call,依次返回结果以下:

helle consul
helle consul two
...

 

源码下载

码云:https://gitee.com/liuge1988/spring-cloud-demo.git


做者:朝雨忆轻尘
出处:https://www.cnblogs.com/xifengxiaoma/ 版权全部,欢迎转载,转载请注明原文做者及出处。

相关文章
相关标签/搜索