根據上一篇Consul服務的注冊和發現,那么客戶端如何去訪問我們的Consul服務?其實客戶端訪問Consul實際上是訪問Consul的服務實例。客戶端自己可以實現對Consul服務實例的輪訓,每次刷新端口都會發生改變,由於客戶端訪問Consul采用的輪訓策略,所以每次刷新Consul的服務實例都會發生改變。
下面就直接上客戶端訪問Consul服務實例的代碼:
using System; using System.Collections.Generic; using System.Text; namespace Demo { /// <summary> /// 用戶服務的接口定義。 /// </summary> public interface IUserService { /// <summary> /// 查找指定主鍵的用戶實例對象。 /// </summary> /// <param name="id">用戶的主鍵。</param> /// <returns>返回查找到的用戶實例對象。</returns> User FindUser(int id); /// <summary> /// 獲取所有用戶的實例集合。 /// </summary> /// <returns>返回所有的用戶實例。</returns> IEnumerable<User> UserAll(); } }
using System; using System.Collections.Generic; using System.Text; namespace Demo { /// <summary> /// 用戶模型。 /// </summary> public class User { /// <summary> /// 獲取或者設置用戶主鍵。 /// </summary> public int ID { get; set; } /// <summary> /// 獲取或者設置用戶姓名。 /// </summary> public string Name { get; set; } /// <summary> /// 獲取或者設置用戶賬號名稱。 /// </summary> public string Account { get; set; } /// <summary> /// 獲取或者設置用戶密碼。 /// </summary> public string Password { get; set; } /// <summary> /// 獲取或者設置用戶的電子郵箱地址。 /// </summary> public string Email { get; set; } /// <summary> /// 獲取或者設置用戶角色。 /// </summary> public string Role { get; set; } /// <summary> /// 獲取或者設置用戶的登錄時間。 /// </summary> public DateTime LoginTime { get; set; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Demo { /// <summary> /// 實現用戶服務接口的實現類型。 /// </summary> public class UserService : IUserService { private IList<User> dataList; /// <summary> /// 初始化類型的實例 /// </summary> public UserService() { dataList = new List<User>() { new User {ID=1,Name="張三",Account="5435435345",Password="4535435435",Email="4535345345", Role="Admin", LoginTime=DateTime.Now}, new User {ID=2,Name="李四",Account="5435435345",Password="5435345345",Email="543534535", Role="Admin", LoginTime=DateTime.Now.AddDays(-5) }, new User { ID = 3, Name = "王二", Account = "45354", Password = "3245345", Email = "54353455", Role = "Admin", LoginTime = DateTime.Now.AddDays(-30) }, new User { ID = 4, Name = "麻子", Account = "45354", Password = "4534535", Email = "453534534", Role = "Admin", LoginTime = DateTime.Now.AddDays(-90) }, new User { ID = 5, Name = "陳五", Account = "54353", Password = "5435345", Email = "5435345345", Role = "Admin", LoginTime = DateTime.Now.AddMinutes(-50) } }; } /// <summary> /// 查找指定主鍵的用戶實例對象。 /// </summary> /// <param name="id">用戶的主鍵。</param> /// <returns>返回查找到的用戶實例對象。</returns> public User FindUser(int id) { return dataList.FirstOrDefault(user => user.ID == id); } /// <summary> /// 獲取所有用戶的實例集合。 /// </summary> /// <returns>返回所有的用戶實例。</returns> public IEnumerable<User> UserAll() { return dataList; } } }
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using ConsulDemo.Models; using Microsoft.Extensions.Logging; using Demo; using Consul; using System.Net.Http; namespace ConsulDemo.Controllers { public class HomeController : Controller { private readonly ILogger<HomeController> _logger; private readonly IUserService _userService; private static int index; /// <summary> /// 初始化該類型的新實例。 /// </summary> /// <param name="logger">注入日志對象。</param> /// <param name="userService">注入用戶服務對象。</param> public HomeController(ILogger<HomeController> logger, IUserService userService) { _logger = logger; _userService = userService; } /// <summary> /// 首頁。 /// </summary> /// <returns></returns> public IActionResult Index() { #region 分布式架構 #region 通過 Consul 服務發現來執行服務實例。 //發現服務 string url = "http://PatrickLiuService/api/users/all"; ConsulClient client = new ConsulClient(config => { config.Address = new Uri("http://localhost:8500/"); config.Datacenter = "dc1"; }); var response = client.Agent.Services().Result.Response; foreach (var item in response) { Console.WriteLine("*************************************************************"); Console.WriteLine(item.Key); var service = item.Value; Console.WriteLine($"{service.Address}--{service.Port}--{service.Service}"); Console.WriteLine("*************************************************************"); } Uri uri = new Uri(url); string groupName = uri.Host; AgentService agentService = null; var serviceDirectory = response.Where(s => s.Value.Service.Equals(groupName, StringComparison.OrdinalIgnoreCase)).ToArray(); //{//1、 寫死的 // agentService = serviceDirectory[0].Value; //} { //2、輪詢 if (index >= 10000) { index = 0; } agentService = serviceDirectory[index++ % serviceDirectory.Length].Value; } // {//3、隨機 // var indexResult = new Random(index++).Next(0, serviceDirectory.Length); // agentService = serviceDirectory[indexResult].Value; //} url = $"{uri.Scheme}://{agentService.Address}:{agentService.Port}{uri.PathAndQuery}"; #endregion string content = InvokeAPI(url); this.ViewBag.Users = Newtonsoft.Json.JsonConvert.DeserializeObject<IEnumerable<User>>(content); Console.WriteLine($"This is {url} Invoke."); #endregion return View(); } /// <summary> /// 封裝 HttpClient 實例,提供 Http 調用。 /// </summary> /// <param name="url">http url 的地址。</param> /// <returns>返回結束數據,格式:JSON。</returns> public static string InvokeAPI(string url) { using (HttpClient client = new HttpClient()) { HttpRequestMessage message = new HttpRequestMessage(); message.Method = HttpMethod.Get; message.RequestUri = new Uri(url); var result = client.SendAsync(message).Result; string conent = result.Content.ReadAsStringAsync().Result; return conent; } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Demo; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; namespace ConsulDemo { 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.Configure<CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddSingleton<IUserService, UserService>(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseCookiePolicy(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); } } }
啟動Consul:
Consul啟動命令:Consul agent –dev

啟動5個服務實例端口分別為:1000,2000,3000,4000,5000

Consul實例:


然后啟動客戶端,訪問Consul服務實例:
第一次啟動:端口1000

第一次刷新端口為:2000

第二次刷新端口為:3000

目前為止 雖然可以自由的發現新服務,也可以發現失敗的服務,實現了服務的自動注冊和發現,但是Consul另外一個問題就是,客戶端使用太麻煩,我們需要自己去決定調用服務策略,是輪訓、隨機、權重,還是其他策略,如果項目很小不是問題,如果項目很大,需求變化很快,我們都需要手動去做這些事,就太浪費時間和精力了。
