相关文章:手动造轮子——为Ocelot集成Nacos注册中心

出处:https://www.cnblogs.com/buruainiaaaa/p/14121176.html

作者:唐@

  最近一段时间 因公司业务需要,需要使用.net5做一套微服务的接口,使用nacos 做注册中心和配置中心,ocelot做网关。

因为ocelot 支持的是consol和eureka,如果使用nacos做服务发现,需要自己集成,以此记录下

  Nacos 支持基于 DNS 和基于 RPC 的服务发现(可以作为注册中心)、动态配置服务(可以做配置中心)、动态 DNS 服务。官网地址:https://nacos.io/en-us/

  ocelot 相信大家都比较熟悉,官网:https://ocelot.readthedocs.io/en/latest/index.html

环境安装:

  nacos参考地址:https://blog.csdn.net/ooyhao/article/details/102744904

  基于.net版本的nacos  sdk:nacos-sdk-csharp-unofficial.AspNetCore  (此处有坑 :Nacos.AspNetCore 已经停止更新,代码已迁移,服务注册会有问题)

  SDK源码地址:https://github.com/nacos-group/nacos-sdk-csharp

配置中心:

  1.在nacos添加配置

2.在.net 项目中 配置文件中 添加相关配置

 1  "nacos": {2     "ServerAddresses": [ "http://127.0.0.1:8849/" ],3     "DefaultTimeOut": 30000,4     "Namespace": "",5     "ListenInterval": 30000,6     "ServiceName": "ServiceName","RegisterEnabled": true,7     "Weight": 108   },9   "nacosData": {
10     "DataId": "nacosConfig",
11     "Group": "Pro"
12   }

3.在Startup.cs添加nacos  sdk的DI注册

1 services.AddNacos(Configuration);

4.创建AppConfig类,定义构造函数:(从DI中获取INacosConfigClient对象)

 public AppConfig(IServiceCollection _services, IConfiguration _configuration){services = _services;configuration = _configuration;var serviceProvider = services.BuildServiceProvider();_configClient = serviceProvider.GetService<INacosConfigClient>();}

5.添加LoadConfig方法,加载配置中心的配置

代码说明:pKey入参 为配置文件中的key(nacosData),responseJson为配置中心的完整配置字符串,可以是json,可以是key=value模式,根据字符串格式,转为Dictionary中,放入静态私有对象中

/// <summary>/// 加载nacos配置中心/// </summary>/// <param name="pKey"></param>private async Task LoadConfig(string pKey){try{GetConfigRequest configRequest = configuration.GetSection(pKey).Get<GetConfigRequest>();if (configRequest == null || string.IsNullOrEmpty(configRequest.DataId)){return;}var responseJson = await _configClient.GetConfigAsync(configRequest);Console.WriteLine(responseJson);if (string.IsNullOrEmpty(responseJson)){return;}var dic = LoadDictionary(responseJson);if (pKey == commonNacosKey){commonConfig = dic;}else{dicConfig = dic;}}catch (Exception ex){throw ex;}}

6.添加监听:

ps:

AddListenerRequest对象为nacos sdk的监听请求对象,通过INacosConfigClient对象的AddListenerAsync方法,可以添加对nacos dataid=nacosConfig 的监听,监听的时间间隔设置可以为:ListenInterval
 1 /// <summary>2         /// 监控3         /// </summary>4         private void ListenerConfig()5         {6             AddListenerRequest request = configuration.GetSection("nacosData").Get<AddListenerRequest>();7             request.Callbacks = new List<Action<string>>() {8                 x=>{9                    var dic = LoadDictionary(x);
10                     foreach (var item in dicConfig.Keys)
11                     {
12                         if (dic.Keys.Any(p=>p==item))
13                         {
14                             if (dic[item] != dicConfig[item])
15                             {
16                                 dicConfig[item]=dic[item].Trim();
17                             }
18                         }else
19                         {
20                             dicConfig.Remove(item);
21                         }
22                     }
23                     foreach (var item in dic.Keys)
24                     {
25                         if (!dicConfig.Keys.Any(p=>p==item)){
26                             dicConfig.Add(item,dic[item]);
27                         }
28                     }
29                 }
30             };
31             var serviceProvider = services.BuildServiceProvider();
32             INacosConfigClient _configClient = serviceProvider.GetService<INacosConfigClient>();
33             _configClient.AddListenerAsync(request);
34         }

7.添加自动注入:

ps:如果需要在同一个项目中,获取多个配置,需要AppConfig对象的单列模式,这一点 自己注意下

 public static IServiceCollection AddLoadConfig(this IServiceCollection _services, IConfiguration _configuration){var config = new AppConfig(_services, _configuration);config.Load();return _services;}

/******************************************************* 配置中心  end *************************************************************/

服务注册:

基于上面的配置信息 在自动注入中添加如下代码即可

services.AddNacosAspNetCore(conf);

启动之后 在nacos中,就可以看到此服务  如果在nacos 看到多个实列 或者 端口号和项目启动的端口号不一致,最好添加IP和port。

/***************************************************************服务注册  end***********************************************************************/

基于ocelot 的服务发现:

新建网关项目,添加ocelot和 nacos sdk 的nuget依赖

查看ocelot的官方文档就会发现,如果 能够取到nacos 中 服务的名称和服务里边可用实列的ip和port,然后把这些信息放入ocelot里边的, 就可以通过ocelot访问到这些服务接口

然后在通过自定义监听器,就可以实现想要的效果

通过上面的配置中心的配置方式,在nacos中 添加 ocelot 的模板配置

{"Routes": [{"DownstreamHostAndPorts": [{"Host": "localhost","Port": 5000}],"DownstreamPathTemplate": "/{url}","DownstreamScheme": "http","UpstreamHttpMethod": ["GET", "POST", "DELETE", "PUT"],"UpstreamPathTemplate": "/OrderServer/{url}","LoadBalancerOptions": {"Type": "RoundRobin"}}, {"DownstreamHostAndPorts": [{"Host": "localhost","Port": 5000}],"DownstreamPathTemplate": "/{url}","DownstreamScheme": "http","UpstreamHttpMethod": ["GET", "POST", "DELETE", "PUT"],"UpstreamPathTemplate": "/ProductServer/{url}"}],"ServiceDiscoveryProvider": {},"GlobalConfiguration": {}
}

关于ocelot的Startup.cs的相关配置  这里就不赘述了,网上有很多。

这里的关键是,从nacos中拉取服务列表,然后根据ocelot的配置模板,生成需要的ocelot的配置信息,然后放入ocelot中

获取nacos中所有的服务列表

ps:通过INacosNamingClient对象的ListServicesAsync方法,获取nacos 的服务

/// <summary>/// 获取所有服务/// </summary>/// <param name="serviceProvider"></param>/// <param name="_servicesRequest"></param>/// <returns></returns>private async Task<List<ListInstancesResult>> GetServerListener(IServiceProvider serviceProvider, object _servicesRequest){ListServicesRequest request = (ListServicesRequest)_servicesRequest;try{var _namingClient = serviceProvider.GetService<INacosNamingClient>();var res = await _namingClient.ListServicesAsync(request);List<ListInstancesResult> resultList = new List<ListInstancesResult>();if (res.Count > 0){List<Task<ListInstancesResult >> taskList = new List<Task<ListInstancesResult>>();foreach (var item in res.Doms){var taskItem = GetListInstancesResult(_namingClient,item);taskList.Add(taskItem);}Task.WaitAll(taskList.ToArray());foreach (var item in taskList){resultList.Add(item.Result);}}return resultList;}catch (Exception ex){LoggerLocal.Error(ex.Message, ex);return new List<ListInstancesResult>();}}

将nacos的服务和配置中心的ocelot模板转换为ocelot的配置对象

/// <summary>/// nacos中的服务 转为ocelot对象的路由/// </summary>/// <param name="fileConfiguration"></param>/// <param name="listInstancesResults"></param>/// <returns></returns>private FileConfiguration InstancesResultToFileConfiguration(FileConfigurationTemplate fileConfiguration, List<ListInstancesResult> listInstancesResults) {if (fileConfiguration.RouteTemplate == null || fileConfiguration.RouteTemplate.Count == 0){throw new Exception("路由不能为空");}var result = new FileConfiguration() {GlobalConfiguration = fileConfiguration.GlobalConfiguration,Aggregates = fileConfiguration.Aggregates,DynamicRoutes = fileConfiguration.DynamicRoutes,Routes = new List<FileRoute>()};nacosServerModelList.ServerInfo = new List<ServerInfo>();var routeList = fileConfiguration.RouteTemplate;var defaultRoute = fileConfiguration.RouteTemplate.Find(p=>p.RoutesTemplateName=="common");fileConfiguration.Routes = new List<FileRoute>();foreach (var item in listInstancesResults){var routeTemp = routeList.Find(p => p.ServiceName.ToLower() == item.Dom.ToLower());if (routeTemp == null){routeTemp = defaultRoute;}var newRouteTmp = CopyTo(routeTemp);newRouteTmp.UpstreamPathTemplate = "/" + item.Dom + "/{url}";newRouteTmp.DownstreamPathTemplate = "/{url}";newRouteTmp.DownstreamHostAndPorts = new List<FileHostAndPort>();if (item.Hosts.Count > 0){foreach (var host in item.Hosts){newRouteTmp.DownstreamHostAndPorts.Add(new FileHostAndPort(){Host = host.Ip,Port = host.Port,});}}if (newRouteTmp.DownstreamHostAndPorts.Count > 0){result.Routes.Add(newRouteTmp);nacosServerModelList.ServerInfo.Add(new ServerInfo() { Name = item.Dom });}}UpdSwaggerUrlAction(serviceProvider, nacosServerModelList);return result;}private  FileRoute CopyTo(RouteTemplate s){var result = new FileRoute() { AddClaimsToRequest=s.AddClaimsToRequest,DangerousAcceptAnyServerCertificateValidator=s.DangerousAcceptAnyServerCertificateValidator,DelegatingHandlers=s.DelegatingHandlers,DownstreamHeaderTransform=s.DownstreamHeaderTransform,DownstreamHostAndPorts=s.DownstreamHostAndPorts,DownstreamHttpMethod=s.DownstreamHttpMethod,DownstreamHttpVersion=s.DownstreamHttpVersion,DownstreamPathTemplate=s.DownstreamPathTemplate,SecurityOptions=s.SecurityOptions,DownstreamScheme=s.DownstreamScheme,ChangeDownstreamPathTemplate=s.ChangeDownstreamPathTemplate,AddHeadersToRequest=s.AddHeadersToRequest,AddQueriesToRequest=s.AddQueriesToRequest,AuthenticationOptions=s.AuthenticationOptions,FileCacheOptions=s.FileCacheOptions,HttpHandlerOptions=s.HttpHandlerOptions,Key=s.Key,LoadBalancerOptions=s.LoadBalancerOptions,Priority=s.Priority,QoSOptions=s.QoSOptions,RateLimitOptions=s.RateLimitOptions,RequestIdKey=s.RequestIdKey,RouteClaimsRequirement=s.RouteClaimsRequirement,RouteIsCaseSensitive=s.RouteIsCaseSensitive,ServiceName=s.ServiceName,ServiceNamespace=s.ServiceNamespace,Timeout=s.Timeout,UpstreamHeaderTransform=s.UpstreamHeaderTransform,UpstreamHost=s.UpstreamHost,UpstreamHttpMethod=s.UpstreamHttpMethod,UpstreamPathTemplate=s.UpstreamPathTemplate,};return result;}

将配置信息放入ocelot里边

ps:这个地方 需要看ocelot的源码,才知道这中间的对象转换逻辑

1  private void SetOcelotConfig(FileConfiguration configuration)
2         {
3
4             var internalConfigCreator = serviceProvider.GetService<IInternalConfigurationCreator>();
5             Task<Response<IInternalConfiguration>> taskResponse = internalConfigCreator.Create(configuration);
6             taskResponse.Wait();
7             IInternalConfigurationRepository internalConfigurationRepository = serviceProvider.GetService<IInternalConfigurationRepository>();
8             internalConfigurationRepository.AddOrReplace(taskResponse.Result.Data);
9         }

自定义监听器:

ps:isLoadUri 防止处理过慢,监听服务 多次监听

routesMd5:判断监听到的服务 是否需要放入ocelot

自定义监听的方式与nacos sdk中,监听配置中心的方式类似,有兴趣可以看看sdk的源码

/// <summary>/// 获取nacos里边的所有服务信息,同时自定义服务监听/// </summary>/// <param name="serviceProvider"></param>/// <returns></returns>private async Task<List<ListInstancesResult>> GetServerList(IServiceProvider serviceProvider){var request = new ListServicesRequest{PageNo = 1,PageSize = 100,};List<ListInstancesResult> listInstancesResults = await GetServerListener(serviceProvider, request);//return listInstancesResults;var timeSeconds = 1000 * 10;Timer timer = new Timer(async x =>{//防止重复Timerif (isLoadUri){return;}isLoadUri = true;List<ListInstancesResult> listInstancesList = await GetServerListener(serviceProvider, x);GetConfigRequest configRequest = configuration.GetSection("nacosData").Get<GetConfigRequest>();INacosConfigClient _configClient = serviceProvider.GetService<INacosConfigClient>();Task<string> taskResult = _configClient.GetConfigAsync(configRequest);taskResult.Wait();var responseJson = taskResult.Result;if (listInstancesList.Count>0){var fileConfiguration = InstancesResultToFileConfiguration(JsonConvert.DeserializeObject<FileConfigurationTemplate>(responseJson), listInstancesList);responseJson = JsonConvert.SerializeObject(fileConfiguration);var rMd5 = HashUtil.GetMd5(responseJson);if (!rMd5.Equals(routesMd5)){SetOcelotConfig(fileConfiguration);routesMd5 = rMd5;}}isLoadUri = false;}, request, timeSeconds, timeSeconds);timers.Add(timer);return listInstancesResults;}

相关文章:手动造轮子——为Ocelot集成Nacos注册中心

.net5+nacos+ocelot 配置中心和服务发现实现相关推荐

  1. Nacos配置中心与服务发现

    1.Nacos原理 2.模型领域 3.下载地址:nacos 这里本人下载的是2.0.4版本 4.nacos配置文件与启动命令 在conf文件夹中找到application.properties文件中改 ...

  2. spring cloud集成nacos注册中心、配置中心、服务远程调用

    简介 Nacos 致力于帮助您发现.配置和管理微服务.Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现.服务配置.服务元数据及流量管理. Nacos 帮助您更敏捷和容易地构建.交付和 ...

  3. Spring Cloud Alibaba - 19 Nacos Config配置中心加载不同微服务的通用配置的两种方式

    文章目录 Pre 实现 方式一 通过 shared-dataids 方式 方式二 通过 ext-config方式 配置文件优先级 源码 Pre Spring Cloud Alibaba - 18 Na ...

  4. Spring Cloud Alibaba - 18 Nacos Config配置中心加载相同微服务的不同环境下的通用配置

    文章目录 需求 实现 Step 1 Nacos Config 新增公共配置 Step 2 验证 配置文件优先级 源码 需求 举个例子,同一个微服务,通常我们的servlet-context 都是相同的 ...

  5. SpringBoot使用Nacos作为配置中心服务

    spring cloud alibaba教程:如何使用nacos作为配置中心 startup.cmd -m standalone 1.下载与解压Nacos压缩包(Nacos安装指南具体教程可查看) 下 ...

  6. Spring Cloud Alibba教程:如何使用Nacos作为配置中心

    点击上方"方志朋",选择"置顶公众号" 技术文章第一时间送达! 在上一篇文章中讲解了如何使用Nacos作为服务注册中心注册.Nacos除了可以作为服务注册中心, ...

  7. nacos当配置中心读取其他配置文件_SpringBoot+Nacos实现配置中心

    为什么需要配置中心 不知道你是否遇到过以下情况: 同一个项目有多套配置,分布在不同的配置文件中,需要修改时,要改多个文件,有时候会遗漏配置 某天突然需要修改线上的一个配置,只能修改.提交,重启服务 项 ...

  8. [享学Eureka] 一、源生Eureka介绍 --- 基于注册中心的服务发现

    凡事皆有代价,一切皆是取舍. 本专栏所有文章均计划逐步重写搬迁至本人公号:Java方向盘,且免费开放!故不再建议下单购买,可关注我公号前往免费学习.交流 –> 返回Netflix OSS套件专栏 ...

  9. Spring Cloud Alibaba Nacos 分布式配置中心

    文章目录 1 摘要 2 核心 Maven 依赖 3 核心代码 3.1 bootstrap 配置文件 3.2 application 配置文件 3.3 配置测试类 - Controller 层 3.4 ...

最新文章

  1. 2019第十四届全国菌根学术研讨会(第二轮通知)
  2. 20180917-1每周例行报告
  3. 洛谷模拟赛 数据结构
  4. python xlrd_python模块之xlrd
  5. VS2010与.NET4系列 23.Visual Studio 2010 扩展管理器(和新的 VS2010 PowerComman
  6. javaweb(三十八)——mysql事务和锁InnoDB(扩展)
  7. layui上传文件请求接口异常_SpringMVC实现文件上传与下载,拦截器,异常处理
  8. 【C语言基础】C语言异常捕获机制 - setjmp
  9. html 小于号 乱码,shell重定向(大于号,小于号,左右,21,)
  10. android 开发赚钱
  11. wamp php 升级,wamp升级PHP7.1
  12. java file list listfiles,Java File listFiles()用法及代码示例
  13. JavaScript生成树形菜单(递归算法)
  14. matlab——knnsearch用法介绍
  15. 【Java基础】建立Java面向对象编程OOP模型
  16. 一根均线选股法_一根足以,万能均线买卖法!(实战干货)
  17. 计算机键盘上每一个键的作用,电脑键盘上各种键的作用是什么 电脑键盘上每个键的作用说明【图文】...
  18. 海康录像机识别不到硬盘_海康硬盘录像机提示“资源不足”如何解决?
  19. (1)asp。net操作ftp,上传和下载 (2) 长时间提交,在提交后禁止页面按钮 (3) 方便的javascript日历
  20. JDK1.8_API(不能用 你来看砍我)

热门文章

  1. Linux下SSH远程连接断开后让程序继续运行解决办法
  2. PHP7 学习笔记(十一)使用phpstudy快速配置一个虚拟主机
  3. js 栈(进制转换)
  4. 4.3.2 基于集合的操作
  5. (第九周)团队项目14
  6. c#3.0关于JSON简单操作的实用帮助类(泛型实现)
  7. php html 伪静态,php 伪静态(url重写)的写法
  8. java调用siri 语言_如何更改Siri的声音,口音,性别和语言
  9. powershell实现设置程序相关性脚本
  10. EventBus的实现