net 6 使用 consul 做服务注册与服务发现(上)
前言
学无止境
今天来了解一下使用 cousul ,那什么是consul 呢
Consul是一种开源的、分布式的服务发现和配置管理工具。它由HashiCorp公司开发,用于帮助构建和维护现代化的分布式系统和微服务架构。
Consul提供了许多核心功能,包括:
服务发现:Consul充当了一个注册表,使得服务能够自动注册和发现其他服务。当新的服务启动或停止时,Consul能够自动更新服务注册表,并通知其他服务。
健康检查:Consul可以周期性地检查服务的健康状态,确保只有可用的服务被注册并参与负载均衡。
键值存储:Consul提供了一个分布式键值存储系统,允许应用程序存储和检索配置信息、特征标志或其他共享数据。
多数据中心支持:Consul支持多个数据中心之间的连接和复制,以确保服务在不同地理位置的高可用性。
安全性:Consul提供了身份验证和授权机制,以确保只有经过授权的服务可以访问和使用共享资源。
首先是安装counsul
安装这块我主要用docker 做例子
使用命令拉取consul (不知道为啥我的虚拟机中的docker 必须要让我填版本号)
$ docker pull consul # 默认拉取latest $ docker pull consul:1.6.1 # 拉取指定版本
拉取完成后 运行
docker run -d -p 8500:8500 --restart=always --name=consul consul:latest agent -server -bootstrap -ui -node=1 -client='0.0.0.0'
agent: 表示启动 Agent 进程。
server:表示启动 Consul Server 模式
client:表示启动 Consul Cilent 模式。
bootstrap:表示这个节点是 Server-Leader ,每个数据中心只能运行一台服务器。技术角度上讲 Leader 是通过 Raft 算法选举的,但是集群第一次启动时需要一个引导 Leader,在引导群集后,建议不要使用此标志。
ui:表示启动 Web UI 管理器,默认开放端口 8500,所以上面使用 Docker 命令把 8500 端口对外开放。
node:节点的名称,集群中必须是唯一的,默认是该节点的主机名。
client:consul服务侦听地址,这个地址提供HTTP、DNS、RPC等服务,默认是127.0.0.1所以不对外提供服务,如果你要对外提供服务改成0.0.0.0
join:表示加入到某一个集群中去。 如:-json=192.168.0.11。
防火墙开启8500 端口
【查看防火墙是否开启】
$ systemctl status firewalld
【开启或关闭防火墙】
$ systemctl start firewalld $ systemctl stop firewalld
【查看所有开启的端口】
$ firewall-cmd --list-ports
【开启8500端口】
$ firewall-cmd --zone=public --add-port=8500/tcp --permanent
【重启防火墙,使其生效】
$ firewall-cmd --reload
接下来就可以访问8500 端口了
成功后如下图
代码部分
先下载consul nuget 包
添加一个ConsulHelper,提供一个服务注册的方法
/// <summary> /// 服务注册到consul /// </summary> /// <param name="app"></param> /// <param name="lifetime"></param> public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, IConfiguration configuration, IHostApplicationLifetime lifetime) { var consulClient = new ConsulClient(c => { //consul地址 c.Address = new Uri(configuration["ConsulSetting:ConsulAddress"]); }); var registration = new AgentServiceRegistration() { ID = Guid.NewGuid().ToString(),//服务实例唯一标识 Name = configuration["ConsulSetting:ServiceName"],//服务名 Address = configuration["ConsulSetting:ServiceIP"], //服务IP Port = int.Parse(configuration["ConsulSetting:ServicePort"]),//服务端口 因为要运行多个实例,端口不能在appsettings.json里配置,在docker容器运行时传入 Check = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册 Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔 HTTP = $"http://{configuration["ConsulSetting:ServiceIP"]}:{configuration["ConsulSetting:ServicePort"]}{configuration["ConsulSetting:ServiceHealthCheck"]}",//健康检查地址 Timeout = TimeSpan.FromSeconds(5)//超时时间 } }; //服务注册 consulClient.Agent.ServiceRegister(registration).Wait(); //应用程序终止时,取消注册 lifetime.ApplicationStopping.Register(() => { consulClient.Agent.ServiceDeregister(registration.ID).Wait(); }); return app; }
appsettings.json 文件入下
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*", "ConsulSetting": { "ServiceName": "OrderService", //服务名 "ServiceIP": "192.168.1.3", //服务IP "ServiceHealthCheck": "/healthcheck",//健康检查地址 "ConsulAddress": "http://192.168.1.3:8500" //注意,docker容器内部无法使用localhost访问宿主机器,如果是控制台启动的话就用localhost } }
在管道中注册consul
记得添加健康检查接口,与上方配置的路径一致即可
接下来就是程序的打包运行了
将程序打包到docker 中
dockerfile 示例如下
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app/publish EXPOSE 80 ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone COPY . . ENV ASPNETCORE_URLS=http://+:80 ENTRYPOINT ["dotnet", "Order.API.dll"]
然后在执行 docker 将项目运行 5 份 分别是这几个端口
docker build -t orderapi -f ./Dockerfile . docker run -d -p 9051:80 --name orderservice1 orderapi --ConsulSetting:ServicePort="9051" docker run -d -p 9052:80 --name orderservice2 orderapi --ConsulSetting:ServicePort="9052" docker run -d -p 9053:80 --name orderservice3 orderapi --ConsulSetting:ServicePort="9053" docker run -d -p 9054:80 --name orderservice4 orderapi --ConsulSetting:ServicePort="9054" docker run -d -p 9055:80 --name orderservice5 orderapi --ConsulSetting:ServicePort="9055"
运行完成后,查看一下,已经成功启动
然后在consul 中查看服务是否已经注册成功
现在是五个,因为在上方注册服务的方法中方还写了,程序终止时取消注册
//应用程序终止时,取消注册 lifetime.ApplicationStopping.Register(() => { consulClient.Agent.ServiceDeregister(registration.ID).Wait(); });
现在来试一下,随便停止其中一个容器
这就是consul 的服务注册