Consul 笔记
Consul
运行Consul
docker run -d -p 8500:8500 --restart=always --name=consul consul:latest agent -server -bootstrap -ui -node=1 -client='0.0.0.0'
API的代码
using Consul;
using Newtonsoft.Json;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
// 传参是为了告诉consul自己的 host 和 port
// 这里我是直接取执行的参数,可以自己换别的形式通知到应用自己的host和port。
if (!string.IsNullOrWhiteSpace(args[0]) && !string.IsNullOrWhiteSpace(args[1]) && !string.IsNullOrWhiteSpace(args[2]))
{
var name = args[0];
var host = args[1];
var port = int.Parse(args[2]);
var consulClient = new ConsulClient(options =>
{
options.Address = new Uri($"http://wosperry.com.cn:8500/");
options.Datacenter = "dc1";
});
var httpCheck = new AgentServiceCheck()
{
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册
Interval = TimeSpan.FromSeconds(10),//健康监测
HTTP = string.Format($"http://{host}:{port}/api/health"),//心跳检测地址
Timeout = TimeSpan.FromSeconds(5)
};
Console.WriteLine(JsonConvert.SerializeObject(httpCheck));
//注册
var registrtion = new AgentServiceRegistration()
{
Checks = new[] { httpCheck },
ID = "perry-" + Guid.NewGuid().ToString(),//服务编号不可重复
Name = name,//服务名称
Address = host,//ip地址
Port = port//端口
};
//注册服务
consulClient.Agent.ServiceRegister(registrtion);
}
app.MapGet("api/health", () => { });
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Docker 拉代码、构建、运行 API
# docker镜像名字
IMAGE=perry20220918
# 服务名字(Consul用的)
NAME=perry-test
# API 应用自己的Host
HOST=http://wosperry.com.cn
# API 应用自己的端口,给docker,并传到ENTRYPOINT 给dotnet cli 用
# 这个$1是因为我不想手动一次次复制,就定义了一个update.sh文件,通过 ./update.sh 8001 把端口当成参数给到命令里。
# (如果Linux不能执行,可以 chmod 777 update.sh 给全部权限
PORT=$1
# 这里的几个参数其实是我用代码写的 args[0] 这样获取的,可以换别的形式传
# 下面是真正的命令,就移除掉 容器、镜像,然后拉代码,重新构建镜像,然后运行到指定的端口
docker rm -f ${NAME}-${PORT}
docker rmi -f ${IMAGE}
git pull
docker build -t ${IMAGE} -f Perry20220918/Dockerfile .
docker run -d -p ${PORT}:80 --name ${NAME}-${PORT} ${IMAGE} ${NAME} ${HOST} ${PORT}
Ocelot的配置
{
"Routes": [
{
//转发到下游服务地址--url变量
"DownstreamPathTemplate": "/{url}",
//下游http协议
"DownstreamScheme": "http",
//负载方式,
"LoadBalancerOptions": {
"Type": "RoundRobin" // 轮询 RoundRobin 最少连接 LeastConnection
},
//上游地址
"UpstreamPathTemplate": "/serviceA/{url}", //网关地址--url变量 //冲突的还可以加权重Priority
"UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ],
"UseServiceDisConvery": true, //使用服务发现
"ServiceName": "perry-test", //Consul服务名称
//缓存设置
"FileCacheOptions": {
"TtlSeconds": 10, //缓存10s(同一个地址请求就返回缓存结果)
"Region": "" //缓存region
}
},
{
//转发到下游服务地址--url变量
"DownstreamPathTemplate": "/{url}",
//下游http协议
"DownstreamScheme": "http",
//负载方式,
"LoadBalancerOptions": {
"Type": "RoundRobin" // 轮询
},
//上游地址
"UpstreamPathTemplate": "/serviceB/{url}", //网关地址--url变量 //冲突的还可以加权重Priority
"UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ],
"UseServiceDisConvery": true, //使用服务发现
"ServiceName": "hahaha", //Consul服务名称
//缓存设置
"FileCacheOptions": {
"TtlSeconds": 10, //缓存10s(同一个地址请求就返回缓存结果)
"Region": "" //缓存region
}
},
{
//转发到下游服务地址--url变量
"DownstreamPathTemplate": "/{url}",
//下游http协议
"DownstreamScheme": "http",
//负载方式,
"LoadBalancerOptions": {
"Type": "RoundRobin" // 轮询
},
//上游地址
"UpstreamPathTemplate": "/serviceC/{url}", //网关地址--url变量 //冲突的还可以加权重Priority
"UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ],
"UseServiceDisConvery": true, //使用服务发现
"ServiceName": "PTEST", //Consul服务名称
//缓存设置
"FileCacheOptions": {
"TtlSeconds": 10, //缓存10s(同一个地址请求就返回缓存结果)
"Region": "" //缓存region
}
}
],
"GlobalConfiguration": {
//Ocelot应用地址
"BaseUrl": "http://localhost:5096",
"ServiceDiscoveryProvider": {
//Consul地址
"Host": "wosperry.com.cn",
//Consul端口
"Port": 8500,
"Type": "Consul" //由Consul提供服务发现,每次请求Consul
}
}
}
consul api读取服务列表: https://www.jianshu.com/p/d35cd527d5fb
官方文档: https://ocelot.readthedocs.io/en/latest/features/servicediscovery.html
腾讯云文档《.NET 5 中使用 Consul+Ocelot+Polly缓存、限流、熔断、降级》: https://cloud.tencent.com/developer/article/1899794