Consul 學習筆記—服務發現
阿新 • • 發佈:2020-10-19
前言:
上一篇文章簡單實用Consul試下服務註冊,本篇繼續學習Consul中的另外特性:服務發現、KV操作 ;以及對上篇文章中存在的問題進行解決
問題解決
在上一篇文章中,註冊服務提示檢查失敗。
通過排查發現為在docker 中執行的容器中配置的心跳檢查api地址配置錯誤:
"Consul": { "Address": "http://host.docker.internal:8500", "HealthCheck": "/api/healthcheck",//心跳檢查api地址 "Name": "czapigoods", "Ip": "host.docker.internal", "Port": "5602" //未指定成當前docker執行對於埠 }
解決方法(docker修改配置方式):修改docker中配置檔案appsettings.json:
- 進入docker命令列:docker exec -it 容器id /bin/bash 例如:docker exec -it f38a7a2ddfba /bin/bash
- 更新軟體列表:apt-get update
- 安裝vim命令:apt-get install vim
- 進入appsettings.json 修改:vim appsettings.json
- 修改appsettings中Consul.Port節點為對於docker對映埠
- 按Esc鍵,並輸入:wq命令(退出儲存修改)
- 重啟對於容器效果如下
Ps:Doker相關操作後面單獨詳細
服務發現
服務註冊問題解決了,接下來我們瞭解下服務如何發現;首先建立一個web專案Consul.Client並新增Consul包引用
Install-Package Consul
1、新增一個服務呼叫介面ICallService.cs用於呼叫我們新增的服務
public interface ICallService { /// <summary> /// 獲取 Goods Service 返回資料 /// </summary> /// <returns></returns> Task<string> GetGoodsService(); /// <summary> /// 獲取 Order Service 返回資料 /// </summary> /// <returns></returns> Task<string> GetOrderService(); /// <summary> /// 初始化服務 /// </summary> void InitServices(); }
2、實現該介面CallService.cs呼叫Goods、Order的api方法
public class CallService : ICallService { private readonly IConfiguration _configuration; private readonly ConsulClient _consulClient; private ConcurrentBag<string> _serviceAUrls; private ConcurrentBag<string> _serviceBUrls; private IHttpClientFactory _httpClient; public CallService(IConfiguration configuration, IHttpClientFactory httpClient) { _configuration = configuration; _consulClient = new ConsulClient(options => { options.Address = new Uri(_configuration["Consul:Address"]); }); _httpClient = httpClient; } public async Task<string> GetGoodsService() { if (_serviceAUrls == null) return await Task.FromResult("Goods Service Initializing..."); using var httpClient = _httpClient.CreateClient(); //隨機獲取一個服務地址呼叫 var serviceUrl = _serviceAUrls.ElementAt(new Random().Next(_serviceAUrls.Count())); Console.WriteLine("Goods Service:" + serviceUrl); var result = await httpClient.GetStringAsync($"{serviceUrl}/goods"); return result; } public async Task<string> GetOrderService() { if (_serviceBUrls == null) return await Task.FromResult("Order Service Initializing..."); using var httpClient = _httpClient.CreateClient(); //隨機獲取一個服務地址呼叫 var serviceUrl = _serviceBUrls.ElementAt(new Random().Next(_serviceBUrls.Count())); Console.WriteLine("Order Service:" + serviceUrl); var result = await httpClient.GetStringAsync($"{serviceUrl}/order"); return result; } public void InitServiceList() { var serviceNames = new string[] { "czapigoods", "czapiorder" }; foreach (var item in serviceNames) { Task.Run(async () => { var queryOptions = new QueryOptions { WaitTime = TimeSpan.FromMinutes(5) }; while (true) { await InitServicesAsync(queryOptions, item); } }); } } private async Task InitServicesAsync(QueryOptions queryOptions, string serviceName) { //獲取心跳檢查服務 var result = await _consulClient.Health.Service(serviceName, null, true, queryOptions); if (queryOptions.WaitIndex != result.LastIndex) { queryOptions.WaitIndex = result.LastIndex; var services = result.Response.Select(x => $"http://{x.Service.Address}:{x.Service.Port}"); if (serviceName == "czapigoods") { _serviceAUrls = new ConcurrentBag<string>(services); } else if (serviceName == "czapiorder") { _serviceBUrls = new ConcurrentBag<string>(services); } } } }
3、接下來新增介面依賴注入、以及服務初始化呼叫
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddHttpClient(); //依賴注入CallService services.AddSingleton<ICallService, CallService>(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ICallService service) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); //初始化服務列表呼叫 service.InitServiceList(); } }
4、使用Postman測試呼叫
KV操作
除了提供服務發現和健康檢查的整合.Consul提供了一個易用的鍵/值儲存.這可以用來保持動態配置,協助服務協調,領袖選舉,做開發者可以想到的任何事情.
1、建立/修改
- 命令方式:consul kv put key val 如:consul kv put port 9000 --新增key為port值為9000
- Http方式:
2、查詢
- 命令方式:consul kv get key 如:consul kv get port --查詢key為port的KV
- Http方式:value為baisc
3、刪除
- 命令方式:consul kv delete key 如:consul kv delete port --刪除key為port的KV
- Http方式:
其他
網上找了下:常用服務發現框架consul、zookeeper及etcd比較:
參考:
consul手冊:https://blog.csdn.net/liuzhuchen/article/details/81913562
https://www.consul.io/docs
https://www.consul.io/api/kv.html
github:
https://github.com/cwsheng/Consul.Demo