使用Docker部署Consul集群并由Ocelot调用 - 以往清泉
source link: https://www.cnblogs.com/xwc1996/p/17233311.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
关于consul
的介绍就不写了百度就行,我们直接开干。
一、部署consul集群
拉取consul的镜像
docker pull consul
然后部署consul容器
docker run --name consul1 -d -p 8500:8500 -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8600:8600 consul:latest agent -server -bootstrap-expect 2 -ui -bind='0.0.0.0' -client='0.0.0.0'
8500 http
端口,用于 http
接口和 web ui
8300 server rpc
端口,同一数据中心 consul server
之间通过该端口通信8301 serf lan
端口,同一数据中心 consul client
通过该端口通信8302 serf wan
端口,不同数据中心 consul server
通过该端口通信8600 dns
端口,用于服务发现
-bbostrap-expect 2
: 集群至少两台服务器,才能选举集群leader
-ui
:运行 web
控制台-bind
: 监听网口,0.0.0.0
表示所有网口,如果不指定默认为127.0.0.1
,则无法和容器通信-client
: 限制某些网口可以访问
-server
:表示该节点是server
节点,不声明的话默认为client
节点,它们的不同是server
节点持久化信息,但是client
不持久化会转发给server
节点,并且server
节点会有leader
节点进行健康检测和同步信息到其他server
节点
然后我们获取该consul1
容器的ip
,使用如下语句
docker inspect --format '{{ .NetworkSettings.IPAddress }}' consul1
获取到了172.17.0.5
然后我们再新建另一个consul
容器,使用join
来加入第一个consul1
容器的集群
docker run --name consul2 -d -p 18500:8500 -p 18300:8300 -p 18301:8301 -p 18302:8302 -p 18600:8600 consul:latest agent -server -ui -bind='0.0.0.0' -client='0.0.0.0' -join 172.17.0.5
我就建两个节点能运行即可,server
一般建3-5
个,client
没有上限,所以根据上面的语句自己建立即可。
然后我们访问地址http://localhost:8500/
可以进到控制界面。
二、将服务注册到Consul中
为测试方便我们使用-dev
参数允许启动一个Consul
服务。
docker run --name consul1 -d -p 8500:8500 -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8600:8600 consul:latest agent -server -ui -bind='0.0.0.0' -client='0.0.0.0' -dev
我们新建一个项目,然后下载Consul包
Install-Package
Consul
然后我们添加一个健康检查的接口
[Route("[controller]/[action]")] [ApiController] public class HealthController : Controller { [HttpGet("/healthCheck")] public IActionResult Check() => Ok("ok"); }
之后我们在appsetting.json
中配置我们的Consul
参数,这些参数我们用来注册服务的一些信息,参数解释如下:
ServiceName
:是服务的名称,同一个服务名的服务将会注册到同一个服务下的实例
ServiceIP
:服务请求的主机地址
ServicePort
:服务请求的端口
ServiceHealthCheck
:服务健康检测接口地址,此处是host.docker.internal
是因为Consul
在容器内需要访问宿主主机运行的服务
Address
:Consul
服务的请求地址
"Consul": { "ServiceName": "service-a", "ServiceIP": "127.0.0.1", "ServicePort": 5001, "ServiceHealthCheck": "http://host.docker.internal:5001/healthCheck", "Address": "http://127.0.0.1:8500" }
之后我们创建一个类名叫ConsulOption
,用于使用过Option
模式加载appsetting.json
中我们配置的参数,用于注册
View Code
然后创建一个Consul
服务注册类ConsulBuilderExtensions
,对将本服务推送到Consul
中去,具体的参数解释在代码注释中了
public static class ConsulBuilderExtensions { public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, IHostApplicationLifetime lifetime, ConsulOption consulOption) { var consulClient = new ConsulClient(x => { x.Address = new Uri(consulOption.Address); }); var registration = new AgentServiceRegistration() { ID = Guid.NewGuid().ToString(), Name = consulOption.ServiceName,// 服务名 Address = consulOption.ServiceIP, // 服务绑定IP Port = consulOption.ServicePort, // 服务绑定端口 Check = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册 Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔 HTTP = consulOption.ServiceHealthCheck,//健康检查地址 Timeout = TimeSpan.FromSeconds(5) } }; // 服务注册 consulClient.Agent.ServiceRegister(registration).Wait(); // 应用程序终止时,服务取消注册 lifetime.ApplicationStopping.Register(() => { consulClient.Agent.ServiceDeregister(registration.ID).Wait(); }); return app; } }
最后我们注入本服务
builder.Services.AddSingleton(builder.Configuration.GetSection("Consul").Get<ConsulOption>()); //.... app.RegisterConsul(app.Lifetime, app.Services.GetRequiredService<ConsulOption>());
启动项目就能看到服务已经注册
Consul提供了http api可以让我们进行查询、注册、接触注册等操作
http://127.0.0.1:8500/v1/health/service/service-a?passing
三、使用Ocelot调用
我们新建一个项目然后安装包
Install-Package Ocelot.Provider.Consul
然后注册服务
builder.Services.AddOcelot().AddPolly().AddConsul();
之后在配置文件中的GlobalConfiguration
节点下添加如下参数,这是必须的如果没有指定主机Host
和端口Port
将会使用Consul
默认的,Scheme
默认为http
,Type
说明此服务发现由Consul
提供
"ServiceDiscoveryProvider": { "Scheme": "http", "Host": "localhost", "Port": 8500, "Type": "Consul" }
然后我们设置路由,添加我们刚注册的服务,最好是配合负载均衡参数咯,我这里没写
"Routes": [ { "DownstreamPathTemplate": "/{everything}", "DownstreamScheme": "http", "ServiceName": "service-a", "UpstreamPathTemplate": "/api/{everything}", "UpstreamHttpMethod": [ "Get", "Post" ] }
然后运行就可以看到结果了,需要注意的是请求是http
还是https
这些需要注意,我就卡在了这里很久,请求路径需要注意噢
最后,Ocelot
是每次请求都去Consul
获取最新的服务,如果需要设置间隔多久去获取Consul
的最新服务(可能会有微小的性能改进,但是不知道原有服务是否可用,可能会有错误的返回噢)可以如下设置:
"ServiceDiscoveryProvider": { "Host": "localhost", "Port": 8500, "Type": "PollConsul", "PollingInterval": 100 }
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK