.NET微服務從0到1:服務註冊與發現(Consul)
- 2020 年 3 月 8 日
- 筆記
Consul搭建
基於Docker搭建Consul
以下為單機環境構建腳本,用於本機測試,生產環境中應當進行集群搭建
version: '3' services: consul: image: consul:1.7.1 container_name: consul volumes: - /c/docker/consul/data:/consul/data - /c/docker/consul:/consul/config ports: - 8300:8300 - 8301:8301 - 8301:8301/udp - 8302:8302 - 8302:8302/udp - 8400:8400 - 8500:8500 - 53:53/udp command: agent -server -bind=0.0.0.0 -client=0.0.0.0 -node=consul_Server1 -bootstrap-expect=1 -ui
成功搭建後,訪問8500埠,你可以看到如下介面
基於Windows搭建Consul
點擊下載Consul
執行以下命令運行consul
consul agent -dev
ServiceA集成Consul做服務註冊
配置前一篇文章中的ServiceA
Install-Package Consul -Version 0.7.2.6
- Consul配置模型
public class ServiceDisvoveryOptions { public string ServiceName { get; set; } public ConsulOptions Consul { get; set; } } public class ConsulOptions { public string HttpEndpoint { get; set; } public DnsEndpoint DnsEndpoint { get; set; } } public class DnsEndpoint { public string Address { get; set; } public int Port { get; set; } public IPEndPoint ToIPEndPoint() { return new IPEndPoint(IPAddress.Parse(Address), Port); } }
- 添加appsetting.json
"ServiceDiscovery": { "ServiceName": "ServiceA", "Consul": { "HttpEndpoint": "http://127.0.0.1:8500", "DnsEndpoint": { "Address": "127.0.0.1", "Port": 8600 } } }
- Consul服務註冊實現
private void ConfigureConsul(IApplicationBuilder app, IOptions<ServiceDisvoveryOptions> serviceOptions, IConsulClient consul, IHostApplicationLifetime lifetime) { var features = app.Properties["server.Features"] as FeatureCollection; var addresses = features.Get<IServerAddressesFeature>() .Addresses .Select(p => new Uri(p)); foreach (var address in addresses) { var serviceId = $"{serviceOptions.Value.ServiceName}_{address.Host}:{address.Port}"; var httpCheck = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromMinutes(1), Interval = TimeSpan.FromSeconds(30), HTTP = new Uri(address, "health").OriginalString }; var registration = new AgentServiceRegistration() { Checks = new[] { httpCheck }, Address = address.Host, ID = serviceId, Name = serviceOptions.Value.ServiceName, Port = address.Port }; consul.Agent.ServiceRegister(registration).GetAwaiter().GetResult(); lifetime.ApplicationStopping.Register(() => { consul.Agent.ServiceDeregister(serviceId).GetAwaiter().GetResult(); }); } }
- 配置服務到DI容器
public void ConfigureServices(IServiceCollection services) { services.AddOptions(); services.Configure<ServiceDisvoveryOptions>(Configuration.GetSection("ServiceDiscovery")); services.AddSingleton<IConsulClient>(p => new ConsulClient(cfg => { var serviceConfiguration = p.GetRequiredService<IOptions<ServiceDisvoveryOptions>>().Value; if (!string.IsNullOrEmpty(serviceConfiguration.Consul.HttpEndpoint)) { // if not configured, the client will use the default value "127.0.0.1:8500" cfg.Address = new Uri(serviceConfiguration.Consul.HttpEndpoint); } })); services.AddHealthChecks(); services.AddControllers(); }
- 將Consul相關配置添加到管道
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IOptions<ServiceDisvoveryOptions> serviceDisvoveryOptions, IConsulClient consul, IHostApplicationLifetime lifetime) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseAuthorization(); ConfigureConsul(app, serviceDisvoveryOptions, consul, lifetime); app.UseHealthChecks("/health"); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
- 運行ServiceA
可以看到健康檢查已通過,並且服務ServiceA已成功註冊到Consul
Ocelot集成Consul做服務發現
安裝nuget包依賴
Install-Package Ocelot.Provider.Consul -Version 14.0.11
在上一篇文章的基礎上,我們先修改ocelot.json
刪除了ServiceA路由中的DownstreamHostAndPorts寫死的地址和埠,改為使用Consul服務發現
{ "ReRoutes": [ { "DownstreamPathTemplate": "/{url}", "DownstreamScheme": "http", "UpstreamPathTemplate": "/service-a/{url}", "UpstreamHttpMethod": [ "Get", "Post" ], "AuthenticationOptions": { "AuthenticationProviderKey": "SampleKey", "AllowedScopes": [ "gateway_api" ] }, "ServiceName": "ServiceA", "LoadBalancerOptions": { "Type": "LeastConnection" } } ], "GlobalConfiguration": { "BaseUrl": "http://localhost", "ServiceDiscoveryProvider": { "Host": "localhost", "Port": 8500, "Type": "Consul" } } }
向容器中添加Consul服務
public void ConfigureServices(IServiceCollection services) { services.AddOcelot() .AddConsul(); }
啟動各個服務,查看結果
可以看到已成功執行
更多參考
Consul
Service Discovery And Health Checks In ASP.NET Core With Consul