Ocelot + Consul + Registrator 基于Docker 实现服务发现、服务自动注册
目录
-internal选项
关于这个工具的介绍这里就不多说了,网上、官网都很详细,这里直接记录一下搭建过程。另外最后有几个疑惑还未解决,希望各位前辈答疑解惑。
1. Consul集群搭建
我们基于Docker搭建三个Server和两个Client的DC。
- server1
docker run -d --name server1 consul agent -server -node=server1 -bootstrap-expect=3 # 获取server1IP地址,方便后续节点接入集群 JOIN_IP="$(sudo docker inspect -f '{{.NetworkSettings.IPAddress}}' server1)"
- server2
docker run -d --name server2 consul agent -server -node=server2 -join $JOIN_IP
- server3
docker run -d --name server3 consul agent -server -node=server3 -join $JOIN_IP
- client1
docker run -d --name client1 consul agent -node=client1 -join $JOIN_IP
- client2
docker run -d --name client2 -p 8400:8400 -p 8500:8500 -p 8600:53/udp consul agent -ui -node=client2 -client=0.0.0.0 -join $JOIN_IP
运行效果:
1.1 F&Q
Consul官方推荐的host网络模式运行
查看Consul官方文档,官方推荐Consul以Docker的host网络模式运行。但是这样的话,一个Docker寄宿主机只运行一个consul agent?生产中的Docker集群是如何搭建的?
2. Registrator服务注册工具
启动Registrator工具容器,Registrator使用主机网络模式,使用
-internal选项,注册基于expose端口的服务。
docker run -d --name registrator --net host --volume=/var/run/docker.sock:/tmp/docker.sock gliderlabs/registrator -internal consul://172.17.0.6:8500
Consul管理UI服务截图,Registrator会把Consul也作为服务注册到Consul。这也是可以理解的,因为Registrator的观点是任何监听在端口的程序都是服务。
2.1 F&Q
Registrator悬挂服务
正常情况下,这里应该是没有clientservice的,但是由于我之前测试没有正常按顺序启停容器,形成了悬挂服务,一直没有清除。我看Registrator文档中有
-cleanup选项可以清理悬挂服务,后续尝试一下。
Registrator的-internal
选项
不指定这个选项时,Registrator使用容器的发布端口(映射到寄宿主机的端口)自动注册服务,这时候一般要用
-ip选项指定主机的IP地址,因为Registrator一般很难推断出主机的IP地址。当使用-internal选项时,Registrator使用服务所在容器分配的内部地址自动注册服务。
3. clientservice服务Demo
clientservice是一个web api项目,由于是自动服务发现和注册,因此clientservice跟无需做特别的配置。
我仅仅指定服务的端口为5000,修改了ValueController,返回服务调用情况。
3.1 Program.cs
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseUrls("http://*:5000") .UseStartup<Startup>(); }
3.2 ValuesController.cs
... [HttpGet] public ActionResult<RequestInfo> Get() { var clientHost = HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString(); var serverHost = HttpContext.Connection.LocalIpAddress.MapToIPv4().ToString(); var path = HttpContext.Request.Path; return new RequestInfo{ RemoteIp = clientHost, RemotePort = HttpContext.Connection.RemotePort, LocalIp = serverHost, LocalPort = HttpContext.Connection.LocalPort, Path = path, Host = HttpContext.Request.Host.ToUriComponent() }; } ...
3.3 Dockerfile
#基于microsoft/dotnet:latest构建Docker image FROM microsoft/dotnet:latest #进入docker中的/usr/local/src目录,创建DockerWebAPI目录 RUN cd /usr/local/src&&mkdir DockerWebAPI #设置工作路径 WORKDIR /usr/local/src/DockerWebAPI #将当前文件夹下的所有文件全部复制到工作目录 COPY ./ ./ #向外界暴露5000端口 EXPOSE 5000 #执行dotnet *.dll命令 CMD ["dotnet","clientservice.dll"]
3.4 制作镜像并启动容器
- 制作镜像
docker build -t zhangdk/clientservice .
- 启动容器
docker run -d zhangdk/clientservice
Consul管理UI截图,如果你是第一次搭建集群并启动Clientservice的话,后面应该有小标1。我这里由于悬挂服务的问题,有启动前的1现在变成了2。
clientservice注册信息(多余的是悬挂服务的注册信息),要注意查看ServiceAddress和ServicePort是否正确:
4. Ocelot网关Demo
VS Code创建空web项目
dotnet new web,安装ocelot库
dot add package ocelot,主要修改三个文件:
4.1 Program.cs:
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .UseUrls("http://*:5010") //服务监听在5010端口,后期可以调整为从外部读取,方便配置 .ConfigureAppConfiguration((context,builder)=>{ builder.AddJsonFile("configuration.json",false,true); //读取Ocelot配置文件 }); }
4.2 Startup.cs:
public class Startup { public Startup(IConfiguration configuration){ Configuration = configuration; } public IConfiguration Configuration{get;set;} public void ConfigureServices(IServiceCollection services) => services.AddOcelot(Configuration); //注册Ocelot服务 public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseOcelot().Wait(); //启用Ocelot中间件 } }
4.3 添加配置文件configuration.json:
{ "ReRoutes": [ { "UseServiceDiscovery": true, //启用服务发现 "DownstreamPathTemplate": "/api/{url}", "DownstreamScheme": "http", "ServiceName": "clientservice", "LoadBalancerOptions": { "Type": "RoundRobin" }, "UpstreamPathTemplate": "/api/clientservice/{url}", "UpstreamHttpMethod": [ "Get", "Post" ], "ReRoutesCaseSensitive": false } ], "GlobalConfiguration": { "ServiceDiscoveryProvider": { "Host": "172.17.0.6", //Consul client IP "Port": 8500 //Consul HTTP API端口 } } }
4.4 Dockerfile文件编写
#基于microsoft/dotnet:latest构建Docker image FROM microsoft/dotnet:latest #进入docker中的/usr/local/src目录,创建DockerWebAPI目录 RUN cd /usr/local/src&&mkdir DockerWebAPI #设置工作路径 WORKDIR /usr/local/src/DockerWebAPI #将当前文件夹下的所有文件全部复制到工作目录 COPY ./ ./ #向外界暴露5010端口 EXPOSE 5010 #执行dotnet *.dll命令 CMD ["dotnet","oceletgateway.dll"]
4.5 发布项目,制作镜像,并启动容器
- 发布项目
dotnet publish
- 拷贝Dockfile到Demo的publish文件夹,打开终端
docker build -t zhangdk/ocelotgateway .
- 运行OcelotGateway服务容器
docker run -d --name=ocelotgateway zhangdk/ocelotgateway
通过Ocelot网关服务访问clientservice
直接访问clientservice
4.6 F&Q
Ocelot服务发现地址怎么配置
刚开始的我以为应该配置Leader server的地址,但是由于leader server的端口并没有暴露,因此容器间无法访问。尝试使用client的地址,发现也是可以成功的。
Ocelot的服务发现地址配置
Consul在集群模式运行时,单个server或者client agent节点挂掉后仍然可以通过投票等协议正常运行。但是,Ocelot网关服务中配置了唯一的一个agent地址,那岂不是意味着这个节点挂掉后,Ocelot网关服务就和Consul集群的服务发现就失去了联系,那这里的Consul集群有什么意义?
5 总结
初步按照自己的思路搭建起来的服务发现,自动注册的架构,后续会继续完善权限验证、负载均衡等网关的其他功能。搭建的过程中也有许多困惑还没有想明白,后续边想边做。微服务这一块也是刚刚接触,有什么问题或错误,还希望各位前辈指正。
- docker基于consule和registrator实现服务的发现和注册
- 基于Consul+Registrator+Nginx实现容器服务自动发现的集群框架 推荐
- .net core微服务之基于Docker+Consul+Registrator服务注册服务发现
- Docker集群实验环境布署--swarm【3 注册服务监控与自动发现组件--consul】
- 使用Docker搭建consul集群+registrator实现服务自动注册。
- 服务注册发现consul之四: 分布式锁之四:基于Consul的KV存储和分布式信号量实现分布式锁
- docker深入2-使用registrator和consul-template自动注册和变更服务
- 基于 Consul 实现 MagicOnion(GRpc) 服务注册与发现
- 使用Docker搭建consul集群+registrator实现服务自动注册。
- Docker+Jenkins持续集成环境(4):使用etcd+confd实现容器服务注册与发现
- 使用consul实现分布式服务注册和发现
- spring cloud搭建微服务second-fiberhome(二):结合consul实现服务注册与服务发现
- Consul + fabio 实现自动服务发现、负载均衡 - DockOne.io
- 详解Spring Cloud Consul 实现服务注册和发现
- 简单RPC框架-基于Consul的服务注册与发现
- 服务注册发现consul之二:使用Spring Cloud Consul实现服务的注册和发现
- 详解使用Spring Cloud Consul实现服务的注册和发现
- 使用consul实现分布式服务注册和发现--redis篇
- 使用Spring Cloud Consul实现服务的注册和发现
- Spring Cloud Consul 实现服务注册和发现