Consul 服務(wù)的注冊(cè)和發(fā)現(xiàn)
點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”
優(yōu)質(zhì)文章,第一時(shí)間送達(dá)
作者 | 代碼如風(fēng)~~~
來(lái)源 | urlify.cn/UnQnMz
Consul 是Hashicorp公司推出的開(kāi)源工具,用于實(shí)現(xiàn)分布式系統(tǒng)的服務(wù)發(fā)現(xiàn)與配置。Consul是分布式的,高可用的,可橫向擴(kuò)展的。
Consul 的主要特點(diǎn)有:
Service Discovery : 服務(wù)注冊(cè)與發(fā)現(xiàn),Consul 的客戶(hù)端可以做為一個(gè)服務(wù)注冊(cè)到 Consul,也可以通過(guò) Consul 來(lái)查找特定的服務(wù)提供者,并且根據(jù)提供的信息進(jìn)行調(diào)用。
Health Checking: Consul 客戶(hù)端會(huì)定期發(fā)送一些健康檢查數(shù)據(jù)和服務(wù)端進(jìn)行通訊,判斷客戶(hù)端的狀態(tài)、內(nèi)存使用情況是否正常,用來(lái)監(jiān)控整個(gè)集群的狀態(tài),防止服務(wù)轉(zhuǎn)發(fā)到故障的服務(wù)上面。
KV Store: Consul 還提供了一個(gè)容易使用的鍵值存儲(chǔ)。這可以用來(lái)保持動(dòng)態(tài)配置,協(xié)助服務(wù)協(xié)調(diào)、建立 Leader 選舉,以及開(kāi)發(fā)者想構(gòu)造的其它一些事務(wù)。
Secure Service Communication: Consul 可以為服務(wù)生成分布式的 TLS 證書(shū),以建立相互的 TLS 連接。可以使用 intentions 定義允許哪些服務(wù)進(jìn)行通信。可以使用 intentions 輕松管理服務(wù)隔離,而不是使用復(fù)雜的網(wǎng)絡(luò)拓 撲和靜態(tài)防火墻規(guī)則。
Multi Datacenter: Consul 支持開(kāi)箱即用的多數(shù)據(jù)中心,這意味著用戶(hù)不需要擔(dān)心需要建立額外的抽象層讓業(yè)務(wù)擴(kuò)展到多個(gè)區(qū)域。
Consul 角色
Server: 服務(wù)端, 保存配置信息, 高可用集群, 在局域網(wǎng)內(nèi)與本地客戶(hù)端通訊, 通過(guò)廣域網(wǎng)與其它數(shù)據(jù)中心通訊。每個(gè)數(shù)據(jù)中心的 Server 數(shù)量推薦為 3 個(gè)或是 5 個(gè)。
Client: 客戶(hù)端, 無(wú)狀態(tài), 將 HTTP 和 DNS 接口請(qǐng)求轉(zhuǎn)發(fā)給局域網(wǎng)內(nèi)的服務(wù)端集群。
Consul 旨在對(duì) DevOps 社區(qū)和應(yīng)用程序開(kāi)發(fā)人員友好,使其成為現(xiàn)代、彈性基礎(chǔ)架構(gòu)的理想選擇。

首先下載Consul服務(wù)組件:官網(wǎng)下載:https://www.consul.io/downloads

啟動(dòng)Consul:

根據(jù)啟動(dòng)后的http顯示端口8500端口:

通過(guò)瀏覽器查看 Consul服務(wù)中心是否啟動(dòng)成功,地址:http://localhost:8500,如果成功,效果如下:

然后創(chuàng)建一個(gè)服務(wù)端實(shí)例工程:

添加必要的測(cè)試類(lèi):
using System;
using System.Collections.Generic;
using System.Text;
namespace Demo
{
/// <summary>
/// 用戶(hù)模型。
/// </summary>
public class User
{
/// <summary>
/// 獲取或者設(shè)置用戶(hù)主鍵。
/// </summary>
public int ID { get; set; }
/// <summary>
/// 獲取或者設(shè)置用戶(hù)姓名。
/// </summary>
public string Name { get; set; }
/// <summary>
/// 獲取或者設(shè)置用戶(hù)賬號(hào)名稱(chēng)。
/// </summary>
public string Account { get; set; }
/// <summary>
/// 獲取或者設(shè)置用戶(hù)密碼。
/// </summary>
public string Password { get; set; }
/// <summary>
/// 獲取或者設(shè)置用戶(hù)的電子郵箱地址。
/// </summary>
public string Email { get; set; }
/// <summary>
/// 獲取或者設(shè)置用戶(hù)角色。
/// </summary>
public string Role { get; set; }
/// <summary>
/// 獲取或者設(shè)置用戶(hù)的登錄時(shí)間。
/// </summary>
public DateTime LoginTime { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace Demo
{
/// <summary>
/// 用戶(hù)服務(wù)的接口定義。
/// </summary>
public interface IUserService
{
/// <summary>
/// 查找指定主鍵的用戶(hù)實(shí)例對(duì)象。
/// </summary>
/// <param name="id">用戶(hù)的主鍵。</param>
/// <returns>返回查找到的用戶(hù)實(shí)例對(duì)象。</returns>
User FindUser(int id);
/// <summary>
/// 獲取所有用戶(hù)的實(shí)例集合。
/// </summary>
/// <returns>返回所有的用戶(hù)實(shí)例。</returns>
IEnumerable<User> UserAll();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Demo
{
/// <summary>
/// 實(shí)現(xiàn)用戶(hù)服務(wù)接口的實(shí)現(xiàn)類(lèi)型。
/// </summary>
public class UserService : IUserService
{
private IList<User> dataList;
/// <summary>
/// 初始化類(lèi)型的實(shí)例
/// </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>
/// 查找指定主鍵的用戶(hù)實(shí)例對(duì)象。
/// </summary>
/// <param name="id">用戶(hù)的主鍵。</param>
/// <returns>返回查找到的用戶(hù)實(shí)例對(duì)象。</returns>
public User FindUser(int id)
{
return dataList.FirstOrDefault(user => user.ID == id);
}
/// <summary>
/// 獲取所有用戶(hù)的實(shí)例集合。
/// </summary>
/// <returns>返回所有的用戶(hù)實(shí)例。</returns>
public IEnumerable<User> UserAll()
{
return dataList;
}
}
}
using Consul;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Text;
namespace Demo
{
/// <summary>
/// Consul 靜態(tài)擴(kuò)展類(lèi)。
/// </summary>
public static class ConsulExtension
{
/// <summary>
///類(lèi)型初始化器,初始化 Consul 網(wǎng)址和數(shù)據(jù)中心。
/// </summary>
static ConsulExtension()
{
Uri = new Uri("http://localhost:8500");
DataCenter = "dc1";
}
/// <summary>
/// 獲取或者設(shè)置 Consul 的網(wǎng)址。
/// </summary>
public static Uri Uri { get; set; }
/// <summary>
/// 獲取或者設(shè)置數(shù)據(jù)中心。
/// </summary>
public static string DataCenter { get; set; }
/// <summary>
/// 向 Consul 服務(wù)中心注冊(cè)服務(wù)實(shí)例。
/// </summary>
/// <param name="configuration">配置對(duì)象。</param>
/// <param name="consulServiceName">在 Consul 服務(wù)中心注冊(cè)的服務(wù)類(lèi)別名稱(chēng),多個(gè)實(shí)例的 ID 可以屬于一個(gè)服務(wù)類(lèi)別名稱(chēng)。</param>
/// <param name="serviceID">服務(wù)實(shí)例的主鍵值,必須唯一。</param>
public static void ConsulRegist(this IConfiguration configuration, string consulServiceName, string serviceID)
{
if (string.IsNullOrEmpty(consulServiceName) || string.IsNullOrWhiteSpace(consulServiceName))
{
throw new ArgumentNullException("consulServiceName is null");
}
if (string.IsNullOrEmpty(serviceID) || string.IsNullOrWhiteSpace(serviceID))
{
throw new ArgumentNullException("serviceID is null.");
}
using (ConsulClient client = new ConsulClient(config =>
{
config.Address = Uri;
config.Datacenter = DataCenter;
}))
{
string ip = configuration["ip"];
int port = int.Parse(configuration["port"]);
int weight = string.IsNullOrWhiteSpace(configuration["weight"]) ? 1 : int.Parse(configuration["weight"]);
client.Agent.ServiceRegister(new AgentServiceRegistration()
{
ID = serviceID,
Name = consulServiceName,
Address = ip,
Port = port,
Tags = new string[] { weight.ToString() },
Check = new AgentServiceCheck()
{
Interval = TimeSpan.FromSeconds(12),
HTTP = $"http://{ip}:{port}/API/Health/Index",
Timeout = TimeSpan.FromSeconds(5),
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(20)
}
}).Wait();
Console.WriteLine($"注冊(cè)服務(wù):{ip}:{port}--Weight:{weight}");
};
}
/// <summary>
/// 向 Consul 服務(wù)中心注銷(xiāo)服務(wù)實(shí)例。
/// </summary>
/// <param name="applicationLifetime">配置對(duì)象。</param>
/// <param name="serviceID">服務(wù)實(shí)例的主鍵值,必須唯一。</param>
public static void ConsulDown(this IApplicationLifetime applicationLifetime, string serviceID)
{
if (string.IsNullOrEmpty(serviceID) || string.IsNullOrWhiteSpace(serviceID))
{
throw new ArgumentNullException("serviceID is null");
}
applicationLifetime.ApplicationStopped.Register(() =>
{
using (var consulClient = new ConsulClient(config => { config.Address = Uri; config.Datacenter = DataCenter; }))
{
Console.WriteLine("服務(wù)已經(jīng)退出");
consulClient.Agent.ServiceDeregister(serviceID);
}
});
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
namespace ConsulAPIDemo.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class HealthController : ControllerBase
{
private IConfiguration _configuration;
/// <summary>
/// 初始化該類(lèi)型的新實(shí)例。
/// </summary>
/// <param name="configuration">配置接口。</param>
public HealthController(IConfiguration configuration)
{
_configuration = configuration;
}
/// <summary>
/// 要調(diào)用的接口。
/// </summary>
[HttpGet]
[Route("Index")]
public IActionResult Index()
{
Console.WriteLine($"This is HealhController {_configuration["port"]} Invoke");
return Ok();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Demo;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace ConsulAPIDemo.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
/// <summary>
/// 用戶(hù)的 API 類(lèi)型。
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class UsersController : ControllerBase
{
#region 私有字段
private readonly ILogger<UsersController> _logger;
private readonly IUserService _userService;
private IConfiguration _configuration;
#endregion
#region 構(gòu)造函數(shù)
/// <summary>
/// 初始化該類(lèi)型的新實(shí)例。
/// </summary>
/// <param name="logger">日志記錄器。</param>
/// <param name="userService">用戶(hù)服務(wù)接口。</param>
/// <param name="configuration">配置服務(wù)。</param>
public UsersController(ILogger<UsersController> logger, IUserService userService, IConfiguration configuration)
{
_logger = logger;
_userService = userService;
_configuration = configuration;
}
#endregion
#region 實(shí)例方法
/// <summary>
/// 獲取一條記錄
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpGet]
[Route("Get")]
public User Get(int id)
{
return _userService.FindUser(id);
}
/// <summary>
/// 獲取所有記錄。
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("All")]
//[Authorize]
public IEnumerable<User> Get()
{
Console.WriteLine($"This is UsersController {this._configuration["port"]} Invoke");
return this._userService.UserAll().Select((user => new User
{
ID = user.ID,
Name = user.Name,
Account = user.Account,
Password = user.Password,
Email = user.Email,
Role = $"{this._configuration["ip"]}:{this._configuration["port"]}",
LoginTime = user.LoginTime
})); ;
}
/// <summary>
/// 超時(shí)處理
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("Timeout")]
public IEnumerable<User> Timeout()
{
Console.WriteLine($"This is Timeout Start");
//超時(shí)設(shè)置。
Thread.Sleep(3000);
Console.WriteLine($"This is Timeout End");
return this._userService.UserAll().Select((user => new User
{
ID = user.ID,
Name = user.Name,
Account = user.Account,
Password = user.Password,
Email = user.Email,
Role = $"{this._configuration["ip"]}:{this._configuration["port"]}",
LoginTime = user.LoginTime
})); ;
}
#endregion
}
}
}
startup里面的配置:
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.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace ConsulAPIDemo
{
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.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, Microsoft.AspNetCore.Hosting.IHostingEnvironment env, Microsoft.Extensions.Hosting.IApplicationLifetime applicationLifetime)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
#region Consul 注冊(cè),需要增加的
string serviceID = $"Service:{Configuration["ip"]}:{Configuration["port"]}---{Guid.NewGuid()}";
string consuleServiceName = "PatrickLiuService";
//注冊(cè)服務(wù)。
Configuration.ConsulRegist(consuleServiceName, serviceID);
//注銷(xiāo)服務(wù)
applicationLifetime.ConsulDown(serviceID);
#endregion
app.UseHttpsRedirection();
app.UseMvc();
}
}
}
編譯一下,根據(jù)不同端口啟動(dòng)api接口服務(wù):
API端口設(shè)置為2000:

API端口設(shè)置為3000:

注冊(cè)四個(gè)實(shí)例:

上面整個(gè)過(guò)程已經(jīng)完成了服務(wù)的注冊(cè),至于發(fā)現(xiàn)自己可以測(cè)一下,自己關(guān)掉一個(gè)服務(wù),Consul會(huì)自動(dòng)檢查各個(gè)服務(wù)的健康度,如果哪個(gè)服務(wù)出現(xiàn)異常,consul會(huì)自動(dòng)剔除異常服務(wù)。
粉絲福利:Java從入門(mén)到入土學(xué)習(xí)路線(xiàn)圖
??????

??長(zhǎng)按上方微信二維碼 2 秒
感謝點(diǎn)贊支持下哈 
