当前位置: 首页 > news >正文

在 C# 中使用 Consul 客户端库实现服务发现

在 C# 中使用 Consul 客户端库实现服务发现,主要通过查询 Consul 服务器获取指定服务的健康实例列表。以下是详细的实现步骤和代码示例:

实现步骤

  1. 安装 Consul 客户端库(已安装可跳过):

    dotnet add package Consul
    
  2. 核心逻辑

    • 创建 Consul 客户端连接
    • 调用 Consul API 查询指定服务的健康实例
    • 处理返回结果,提取可用服务地址

完整代码实现

using Consul;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;/// <summary>
/// Consul 服务发现工具类
/// </summary>
public class ConsulServiceDiscoverer
{private readonly ConsulClient _consulClient;/// <summary>/// 初始化服务发现器/// </summary>/// <param name="consulServerAddresses">Consul 服务器地址列表(支持集群)</param>public ConsulServiceDiscoverer(params string[] consulServerAddresses){if (consulServerAddresses == null || !consulServerAddresses.Any()){// 默认连接本地 Consul 服务consulServerAddresses = new[] { "http://localhost:8500" };}_consulClient = new ConsulClient(config =>{config.Address = new Uri(consulServerAddresses.First());// 如需配置多个 Consul 服务器(高可用),可添加以下代码// config.SecondaryAddresses = consulServerAddresses.Skip(1).Select(uri => new Uri(uri)).ToList();});}/// <summary>/// 发现指定服务的所有健康实例/// </summary>/// <param name="serviceName">服务名称(必须与注册时一致)</param>/// <param name="tag">筛选标签(null 表示不筛选)</param>/// <returns>健康服务实例列表(地址+端口)</returns>public async Task<List<ServiceInstance>> DiscoverHealthyServicesAsync(string serviceName, string tag = null){try{// 调用 Consul API 查询健康服务实例var queryResult = await _consulClient.Health.Service(service: serviceName,tag: tag,passingOnly: true, // 只返回通过健康检查的实例queryOptions: new QueryOptions { WaitTime = TimeSpan.FromSeconds(10) });if (queryResult.Response == null || !queryResult.Response.Any()){throw new KeyNotFoundException($"未找到服务 {serviceName} 的健康实例");}// 转换为自定义服务实例对象return queryResult.Response.Select(s => new ServiceInstance{ServiceId = s.Service.ID,ServiceName = s.Service.Service,Address = s.Service.Address,Port = s.Service.Port,Tags = s.Service.Tags?.ToList() ?? new List<string>(),FullAddress = $"{s.Service.Address}:{s.Service.Port}"}).ToList();}catch (Exception ex){Console.WriteLine($"服务发现失败:{ex.Message}");throw;}}/// <summary>/// 从服务实例列表中随机选择一个(简单负载均衡)/// </summary>public ServiceInstance SelectRandomInstance(List<ServiceInstance> instances){if (instances == null || !instances.Any())return null;var random = new Random();return instances[random.Next(instances.Count)];}
}/// <summary>
/// 服务实例模型
/// </summary>
public class ServiceInstance
{public string ServiceId { get; set; }       // 服务唯一IDpublic string ServiceName { get; set; }     // 服务名称public string Address { get; set; }         // 服务地址(IP或域名)public int Port { get; set; }               // 服务端口public List<string> Tags { get; set; }      // 服务标签(如版本、环境)public string FullAddress { get; set; }     // 完整地址(地址:端口)
}

使用示例

// 1. 创建服务发现器(可指定多个 Consul 服务器地址)
var discoverer = new ConsulServiceDiscoverer("http://consul-server1:8500", "http://consul-server2:8500"
);// 2. 发现指定服务的健康实例(例如:发现支付服务)
var paymentServices = await discoverer.DiscoverHealthyServicesAsync("PaymentService");// 3. 从实例列表中选择一个进行调用(这里使用随机选择实现简单负载均衡)
var targetService = discoverer.SelectRandomInstance(paymentServices);if (targetService != null)
{Console.WriteLine($"选中的服务实例:{targetService.FullAddress}");// 4. 调用服务(示例:使用 HttpClient 调用)using (var httpClient = new HttpClient()){var response = await httpClient.GetAsync($"http://{targetService.FullAddress}/api/pay");var result = await response.Content.ReadAsStringAsync();Console.WriteLine($"服务响应:{result}");}
}

关键说明

  1. 健康实例筛选passingOnly: true 参数确保只返回通过健康检查的服务实例,避免调用故障节点。

  2. 高可用配置:通过传入多个 Consul 服务器地址,可实现客户端的高可用(当一个服务器不可用时自动切换到其他服务器)。

  3. 负载均衡:示例中使用了简单的随机选择策略,实际项目中可根据需求实现轮询、权重、哈希等更复杂的负载均衡算法。

  4. 服务标签:可通过 tag 参数筛选特定标签的服务实例(例如:只发现 version=v2 的服务)。

  5. 异常处理:代码包含了异常捕获逻辑,可根据实际需求扩展(如重试机制、降级策略等)。

通过这种方式,C# 应用可以动态发现并调用 Consul 中注册的服务,适配服务的动态扩缩容和故障转移场景。

相关代码

consul.demo资源-CSDN下载

http://www.dtcms.com/a/352566.html

相关文章:

  • 卷积操作现实中的意义
  • 发力低空经济领域,移动云为前沿产业加速崛起注入云端动能
  • 微服务-24.网关登录校验-实现登录校验
  • Linux系统日志分析与存储
  • 机器学习:前篇
  • 从行业智能体到一站式开发平台,移动云推动AI智能体规模化落地
  • 产品经理操作手册(3)——产品需求文档
  • Duplicate Same Files Searcher v10.7.0,秒扫全盘重复档,符号链接一键瘦身
  • 【软件测试面试】全网最全,自动化测试面试题总结大全(付答案)
  • 告别出差!蓝蜂物联网网关让PLC程序远程修改零延迟
  • 二、JVM 入门 —— (四)堆以及 GC
  • 渗透测试术语大全(超详细)
  • C++ STL 顶层设计与安全:迭代器、失效与线程安全
  • 【C++游记】栈vs队列vs优先级队列
  • 算法编程实例-快乐学习
  • 随机森林实战:在鸢尾花数据集上与决策树和逻辑斯蒂回归进行对比
  • AI安全监控与人才需求的时间悖论(对AI安全模型、AI安全人才需求的一些思考)
  • AIDL和HIDL的AudioHal对比
  • Maya绑定基础: FK 和 IK 介绍和使用
  • lottie动画动态更改切图添加事件
  • 五自由度磁悬浮轴承:精准狙击转子质量不平衡引发的同频振动
  • pycharm 远程连接服务器报错
  • NeRAF、ImVid论文解读
  • 2007-2022年上市公司企业关联交易数据
  • 面向对象爬虫架构设计:构建高复用、抗封禁的爬虫系统​
  • 工业数据消费迎来“抖音式”革命:TDengine IDMP 让数据自己开口说话
  • 利用 Java 爬虫按关键字搜索 1688 商品详情 API 返回值说明实战指南
  • 如何在360极速浏览器中调出底部状态栏
  • Wireshark和USRP捕获同一信号波形差异原因
  • MQ 最终一致性实现跨库转账