Spring Cloud Consul简介

发布时间 2023-04-08 14:44:24作者: shigp1

Spring Cloud Consul通过自动配置和绑定到Spring Environment和其他Spring编程模型习惯用法,为Spring Boot应用程序提供Consul集成。通过一些简单的注释,您可以快速启用和配置应用程序中的常见模式,并使用Hashicorp的Consul构建大型分布式系统。提供的模式包括服务发现、分布式配置和控制总线。服务发现是基于微服务的体系结构的关键原则之一。尝试手动配置每个客户端或某种形式的约定可能非常困难,而且可能非常脆弱。Consul通过HTTP API和DNS提供服务发现服务。Spring Cloud Consul利用HTTP API进行服务注册和发现。这并不能阻止非Spring Cloud应用程序利用DNS接口。Consul代理服务器在集群中运行,该集群通过gossip协议进行通信,并使用Raft共识协议。

特点

1、服务发现:可以向Consul代理注册实例,客户端可以使用Spring托管bean发现实例。
2、通过Spring Cloud Netflix支持Ribbon客户端负载均衡器。
3、支持Spring Cloud LoadBalancer-Spring Cloud项目提供的客户端负载平衡器
4、通过Spring Cloud Netflix支持Zuul,一个动态路由器和过滤器
5、分布式配置:使用Consul密钥/值存储
6、控制总线:使用Consul事件的分布式控制事件

使用Consul

将Consul作为服务注册和发现的服务器,微服务作为客户端。Consume(端口是8001)和Producer(两个服务,一个端口是8000,一个端口是8002)添加依赖:

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>

 
并在application.properties配置:

spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500

 
 

启动Consumer,Producer。访问http://127.0.0.1:8500/,结果如下:
 

看到consumer左边有个红叉,点进去看到:

HTTP GET http://192.168.31.148:8001/actuator/health: 404  Output: <html><body><h1>Whitelabel Error Page</h1><p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p><div id='created'>Sat Apr 08 12:52:07 CST 2023</div><div>There was an unexpected error (type=Not Found, status=404).</div></body></html>

Consul通过spring-boot-actuator与客户端进行健康检查,只需在consumer中加入依赖:

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

并在application.properties配置:

management.endpoints.web.exposure.include=*

开启spring-boot-actuator端点重启即可。当客户端向Consul注册时,它会提供有关自身的元数据,如主机和端口、id、名称和标记。默认情况下,会创建一个HTTP检查,Consul每10秒命中一次/actuator/health端点。如果运行状况检查失败,则服务实例被标记为critical实例。
 
 

Consumer的application.properties:

server.port=8001

spring.application.name=consumer

#eureka.client.service-url.defaultZone=http://test1.com:8761/eureka/

#eureka.client.healthcheck.enabled=true

management.endpoints.web.exposure.include=*
#management.endpoint.health.show-details=always

spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500

 
 

Producer的application.properties:

server.port=8002

spring.application.name=producer

#eureka.client.service-url.defaultZone=http://user:123@localhost:8761/eureka/

spring.zipkin.base-url=http://localhost:9411/
spring.zipkin.sleuth.sampler.rate=1

management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
spring.boot.admin.client.url=http://localhost:7500

spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500

 
 

在Consumer的controller中:

@Autowired
private DiscoveryClient discoveryClient;

@RequestMapping("/serviceList")
public List<String> serviceList() {
    return discoveryClient.getServices();
}

访问http://localhost:8001/serviceList,看到

["consul","consumer","producer"]

健康检查

Consul实例的运行状况检查默认为“/actuator/health”,这是Spring Boot actuator应用程序中运行状况端点的默认位置。如果您使用非默认上下文路径或servlet路径(例如server.servletPath=/foo)或管理端点路径(例如management.server.servlet.context path=/admin),即使对于Actuator应用程序,也需要更改这一点。
 
Consul用于检查健康端点的间隔也可以进行配置。“10s”和“1m”分别表示10秒和1分钟。健康检查间隔默认是10s。通过以下的配置改变健康检查端点的路径和时间间隔:

spring.cloud.consul.discovery.healthCheckPath=/actuator/health
spring.cloud.consul.discovery.healthCheckInterval=15s

可以通过设置spring.cloud.consor.discovery.register health-check=false来完全禁用HTTP健康检查。

 

还可以在健康检查时添加请求头参数,例如:

spring.cloud.consul.discovery.health-check-headers.X-Config-Token=6442e58b-d1ea-182e-cfa5-cf9cddef0722
上报健康指标

可以实现HealthIndicator,ConsulHealthIndicator,DiscoveryClientHealthIndicator来上报服务的健康指标。

 
例子

@Service
public class HealthStatusService implements HealthIndicator {

    private Boolean status = true;

    public void setStatus(Boolean status) {
        this.status = status;
    }

    @Override
    public Health health() {
        if (status)
            return new Health.Builder().up().build();
        return new Health.Builder().down().build();
    }

    public String getStatus() {
        return this.status.toString();
    }

}

在Controller中:

@Autowired
private HealthStatusService healthStatusSrv;


@GetMapping("/health")
public String health(@RequestParam("status") Boolean status) {

    healthStatusSrv.setStatus(status);
    return healthStatusSrv.getStatus();
}

访问http://localhost:8001/health?status=false,等待10秒左右可以看到consumer的状态变为Critical,在访问http://localhost:8001/health?status=true,consumer的状态变为Passing。

将HealthStatusService改成下面可看到相同效果:

@Service
public class MyHealthStatus extends ConsulHealthIndicator {

    private Boolean status = true;

    public void setStatus(Boolean status) {
        this.status = status;
    }


    @Autowired
    public MyHealthStatus(ConsulClient consul, ConsulHealthIndicatorProperties properties) {
        super(consul, properties);
    }

    @Override
    public Health getHealth(boolean includeDetails) {
        if (status)
            return new Health.Builder().up().build();
        return new Health.Builder().down().build();
    }
}

元数据

配置以下参数添加元数据:

spring.cloud.consul.discovery.metadata.myfield=myvalue
spring.cloud.consul.discovery.metadata.anotherfield=anothervalue

访问http://127.0.0.1:8500/,进入具体服务,看到元数据:

&nbsp;
 

Consul自动生成了元数据:

key value
'group' 属性值spring.cloud.consul.discovery.instance-group ,不为空才展示
'secure' 如果属性spring.cloud.consol.discovery.scheme等于“https”,则为True,否则为false。
属性spring.cloud.consol.discovery.default-zone-metadata-name,默认为“zone” 属性spring.cloud.consol.discovery.instance-zone。只有实例区域不为空时才会生成此值。

Consul Instance ID唯一

默认情况下,consur实例注册的ID等于其Spring应用程序上下文ID。默认情况下的Spring应用程序语境ID为\({Spring.Application.name}:逗号,分隔,profiles:\){server.port}。在大多数情况下,这将允许一个服务的多个实例在一台计算机上运行。如果需要进一步的唯一性,则使用Spring Cloud可以通过在Spring.Cloud.consol.discovery.instanceId中提供唯一标识符来覆盖这一点。

 

访问http://127.0.0.1:8500/,看到服务的默认Instance id:

 

在Consumer的application.properties中加入配置:

spring.cloud.consul.discovery.instance-id=${spring.application.name}-${server.port}-${random.value}

访问http://127.0.0.1:8500/,看到consumer的Instance id: