Asp.Net Core Consule
Asp.Net Core Consule
1.1 Consule简介
在分布式架构中,服务治理是必须面对的问题,如果缺乏简单有效治理方案,各服务之间只能通过人肉配置的方式进行服务关系管理,当遇到服务关系变化时,就会变得极其麻烦且容易出错。
Consul是一个用来实现分布式系统服务发现与配置的开源工具。它内置了服务注册与发现框架、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方案,不再需要依赖其他工具(比如 ZooKeeper 等),使用起来也较为简单。
服务注册与发现、健康检查
-
服务注册:简单理解,就是有一个注册中心,我们的每个服务实例启动时,都去注册中心注册一下,告诉注册中心我的地址,端口等信息。同样的服务实例要删除时,去注册中心删除一下,注册中心负责维护这些服务实例的信息。
-
服务发现:既然注册中心维护了各个服务实例的信息,那么客户端通过注册中心就很容易发现服务的变化了。
-
健康检查:每个服务都需要提供一个用于健康检查的接口,该接口不具备业务功能。服务注册时把这个接口的地址也告诉注册中心,注册中心会定时调用这个接口来检测服务是否正常,如果不正常,则将它移除,这样就保证了服务的可用性。
1.2 docker安装Consul
环境说明:vmware16 Pro + centos7
(1)查看consul镜像
docker search consul
(2)拉取consul镜像
docker pull consul
(3)运行consul
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。
(4)查看防火墙状态,因为是虚拟机模拟内网,这里直接关闭防火墙
firewall-cmd --state
systemctl stop firewalld
(5)访问8500端口
1.3 VMWare安装centos7,虚拟机ping不通宿主机
本来想着使用虚拟机搭建一个centos7环境运行consul,consul运行正常,且宿主机可以访问8500端口
但是consul需要心跳检测访问宿主机的接口,一直访问失败
具体原因好像虚拟机没法访问宿主机(ping不通),笔记本连得是wife,已经配置固定IP
但是虚拟机可以ping通宿主机并且可以连上外网
ping通百度
按照网上的教程不管是修改注册表还是修改防火墙的高级安全Windows Defender防火墙都未解决
注册表
高级安全Windows Defender防火墙
记录一下,目前为了不影响学习,暂时使用Consul的Windows版本运行exe
1.4 Windows使用consul
(1)下载地址:https://www.consul.io/downloads
下载并解压
(2)运行命令:consul agent -server -bootstrap-expect=1 -node=service1 -bind=127.0.0.1 -data-dir=./data -client=0.0.0.0 -ui -config-dir=./config
-
server:表示consul代理模式,有两个选择-server和-client
-
bootstrap-expect:在一个数据中心中期望提供的server节点数量,只有等到指定数量的server全部启动后,才会启动集群(自行选举ledger)
-
node:集群中节点名称,同一集群中唯一,默认为主机名
-
bind:绑定集群内部通信的地址,表示该节点监听的地址,这个地址必须是集群内部所有节点可达的。默认是0.0.0.0(将绑定机器得所有地址,同时把 ipv4地址告诉集群得其他人)
-
client:绑定客户端的ip地址,默认127.0.0.1,可绑定多个。0.0.0.0表示谁都可以访问。
-
data-dir:用于存放Agent状态的目录
-
ui:启用web ui
-
config-dir:**配置目录,将加载目录中的 .hcl 或 .json 格式配置。 注意子路径不会加载
(3)访问http://localhost:8500/ui/dc1/services
1.5 Asp.Net Core使用Consul
(1)安装Consul
命令
Install-Package Consul
包管理
<ItemGroup>
<PackageReference Include="Consul" Version="1.6.10.4" />
</ItemGroup>
(2)Consul配置类
public class ConsulConfig
{
public string Address { get; set; }
public string DataCenter { get; set; }
public string ServiceName { get; set; }
public int ServicePort { get; set; }
public string HealthCheck { get; set; }
public void Config(ConsulConfig config)
{
Address = config.Address;
DataCenter = config.DataCenter;
ServiceName = config.ServiceName;
ServicePort = config.ServicePort;
HealthCheck = config.HealthCheck;
}
}
(3)Consul服务发现扩展-服务注入
/// <summary>
/// Consul服务发现扩展-服务注入
/// </summary>
public static class ConsulServiceCollectionExtensions
{
public static IServiceCollection ConsulRegister(this IServiceCollection services, Action<ConsulConfig> configAction)
{
var conf = new ConsulConfig();
configAction(conf);
services.AddSingleton(conf);
return services;
}
public static IApplicationBuilder UseConsul(this IApplicationBuilder app, IServiceProvider serviceProvider, IHostApplicationLifetime lifetime)
{
ConsulConfig config = serviceProvider.GetService<ConsulConfig>();
ConsulClient consulClient = new ConsulClient(
(ConsulClientConfiguration c) =>
{
c.Address = new Uri(config.Address); //Consul服务中心地址
c.Datacenter = config.DataCenter; //指定数据中心,如果未提供,则默认为代理的数据中心。
}
);
var ServiceName = config.ServiceName;
//本地测试用localhost即可 保证心跳的接口可以正常访问
var ServiceIP = "localhost"; //DNSHelper.GetLocalIP4();
var ServicePort = config.ServicePort;
var ServiceId = $"{ServiceName}_{ServiceIP}:{ServicePort}";
var httpCheck = new AgentServiceCheck()
{
DeregisterCriticalServiceAfter = TimeSpan.FromMilliseconds(10), //服务停止后多久注销
Interval = TimeSpan.FromSeconds(5), //服务健康检查间隔
Timeout = TimeSpan.FromSeconds(5), //检查超时的时间
HTTP = $"{Uri.UriSchemeHttp}://{ServiceIP}:{ServicePort}/HealthCheck" //检查的地址
//HTTP = $"{Uri.UriSchemeHttps}://{ServiceIP}:{ServicePort}/HealthCheck" //检查的地址
};
var registration = new AgentServiceRegistration()
{
ID = ServiceId, //服务编号,不可重复
Name = ServiceName, //服务名称
Port = ServicePort, //本程序的端口号
Address = ServiceIP,//本程序的IP地址
Checks = new[] { httpCheck },
};
consulClient.Agent.ServiceRegister(registration).Wait();//服务启动时注册,内部实现其实就是使用 Consul API 进行注册(HttpClient发起)
lifetime.ApplicationStopping.Register(() =>
{
consulClient.Agent.ServiceDeregister(registration.ID).GetAwaiter().GetResult();//服务停止时取消注册
});
//健康检测
app.Map(config.HealthCheck, s =>
{
s.Run(async context =>
{
await context.Response.WriteAsync("ok");
});
});
return app;
}
}
(4)配置固定端口
(5)注入Consul
(6)Apollo配置,记得发布
(7)运行服务,访问http://localhost:8500/ui/dc1/services
要保证发现的服务健康检测的接口可以访问