什么是 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
参考资料