地球人家 發表於 2025-7-1 10:47:49

.Net中使用Consul实现服务高可用的方法

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">一、目的</a></li><li><a href="#_label1">二、Consul概述</a></li><li><a href="#_label2">三、安装和部署</a></li><ul class="second_class_ul"><li><a href="#_lab2_2_0">3.1 下载Consul</a></li><li><a href="#_lab2_2_1">3.2 安装和运行</a></li><li><a href="#_lab2_2_2">3.3 访问Consul的UI页面</a></li></ul><li><a href="#_label3">四、.Net中使用Consul</a></li><ul class="second_class_ul"><li><a href="#_lab2_3_3">4.1 安装Nuget包</a></li><li><a href="#_lab2_3_4">4.2 .Net注册服务</a></li><li><a href="#_lab2_3_5">4.3 服务健康检测</a></li><li><a href="#_lab2_3_6">4.4 服务使用</a></li></ul><li><a href="#_label4">五、调用Consul示例</a></li><ul class="second_class_ul"></ul><li><a href="#_label5">六、文章总结</a></li><ul class="second_class_ul"></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>一、目的</h2>
<p>在微服务架构中,为了保证服务的高可用,通常需要在服务使用中,通过负载均衡配置,来分发流量和提高系统可用性扩展系统服务的吞吐能力。并消除系统中的单点故障,提升应用系统的可用性。一般来说Nginx就可以实现负载均衡的功能。但是,因为Nginx无法灵活的动态添加服务,因此一般在微服务架构中,会通过一些中间件来实现,服务发现的框架常用的有:consul、zookeeper等。</p>
<p>这里主要介绍的是在.Net环境下Consul实现服务发现等相关功能。</p>
<p></p>
<p class="maodian"><a name="_label1"></a></p><h2>二、Consul概述</h2>
<p>Consul是一个分布式、高度可用的数据中心感知服务发现平台,包括简单的服务注册、运行状况检查、故障检测和密钥值存储。 它基于这样一个前提:数据中心中的每个节点都运行一个 Consul 代理,并充当服务器或客户端。 每个代理通过可缩放的 gossip 协议进行通信。</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202507/2025070110421036.png" /></p>
<p class="maodian"><a name="_label2"></a></p><h2>三、安装和部署</h2>
<p class="maodian"><a name="_lab2_2_0"></a></p><h3>3.1 下载Consul</h3>
<p>Consul官网地址:<a href="https://www.consul.io/" rel="external nofollow"   target="_blank" title="Consul | HashiCorp Developer">Consul | HashiCorp Developer</a>,Consul安装非常简单,在官网,点击download</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202507/2025070110420969.png" /></p>
<p><strong>ps:</strong>这里我们可以看到Consul支持多种操作系统可选,这里我们在window上测试,这里选择windows。</p>
<p class="maodian"><a name="_lab2_2_1"></a></p><h3>3.2 安装和运行</h3>
<p>Consul安装:下载后,解压即可。解压后只有一个consul.exe可执行文件。</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202507/2025070110420919.png" /></p>
<p>Consul运行命令如下(进入CMD命令行):</p>
<div class="jb51code"><pre class="brush:bash;">cd 对应盘符文件夹\consul_1.17.1_windows_amd64
//启动Consul
consul agent -dev
//设置ip地址访问-需要时配置
consul agent -dev -client=0.0.0.0</pre></div>
<p class="maodian"><a name="_lab2_2_2"></a></p><h3>3.3 访问Consul的UI页面</h3>
<p>启动后会显示如下内容:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202507/2025070110420926.png" /></p>
<p>浏览器中访问地址,<a href="http://localhost:8500/" rel="external nofollow"   title="http://localhost:8500/">http://localhost:8500/</a>判断Consul服务是否运行成功。</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202507/2025070110420945.png" /></p>
<p>ps:以上是Consul基本的单机部署,为保证高可用可以对Consul进行集群部署。</p>
<p class="maodian"><a name="_label3"></a></p><h2>四、.Net中使用Consul</h2>
<p class="maodian"><a name="_lab2_3_3"></a></p><h3>4.1 安装Nuget包</h3>
<p>在业务服务中Nuget安装: Consul,把业务服务注册到Consul中</p>
<div class="jb51code"><pre class="brush:bash;">dotnet add packages Consul</pre></div>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202507/2025070110420918.png" /></p>
<p class="maodian"><a name="_lab2_3_4"></a></p><h3>4.2 .Net注册服务</h3>
<p>把当前服务的相关地址信息,添加到Consul中:</p>
<div class="jb51code"><pre class="brush:csharp;">using Consul;
using Microsoft.Extensions.Configuration;
using System;
namespace MicroService.Framework;
public static class ConsulHelper
{
    /// &lt;summary&gt;
    /// Consul注册
    /// &lt;/summary&gt;
    /// &lt;param name="configuration"&gt;&lt;/param&gt;
    public static void ConsulRegist(this IConfiguration configuration)
    {
      //准备链接Consul的Client
      ConsulClient client = new ConsulClient(c =&gt;
      {
            c.Address = new Uri("http://localhost:8500/");
            c.Datacenter = "test1";
      });//找到consul
      string ip = string.IsNullOrWhiteSpace(configuration["ip"]) ? "127.0.0.1" : configuration["ip"];
      int port = string.IsNullOrWhiteSpace(configuration["port"]) ? 9001 : int.Parse(configuration["port"]);//命令行参数必须传入
      //int weight = string.IsNullOrWhiteSpace(configuration["weight"]) ? 1 : int.Parse(configuration["weight"]);
      client.Agent.ServiceRegister(new AgentServiceRegistration()
      {
            ID = "service" + Guid.NewGuid(),//唯一id
            Name = "test_server",//Group--分组
            Address = ip,
            Port = port,
            //Tags = new string[] { weight.ToString() },//标签
            Check = new AgentServiceCheck()
            {
                Interval = TimeSpan.FromSeconds(10),//间隔10s一次
                HTTP = $"http://{ip}:{port}/Api/Health/Index",//健康检测接口
                Timeout = TimeSpan.FromSeconds(3),//检测等待时间
                DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(60)//失败后多久移除
            }
      });
      //命令行参数获取
      Console.WriteLine($"注册成功:{ip}:{port}");
    }
}</pre></div>
<p>程序启动时注册一次:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202507/2025070110420946.png" /></p>
<p class="maodian"><a name="_lab2_3_5"></a></p><h3>4.3 服务健康检测</h3>
<p>增加一个健康检测接口,接口映射到管道中间件中处理,自定义返回结果:</p>
<div class="jb51code"><pre class="brush:csharp;">public static class HealthExtention
{
    public static void Health(this WebApplication app)
    {
      app.MapWhen(context =&gt; context.Request.Path.Equals("/Api/Health/Index"),
         applicationBuilder =&gt; applicationBuilder.Run(async context =&gt;
         {
             Console.WriteLine($"This is Health Check");
             context.Response.StatusCode = (int)HttpStatusCode.OK;
             await context.Response.WriteAsync("OK");
         }));
    }
}</pre></div>
<p class="maodian"><a name="_lab2_3_6"></a></p><h3>4.4 服务使用</h3>
<p>运行业务服务,使用端口来区分不同的业务逻辑</p>
<div class="jb51code"><pre class="brush:csharp;">dotnet run --urls=http://localhost:9001 --port=9001</pre></div>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202507/2025070110420946.png" /></p>
<p class="maodian"><a name="_label4"></a></p><h2>五、调用Consul示例</h2>
<p>客户端需要引用Consul的组件,正常微服务模式下,客户端只需要请求网关即可,请求通过网关会转发到其他服务层。</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202507/2025070110420962.png" /></p>
<p>客户端调用Consul中的服务示例</p>
<div class="jb51code"><pre class="brush:csharp;">//consul获取服务api/users/all也得知道
string url = null;
url = "http://test_server/api/users/all";//consul就像dns--只是负责解析ip:port--清单
ConsulClient client = new ConsulClient(c =&gt;
{
      c.Address = new Uri("http://localhost:8500/");
      c.Datacenter = "test1";
});
var response = client.Agent.Services().Result.Response;//获取服务清单
Uri uri = new Uri(url);
string groupName = uri.Host;
//服务实例
AgentService agentService = null;
var dictionary = response.Where(s =&gt; s.Value.Service.Equals(groupName, StringComparison.OrdinalIgnoreCase)).ToArray();
{
      //agentService = dictionary.Value;//写死第一个
}
{
      轮询策略 也是平均,但是太僵硬了
      agentService = dictionary.Value;
}
    //可自定义负载策略
url = $"{uri.Scheme}://{agentService.Address}:{agentService.Port}{uri.PathAndQuery}";
string content = InvokeApi(url);
var res = JsonConvert.DeserializeObject&lt;IEnumerable&lt;User&gt;&gt;(content);</pre></div>
<p class="maodian"><a name="_label5"></a></p><h2>六、文章总结</h2>
<p>在微服务架构中,使用Consul作为服务发现和配置管理的工具是非常常见的。Consul由HashiCorp开发,提供了一个完整的解决方案,其中包括服务发现、健康检查、键值存储以及多数据中心支持。</p>
<p>把之所学,以文载之~ 欢迎大家多多交流</p>
<p>相关引用:</p>
<blockquote><p><a href="https://zhuanlan.zhihu.com/p/701107409" rel="external nofollow"   target="_blank" title="https://zhuanlan.zhihu.com/p/701107409">https://zhuanlan.zhihu.com/p/701107409</a></p>
<p><a href="https://learn.microsoft.com/zh-cn/dotnet/orleans/deployment/consul-deployment" rel="external nofollow"   target="_blank" title="使用 Consul 作为成员管理器 - .NET | Microsoft Learn">使用 Consul 作为成员管理器 - .NET | Microsoft Learn</a></p></blockquote>
頁: [1]
查看完整版本: .Net中使用Consul实现服务高可用的方法