Spring Boot + Spring Cloud 集成 Consul 服务注册发现

Posted 东海陈光剑

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Boot + Spring Cloud 集成 Consul 服务注册发现相关的知识,希望对你有一定的参考价值。

什么是 Consul ?

Consul is a service mesh solution。

Consul是开源的,用于实现分布式系统的服务发现与配置。Consul是分布式的、高可用的、 可横向扩展的。它具备以下特性:

服务发现: Consul提供了通过DNS或者HTTP接口的方式来注册服务和发现服务。一些外部的服务通过Consul很容易的找到它所依赖的服务。

健康检测: Consul的Client提供了健康检查的机制,可以通过用来避免流量被转发到有故障的服务上。

Key/Value存储: 应用程序可以根据自己的需要使用Consul提供的Key/Value存储。 Consul提供了简单易用的HTTP接口,结合其他工具可以实现动态配置、功能标记、领袖选举等等功能。

多数据中心: Consul支持开箱即用的多数据中心. 这意味着用户不需要担心需要建立额外的抽象层让业务扩展到多个区域。

The key features of Consul are:

  • Service Discovery: Clients of Consul can register a service, such as api or mysql, and other clients can use Consul to discover providers of a given service. Using either DNS or HTTP, applications can easily find the services they depend upon.

  • Health Checking: Consul clients can provide any number of health checks, either associated with a given service ("is the webserver returning 200 OK"), or with the local node ("is memory utilization below 90%"). This information can be used by an operator to monitor cluster health, and it is used by the service discovery components to route traffic away from unhealthy hosts.

  • KV Store: Applications can make use of Consul's hierarchical key/value store for any number of purposes, including dynamic configuration, feature flagging, coordination, leader election, and more. The simple HTTP API makes it easy to use.

  • Secure Service Communication: Consul can generate and distribute TLS certificates for services to establish mutual TLS connections. Intentions can be used to define which services are allowed to communicate. Service segmentation can be easily managed with intentions that can be changed in real time instead of using complex network topologies and static firewall rules.

  • Multi Datacenter: Consul supports multiple datacenters out of the box. This means users of Consul do not have to worry about building additional layers of abstraction to grow to multiple regions.

Consul is designed to be friendly to both the DevOps community and application developers, making it perfect for modern, elastic infrastructures.

Consul 架构组成

安装 Consul

下载安装:https://www.consul.io/downloads
或者命令行安装:

brew tap hashicorp/tap
brew install hashicorp/tap/consul

本地启动 Consul

启动命令:

$consul agent -server -bootstrap-expect=1 -data-dir=consul_data -ui -bind=127.0.0.1

启动日志:

$consul agent -server -bootstrap-expect=1 -data-dir=consul_data -ui -bind=127.0.0.1 
==> Starting Consul agent...
           Version: '1.9.5'
           Node ID: 'bad6d61c-e87e-8415-f97d-9ba4b996655d'
         Node name: 'C02FJ0KMMD6V'
        Datacenter: 'dc1' (Segment: '<all>')
            Server: true (Bootstrap: true)
       Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, gRPC: -1, 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:

    2021-05-19T11:07:11.643+0800 [WARN]  agent: BootstrapExpect is set to 1; this is the same as Bootstrap mode.
    2021-05-19T11:07:11.643+0800 [WARN]  agent: bootstrap = true: do not enable unless necessary
    2021-05-19T11:07:11.646+0800 [WARN]  agent.auto_config: BootstrapExpect is set to 1; this is the same as Bootstrap mode.
    2021-05-19T11:07:11.647+0800 [WARN]  agent.auto_config: bootstrap = true: do not enable unless necessary
    2021-05-19T11:07:11.884+0800 [INFO]  agent.server.raft: initial configuration: index=1 servers="[{Suffrage:Voter ID:bad6d61c-e87e-8415-f97d-9ba4b996655d Address:127.0.0.1:8300}]"
    2021-05-19T11:07:11.885+0800 [INFO]  agent.server.raft: entering follower state: follower="Node at 127.0.0.1:8300 [Follower]" leader=
    2021-05-19T11:07:11.885+0800 [INFO]  agent.server.serf.wan: serf: EventMemberJoin: C02FJ0KMMD6V.dc1 127.0.0.1
    2021-05-19T11:07:11.886+0800 [INFO]  agent.server.serf.lan: serf: EventMemberJoin: C02FJ0KMMD6V 127.0.0.1
    2021-05-19T11:07:11.886+0800 [INFO]  agent.router: Initializing LAN area manager
    2021-05-19T11:07:11.886+0800 [INFO]  agent.server: Handled event for server in area: event=member-join server=C02FJ0KMMD6V.dc1 area=wan
    2021-05-19T11:07:11.886+0800 [INFO]  agent.server: Adding LAN server: server="C02FJ0KMMD6V (Addr: tcp/127.0.0.1:8300) (DC: dc1)"
    2021-05-19T11:07:11.886+0800 [INFO]  agent: Started DNS server: address=127.0.0.1:8600 network=tcp
    2021-05-19T11:07:11.886+0800 [INFO]  agent: Started DNS server: address=127.0.0.1:8600 network=udp
    2021-05-19T11:07:11.887+0800 [INFO]  agent: Starting server: address=127.0.0.1:8500 network=tcp protocol=http
    2021-05-19T11:07:11.887+0800 [WARN]  agent: DEPRECATED Backwards compatibility with pre-1.9 metrics enabled. These metrics will be removed in a future version of Consul. Set `telemetry { disable_compat_1.9 = true }` to disable them.
    2021-05-19T11:07:11.887+0800 [INFO]  agent: started state syncer
==> Consul agent running!
    2021-05-19T11:07:17.627+0800 [WARN]  agent.server.raft: heartbeat timeout reached, starting election: last-leader=
    2021-05-19T11:07:17.627+0800 [INFO]  agent.server.raft: entering candidate state: node="Node at 127.0.0.1:8300 [Candidate]" term=2
    2021-05-19T11:07:17.769+0800 [INFO]  agent.server.raft: election won: tally=1
    2021-05-19T11:07:17.769+0800 [INFO]  agent.server.raft: entering leader state: leader="Node at 127.0.0.1:8300 [Leader]"
    2021-05-19T11:07:17.769+0800 [INFO]  agent.server: cluster leadership acquired
    2021-05-19T11:07:17.770+0800 [INFO]  agent.server: New leader elected: payload=C02FJ0KMMD6V
    2021-05-19T11:07:17.914+0800 [INFO]  agent.leader: started routine: routine="federation state anti-entropy"
    2021-05-19T11:07:17.914+0800 [INFO]  agent.leader: started routine: routine="federation state pruning"
    2021-05-19T11:07:17.914+0800 [INFO]  agent.server: member joined, marking health alive: member=C02FJ0KMMD6V
    2021-05-19T11:07:17.961+0800 [INFO]  agent.server: federation state anti-entropy synced
    2021-05-19T11:07:18.075+0800 [INFO]  agent: Synced node info

Consul 命令参考:https://www.consul.io/commands

本地访问: http://localhost:8500/ui/dc1/services

创建 Spring Boot 工程

创建 Spring Boot 工程:

consul 核心依赖:

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

编写代码

ConsulSpringbootDemoApplication

package com.example.consulspringbootdemo;

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

@SpringBootApplication
public class ConsulSpringbootDemoApplication {

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

}

HelloController

package com.example.consulspringbootdemo;

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

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        return "hello,world!";
    }
}

配置 application.properties

application.properties

spring.application.name=consul-springboot-demo
server.port=8081
spring.cloud.consul.discovery.enabled=true
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500

启动运行

/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/bin/java -XX:TieredStopAtLevel=1 -noverify -Dspring.output.ansi.enabled=always -javaagent:/private/var/folders/7v/b654w_lx6jz8vw5hzp9qnzqm0000gn/T/AppTranslocation/608C9F51-7E28-4B2B-8497-A980BC72F942/d/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=51775:/private/var/folders/7v/b654w_lx6jz8vw5hzp9qnzqm0000gn/T/AppTranslocation/608C9F51-7E28-4B2B-8497-A980BC72F942/d/IntelliJ IDEA.app/Contents/bin -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dfile.encoding=UTF-8 -classpath /Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtual..........1.7.30.jar:/Users/bytedance/.m2/repository/org/springframework/spring-core/5.3.6/spring-core-5.3.6.jar:/Users/bytedance/.m2/repository/org/springframework/spring-jcl/5.3.6/spring-jcl-5.3.6.jar com.example.consulspringbootdemo.ConsulSpringbootDemoApplication

  .   ____          _            __ _ _
 /\\\\ / ___'_ __ _ _(_)_ __  __ _ \\ \\ \\ \\
( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\
 \\\\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.4.5)

2021-05-19 11:47:09.777  INFO 23711 --- [           main] c.e.c.ConsulSpringbootDemoApplication    : Starting ConsulSpringbootDemoApplication using Java 1.8.0_291 on C02FJ0KMMD6V with PID 23711 (/Users/bytedance/code/consul-springboot-demo/target/classes started by bytedance in /Users/bytedance/code/consul-springboot-demo)
2021-05-19 11:47:09.785  INFO 23711 --- [           main] c.e.c.ConsulSpringbootDemoApplication    : No active profile set, falling back to default profiles: default
2021-05-19 11:47:11.418  INFO 23711 --- [           main] o.s.cloud.context.scope.GenericScope     : BeanFactory id=db96fb34-10ee-37e3-ac5b-2af2e64eea46
2021-05-19 11:47:11.794  INFO 23711 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8081 (http)
2021-05-19 11:47:11.805  INFO 23711 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-05-19 11:47:11.805  INFO 23711 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.45]
2021-05-19 11:47:11.904  INFO 23711 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-05-19 11:47:11.904  INFO 23711 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2032 ms
2021-05-19 11:47:12.181  INFO 23711 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2021-05-19 11:47:12.935  INFO 23711 --- [           main] o.s.s.c.ThreadPoolTaskScheduler          : Initializing ExecutorService 'catalogWatchTaskScheduler'
2021-05-19 11:47:12.942  WARN 23711 --- [           main] iguration$LoadBalancerCaffeineWarnLogger : Spring Cloud LoadBalancer is currently working with the default cache. You can switch to using Caffeine cache, by adding it and org.springframework.cache.caffeine.CaffeineCacheManager to the classpath.
2021-05-19 11:47:12.947  INFO 23711 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 2 endpoint(s) beneath base path '/actuator'
2021-05-19 11:47:13.013  INFO 23711 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8081 (http) with context path ''
2021-05-19 11:47:13.015  INFO 23711 --- [           main] o.s.c.c.s.ConsulServiceRegistry          : Registering service with consul: NewService{id='consul-springboot-demo-8081', name='consul-springboot-demo', tags=[], address='10.94.53.140', meta={secure=false}, port=8081, enableTagOverride=null, check=Check{script='null', dockerContainerID='null', shell='null', interval='10s', ttl='null', http='http://10.94.53.140:8081/actuator/health', method='null', header={}, tcp='null', timeout='null', deregisterCriticalServiceAfter='null', tlsSkipVerify=null, status='null', grpc='null', grpcUseTLS=null}, checks=null}
2021-05-19 11:47:13.151  INFO 23711 --- [           main] c.e.c.ConsulSpringbootDemoApplication    : Started ConsulSpringbootDemoApplication in 4.186 seconds (JVM running for 4.796)
2021-05-19 11:47:13.480  INFO 23711 --- [5)-10.94.53.140] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-05-19 11:47:13.480  INFO 23711 --- [5)-10.94.53.140] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2021-05-19 11:47:13.481  INFO 23711 --- [5)-10.94.53.140] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms

测试验证

Consul 后台管理页面

访问 http://localhost:8500/ui/dc1/services 可以看到新注册服务:

接口测试

GET http://127.0.0.1:8081/hello

HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 12
Date: Wed, 19 May 2021 03:51:36 GMT
Keep-Alive: timeout=60
Connection: keep-alive

hello,world!

Response code: 200; Time: 265ms; Content length: 12 bytes

参考资料

https://www.consul.io/

以上是关于Spring Boot + Spring Cloud 集成 Consul 服务注册发现的主要内容,如果未能解决你的问题,请参考以下文章

Spring Cloud总结29.Zuul的FallBack回退机制

将已有的spring app迁移到spring-boot,手动配置spring-boot?

为啥 Spring Boot 应用程序 pom 同时需要 spring-boot-starter-parent 和 spring-boot-starter-web?

《02.Spring Boot连载:Spring Boot实战.Spring Boot核心原理剖析》

spring-boot-quartz, 依赖spring-boot-parent

spring-boot系列:初试spring-boot