SpringBoot(微服务)注册分布式Consul
Posted 南宫乘风
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot(微服务)注册分布式Consul相关的知识,希望对你有一定的参考价值。
Consul是什么
Consul是一个基于HTTP的服务发现工具,用于配置和管理系统和服务之间的依赖关系。它提供了一个简单的方式来注册、发现和配置服务,并包括健康检查、负载均衡和故障转移等功能。
Consul是一种分布式系统,用于在大型分布式系统中实现服务发现和配置共享。它使用Raft协议来实现强一致性,保证了在多个节点之间进行的数据更新的原子性。
Consul客户端可以将它们自己的服务信息注册到Consul服务器。这样,Consul服务器将自动成为所有服务的服务目录。此外,Consul还提供了一个健康检查机制,以确保已注册的服务仍然可以正常工作。
当一个客户端想要调用一个服务时,它可以从Consul服务器获取服务的网络位置信息。然后,客户端将使用此信息建立与服务的网络连接。
Consul通过HTTP API公开其服务发现和配置共享功能,这使得使用Consul与其他系统相当容易,如Kubernetes等容器编排工具。
总之,Consul的分布式注册原理是通过服务端和客户端之间的交互来实现服务发现和健康检查。客户端将服务信息注册到Consul服务器,然后从Consul服务器获取服务信息并建立网络连接。Consul使用Raft协议确保强一致性,并提供HTTP API进行访问。
Consul原理
Consul采用的是集中式的注册中心架构,其中包含一个服务发现组件和一个KV存储组件。
服务发现组件:Consul中的服务发现是通过一组Agent和Server实现的。Agent是每个主机上运行的代理,用于与服务交互并报告本地运行状况。Server是负责在Consul集群中运行Raft算法的节点,以实现高可用性。
当服务启动时,它会向本地的Consul Agent发送一个服务注册请求,Agent会将服务的元数据信息(服务名、地址、端口等)注册到Consul的KV存储中。服务消费者可以通过向Agent发送服务发现请求来获取服务的地址和端口信息,然后向该地址发送请求以调用服务。
KV存储组件:Consul中的KV存储组件用于存储键值对信息,可以用于存储任何数据。在服务注册和发现中,服务元数据信息就是存储在KV存储中的。
当服务启动时,它会将自己的元数据信息存储到Consul的KV存储中,同时也会定期发送心跳请求告诉Consul服务还在运行。当服务终止时,它会发送一个注销请求告诉Consul将服务从KV存储中删除。
服务消费者可以从Consul的KV存储中获取服务的元数据信息,然后使用这些信息来调用服务。同时,服务消费者也可以监听KV存储中元数据信息的变化,当服务的元数据信息发生变化时,它会自动更新本地缓存。
总体来说,Consul的服务注册和发现过程如下:
- 服务启动时,将自己的元数据信息注册到Consul的KV存储中,同时向本地的Consul Agent发送心跳请求告诉Consul服务还在运行。
- 服务消费者向Consul Agent发送服务发现请求,Agent从KV存储中获取服务的元数据信息并返回给服务消费者。
- 服务消费者使用获取到的服务元数据信息来调用服务。
- 当服务终止时,它会发送一个注销请求告诉Consul将服务从KV存储中删除。
启动 Consul 集群
#启动第1个Server节点,集群要求要有3个Server,将容器8500端口映射到主机8900端口,同时开启管理界面
docker run -d --name=consul1 -p 8900:8500 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=true --bootstrap-expect=3 --client=0.0.0.0 -ui
#启动第2个Server节点,并加入集群
docker run -d --name=consul2 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=true --client=0.0.0.0 --join 172.17.0.2
#启动第3个Server节点,并加入集群
docker run -d --name=consul3 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=true --client=0.0.0.0 --join 172.17.0.2
#启动第4个Client节点,并加入集群
docker run -d --name=consul4 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=false --client=0.0.0.0 --join 172.17.0.2
第 1 个启动容器的 IP 一般是 172.17.0.2,后边启动的几个容器 IP 会排着来:172.17.0.3、172.17.0.4、172.17.0.5。
这些 Consul 节点在 Docker 的容器内是互通的,他们通过桥接的模式通信。但是如果主机要访问容器内的网络,需要做端口映射。
在启动第一个容器时,将 Consul 的 8500 端口映射到了主机的 8900 端口,这样就可以方便的通过主机的浏览器查看集群信息。
kubernetes集成Consul
Kubernetes中的一个Pod中可以包含多个容器,这些容器可以协同工作,形成一个完整的服务。在这个例子中,一个Pod中包含了三个容器:Consul客户端容器、Java应用容器和Filebeat容器。
Consul客户端容器是用来向Kubernetes集群外的Consul服务器注册服务的。Consul客户端可以通过API或DNS接口与Consul服务器进行通信,将服务注册信息发送给Consul服务器,包括服务的名称、IP地址、端口号等元数据信息。
Java应用容器是用来运行业务应用程序的。它会通过Consul客户端容器中的API或DNS接口查询服务的信息,包括IP地址和端口号,以便能够与其它服务通信。
Filebeat容器则是用来收集Java应用程序的日志文件,并将其发送到指定的日志服务器进行处理和存储。
下面是大致的架构图:
+---------------------+
| Consul Server |
| (集群外的Consul服务器) |
+---------------------+
|
| HTTP/DNS API
|
+---------------------+
| Consul Client |
| (Pod中的容器) |
+---------------------+
/ \\
/ \\
/ \\
HTTP/DNS API | HTTP API
+-------+ | +--------+
| Java | | | File- |
| App |<------+------>| beat |
| | | |
+-------+ +--------+
在这个架构图中,Java应用容器和Filebeat容器都与Consul客户端容器通过HTTP/DNS API进行通信。Java应用容器使用Consul客户端容器提供的服务注册信息与其它服务进行通信,Filebeat容器则通过HTTP API将收集的日志文件发送到指定的日志服务器。Consul客户端容器通过HTTP API将服务注册信息发送给Kubernetes集群外的Consul服务器,以便其它服务可以发现和使用它们。
以下是 Java 应用通过 Consul 客户端注册到 Consul 服务端的详细步骤流程:
-
Pod 中的 Consul 客户端启动,并向 Consul 集群发现服务请求。
-
Consul 客户端会向 Consul 服务端的任一节点发出注册请求,告知它所在的服务名称、IP 地址、端口号、标签等信息,以及该服务的健康检查规则。
-
Consul 服务端接收到注册请求后,会将该服务信息存储在本地的 KV 存储中,并将该服务的状态标记为“不健康”。
-
Consul 客户端会根据所注册的健康检查规则,定期向 Consul 服务端发送健康检查请求,并根据响应结果更新本地的服务状态。
-
当该服务的状态为“健康”时,Consul 客户端会将该服务的状态信息存储在本地的缓存中,并向本地的 Java 应用提供服务发现和负载均衡功能。
-
Java 应用通过调用 Consul 客户端提供的 API,获取所需服务的 IP 地址和端口号,并通过这些信息与目标服务建立连接。
-
如果需要对该服务进行修改或注销,Java 应用可以向 Consul 客户端发送对应的请求。
-
Consul 客户端接收到请求后,会将请求转发给 Consul 服务端,并更新本地的缓存。
-
Consul 服务端接收到请求后,会更新该服务在本地 KV 存储中的信息,并将该服务的状态标记为“不健康”。
-
Consul 客户端会根据所注册的健康检查规则,定期向 Consul 服务端发送健康检查请求,并根据响应结果更新本地的服务状态。
总体架构图如下:
在该架构中,Consul 客户端和 Java 应用都运行在 Pod 中,其中 Consul 客户端负责服务注册和服务发现,Java 应用则通过 Consul 客户端获取所需服务的信息。同时,Filebeat 用于收集应用的日志数据,并将其发送至目标日志存储系统。
SpringBoot注册Consul
SpringBoot可以通过使用Consul的Java客户端库来实现与Consul的集成,该库提供了丰富的API,包括服务注册、服务发现、KV存储等功能。下面是SpringBoot注册Consul的大致步骤和原理:
- 引入Consul客户端库
在SpringBoot项目的pom.xml中引入Consul客户端库的依赖,例如:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/>
</parent>
<groupId>com.springboot.demo</groupId>
<artifactId>web-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>web-demo</name>
<description>web-demo</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</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-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2020.0.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
2、配置Consul连接信息
在SpringBoot项目的application.yml文件中配置Consul的连接信息,例如:
server:
port: 1000
spring:
application:
name: heian
cloud:
consul:
enabled: true
host: 192.168.102.20 # 注册中心地址
port: 8500 # 注册中心地址的端口
discovery:
hostname: 192.168.96.19 # 本地ip
instance-id: $spring.application.name:$spring.cloud.consul.discovery.hostname:$server.port
#health-check-path: $server.servlet.context-path/actuator/health # 如果配置了context-path就配置,没有就不配
health-check-interval: 15s # 每隔15s做一次健康检查
register: true
register-health-check: true
service-name: $spring.application.name
# 放开端口
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always
3、实现服务注册
启动类
@EnableDiscoveryClient
@SpringBootApplication
public class WebDemoApplication
public static void main(String[] args)
SpringApplication.run(WebDemoApplication.class, args);
控制类
package com.springboot.demo.webdemo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
@RestController
@RequestMapping("/employee")
public class EmployeeController
@GetMapping
public HashMap<String, String> index()
HashMap<String, String> hashmap = new HashMap<String, String>();
hashmap.put("姓名", "王二");
hashmap.put("年龄", "27");
hashmap.put("工龄", "6");
return hashmap;
总结
Spring Boot应用可以通过向Consul注册自身来实现服务发现和治理,使得其他服务可以在Consul中发现并调用它。
文档:
https://www.cnblogs.com/qingyunye/p/12932493.html
一篇文章了解Consul服务发现实现原理 | Harries Blog™
企业分布式微服务云SpringCloud SpringBoot mybatis 路由网关(zuul)
在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现、服务消费、负载均衡、断路器、智能路由、配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统。一个简答的微服务系统如下图:
注意:A服务和B服务是可以相互调用的,作图的时候忘记了。并且配置服务也是注册到服务注册中心的。
在Spring Cloud微服务系统中,一种常见的负载均衡方式是,客户端的请求首先经过负载均衡(zuul、Ngnix),再到达服务网关(zuul集群),然后再到具体的服。,服务统一注册到高可用的服务注册中心集群,服务的所有的配置文件由配置服务管理(下一篇文章讲述),配置服务的配置文件放在git仓库,方便开发人员随时改配置。
一、Zuul简介
Zuul的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如/api/user转发到到user服务,/api/shop转发到到shop服务。zuul默认和Ribbon结合实现了负载均衡的功能。
zuul有以下功能:
- Authentication
- Insights
- Stress Testing
- Canary Testing
- Dynamic Routing
- Service Migration
- Load Shedding
- Security
- Static Response handling
- Active/Active traffic management
二、准备工作
继续使用上一节的工程。在原有的工程上,创建一个新的工程。
三、创建service-zuul工程
其pom.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.forezp</groupId> <artifactId>service-zuul</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>service-zuul</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</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> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.RC1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> </project>
在其入口applicaton类加上注解@EnableZuulProxy,开启zuul的功能:
@EnableZuulProxy @EnableEurekaClient @SpringBootApplication public class ServiceZuulApplication { public static void main(String[] args) { SpringApplication.run(ServiceZuulApplication.class, args); } }
加上配置文件application.yml加上以下的配置代码:
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ server: port: 8769 spring: application: name: service-zuul zuul: routes: api-a: path: /api-a/** serviceId: service-ribbon api-b: path: /api-b/** serviceId: service-feign
首先指定服务注册中心的地址为http://localhost:8761/eureka/,服务的端口为8769,服务名为service-zuul;以/api-a/ 开头的请求都转发给service-ribbon服务;以/api-b/开头的请求都转发给service-feign服务;
依次运行这五个工程;打开浏览器访问:http://localhost:8769/api-a/hi?name=forezp ;浏览器显示:
hi forezp,i am from port:8762
打开浏览器访问:http://localhost:8769/api-b/hi?name=forezp ;浏览器显示:
hi forezp,i am from port:8762
这说明zuul起到了路由的作用
架构代码如下:
完整项目的源码来源 技术支持2147775633
以上是关于SpringBoot(微服务)注册分布式Consul的主要内容,如果未能解决你的问题,请参考以下文章
企业分布式微服务云SpringCloud SpringBoot mybatis 路由网关(zuul)
分布式与微服务系列SpringBoot+Zookeeper集群+Nginx反向代理+Dubbo分布式托管(提供者消费者)