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

.NetCore下Ocelot + Nacos 实现负载均衡

接上一篇:“.NetCore 接入 Nacos,实现配置中心和服务注册”
本篇实现 Nacos对接Ocelot实现负载均衡,依旧基于.NetCore3.1实现,如在.Net6以及之上实现,更新组件版本。

文章目录

      • 一、所需类库
      • 二、封装类库
        • `Nacos`
        • `NacosServiceDiscoveryProviderFactory`
        • `OcelotBuilderExtensions`
      • 三、网关对接
        • 1、使用项目中本地ocelot.json文件
        • 2、ocelot配置存入Nacos,从Nacos中读取配置

一、所需类库

nacos-sdk-csharp.AspNetCore 版本1.3.8,.Net6以上,更新到1.3.10
Ocelot 版本16.0.1,.Net6以上可更新到最新版本

二、封装类库

在这里插入图片描述

Nacos

此类名称不能修改,因为需要与Ocelot中ServiceDiscoveryProvider的Type匹配

using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
using Ocelot.ServiceDiscovery.Providers;
using Ocelot.Values;
using Nacos.V2;
using Microsoft.Extensions.Options;
using NacosConstants = Nacos.V2.Common.Constants;
using Nacos.AspNetCore.V2;
using Ocelot.Logging;
using Nacos.V2.Naming.Dtos;
using Service = Ocelot.Values.Service;namespace Ocelot.Provider.Nacos.AspNetCore
{public class Nacos : IServiceDiscoveryProvider{private readonly INacosNamingService _client;private readonly string _serviceName;private readonly string _groupName;private readonly IOcelotLogger _logger;private readonly List<string> _clusters;public Nacos(string serviceName, INacosNamingService client, IOptions<NacosAspNetOptions> options, IOcelotLoggerFactory factory){_serviceName = serviceName;_client = client;_groupName = string.IsNullOrWhiteSpace(options.Value.GroupName) ?NacosConstants.DEFAULT_GROUP : options.Value.GroupName;_clusters = (string.IsNullOrWhiteSpace(options.Value.ClusterName) ? NacosConstants.DEFAULT_CLUSTER_NAME : options.Value.ClusterName).Split(",").ToList();_logger = factory.CreateLogger<Nacos>();}public async Task<List<Service>> Get(){var services = new List<Service>();_logger.LogInformation($"Trying to get service instances from Nacos for service: {_serviceName}");var instances = await _client.SelectInstances(_serviceName, _groupName, _clusters, true);if (instances == null || !instances.Any()){_logger.LogWarning($"No service instances found in Nacos for service: {_serviceName}");return services;}foreach (var serviceEntry in instances){if (IsValid(serviceEntry)){services.Add(BuildService(serviceEntry));}else{_logger.LogWarning($"Unable to use service Port: {serviceEntry.Port} as it is invalid.");}}_logger.LogInformation($"Found {services.Count} service instances in Nacos for service: {_serviceName}");return services;}private Service BuildService(Instance instance){return new Service(instance.ServiceName,new ServiceHostAndPort(instance.Ip, instance.Port),instance.InstanceId,GetVersionFromMetadata(instance.Metadata),GetTagFromMetadata(instance.Metadata));}private bool IsValid(Instance instance){if (instance.Port <= 0){return false;}return true;}private IEnumerable<string> GetTagFromMetadata(Dictionary<string, string> metadata){if (metadata == null){return Enumerable.Empty<string>();}return metadata.Select(t => { return $"{t.Key}:{t.Value}"; });}private string GetVersionFromMetadata(Dictionary<string, string> metadata){if (metadata.TryGetValue("version", out var version)){return version;}return "";}}
}
NacosServiceDiscoveryProviderFactory
using Ocelot.ServiceDiscovery;
using Microsoft.Extensions.DependencyInjection;
using Nacos.V2;
using Microsoft.Extensions.Options;
using Nacos.AspNetCore.V2;
using Ocelot.Logging;namespace Ocelot.Provider.Nacos.AspNetCore
{public static class NacosServiceDiscoveryProviderFactory{public static ServiceDiscoveryFinderDelegate Get = (provider, config, route) =>{var client = provider.GetService<INacosNamingService>();if (config.Type?.ToLower() == "nacos" && client != null){var option = provider.GetService<IOptions<NacosAspNetOptions>>();var logger = provider.GetRequiredService<IOcelotLoggerFactory>();return new Nacos(route.ServiceName, client, option, logger);}return null;};}
}
OcelotBuilderExtensions
using Microsoft.Extensions.DependencyInjection;
using Nacos.AspNetCore.V2;
using Ocelot.DependencyInjection;namespace Ocelot.Provider.Nacos.AspNetCore
{public static class OcelotBuilderExtensions{public static IOcelotBuilder AddNacos(this IOcelotBuilder builder, string section = "nacos"){//网关服务注册到Nacosbuilder.Services.AddNacosAspNet(builder.Configuration, section);builder.Services.AddSingleton(NacosServiceDiscoveryProviderFactory.Get);return builder;}}
}

三、网关对接

引用Ocelot.Provider.Nacos.AspNetCore
appsettings.json配置如下:

"Nacos": {"Listeners": [ //配置监听列表,包含多个监听项{"Optional": false, //是否为可选配置。false表示如果配置不存在,应用启动会失败;true表示配置不存在时忽略"DataId": "ocelot","Group": "DEFAULT_GROUP" //配置所属的分组,默认为DEFAULT_GROUP}],"ServerAddresses": [ "http://192.168.5.210:8848" ], //Nacos 服务器地址列表"DefaultTimeOut": 15000,"Namespace": "8f67799f-0eb9-42b1-94e5-080d9b1c56ea", // 命名空间 ID,用于隔离不同环境的配置和服务,Please set the value of Namespace ID !!!!!!!!"ListenInterval": 1000, //监听间隔时间,单位为毫秒"ServiceName": "NacosGateway", //注册到注册中心的服务名称"Weight": 100, //服务权重,用于服务路由时的负载均衡计算"RegisterEnabled": true, //是否启用服务注册"InstanceEnabled": true, //实例是否启用"Ephemeral": true, //是否为临时实例,true表示是临时实例,服务宕机后会被自动摘除"Secure": false, //是否使用安全连接"UserName": "nacos","Password": "nacos","ConfigUseRpc": false, //是否使用 RPC 协议获取配置"NamingUseRpc": false, //是否使用 RPC 协议进行服务发现"NamingLoadCacheAtStart": "", //启动时是否加载服务发现缓存"LBStrategy": "WeightRandom", //负载均衡策略,WeightRandom表示加权随机,WeightRoundRobin表示加权轮询"Metadata": { //服务实例的元数据信息,为键值对形式"version": "1.0","feature": "true"}
}

以上Listeners配置是因为ocelot配置内容也存放在Nacos中,如是使用本地ocelot.json文件,则无需此项配置。

Startup中使用AddNacos进行接入

services.AddOcelot().AddNacos();

完整代码

public class Startup
{public Startup(IConfiguration configuration){Configuration = configuration;}public IConfiguration Configuration { get; }public void ConfigureServices(IServiceCollection services){services.AddControllers(config =>{});// 添加网关services.AddOcelot().AddNacos(); ;}public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime lifetime){app.UseOcelot().Wait();}
}

Ocelot配置内容如下:

{"Routes": [{"ServiceName": "NacosWebApi","DownstreamScheme": "http","DownstreamPathTemplate": "/{url}","UpstreamPathTemplate": "/api/{url}","UseServiceDiscovery": true,"UpstreamHttpMethod": [ "Get" ],"LoadBalancerOptions": {"Type": "RoundRobin"}}],"GlobalConfiguration": {"ServiceDiscoveryProvider": {"Type": "Nacos"}}
}
1、使用项目中本地ocelot.json文件

Program中增加

builder.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);

完整代码

public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureAppConfiguration((hostingContext, builder) =>{builder.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);}).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseStartup<Startup>();});
2、ocelot配置存入Nacos,从Nacos中读取配置

Program中增加

var c = builder.Build();
builder.AddNacosV2Configuration(c.GetSection("Nacos"));

完整代码

public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureAppConfiguration((hostingContext, builder) =>{var c = builder.Build();builder.AddNacosV2Configuration(c.GetSection("Nacos"));}).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseStartup<Startup>();});
http://www.xdnf.cn/news/19535.html

相关文章:

  • qt QWebSocket详解
  • 数据结构与算法个人学习代码笔记包含leetcode,海贼oj,蓝桥杯,ACM
  • 对于牛客网—语言学习篇—编程初学者入门训练—复合类型:BC140 杨辉三角、BC133 回型矩阵、BC134 蛇形矩阵题目的解析
  • Ansible 变量与加密文件全解析:从基础定义到安全实践
  • 了解名词ARM Linux的SOC
  • TIOBE 8月编程语言榜深度解析:Python占比突破26%,Perl成最大黑马
  • Kaia AMA 全回顾:如何让 Web3 无痕融入2.5 亿用户日常?9 月 7 日中国行揭秘!
  • 一键提取,是真强呀!~
  • buuctf_php(极客大挑战 2019)
  • 从程序员到「认识罕见病 DAO」发起人,他用 Web3 承载爱与责任
  • Linux 文本处理四剑客:cut, sort, uniq, tr
  • lua脚本在redis中如何单步调试?
  • 一文吃透 deviceQuery:从安装到输出解读,彻底验证服务器 GPU 环境
  • AlDente Pro for Mac电脑 充电限制保护工具
  • Go 面试题:Goroutine 和 GMP 模型解析
  • 最快的 C 语言 JSON 库 - yyjson
  • 阿里云日志服务之WebTracking 小程序端 JavaScript SDK (阿里SDK埋点和原生uni.request请求冲突问题)
  • 2025全球绿色发展与健康生活方式高峰论坛 推动HLCC国际认证体系全球化实施
  • VGG改进(7):基于Spatial Attention的性能优化
  • 跨平台游戏引擎 Axmol-2.8.0 发布
  • Prettier代码格式化工具测评:支持JS/TS/Vue多语言,兼容ESLint实现团队代码格式统一
  • TKDE-2022《Low-Rank Linear Embedding for Robust Clustering》
  • Element-Plus 入门指南
  • 【3D通用视觉框架】基于Qt5开发的3D视觉框架软件,纯底层,全套源码,开箱即用
  • R语言根据经纬度获得对应样本的省份
  • PCB设计规范
  • redis-----java客户端
  • K8s集群+Rancher Server:部署DolphinScheduler 3.2.2集群
  • 【vue2】vue2.7x的项目中集成tailwind.css真的不要太香
  • GPT-5在医疗领域应用的研究效能初探(上)