.net5+nacos+ocelot 配置中心和服务发现实现

18 篇文章 0 订阅
14 篇文章 1 订阅

 引用地址:.net5+nacos+ocelot 配置中心和服务发现实现 - 疯痴傻 - 博客园

最近一段时间 因公司业务需要,需要使用.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/catcherwong/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": 10
 8   },
 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方法,加载配置中心的配置

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

/// <summary>
        /// 加载nacos配置中心
        /// </summary>
        /// <param name="sectionKey"></param>
        private async Task LoadConfig(string sectionKey)
        {
            try
            {
                GetConfigRequest configRequest = configuration.GetSection(sectionKey).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 (sectionKey == 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的配置对象

 View Code

将配置信息放入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 =>
            {
                //防止重复Timer
                if (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;
        }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于这个问题,作为一个聊天机器人,我可以提供一些基本的信息,但是对于具体的配置,可能需要您参考相关的文档或者向开发人员寻求帮助。您可以尝试通过以下步骤进行配置: 1. 配置注册中心 在dubbo的配置文件中,需要指定注册中心的地址和协议等信息,例如: ```xml <dubbo:registry address="nacos://localhost:8848"/> ``` 其中,地址是nacos注册中心的地址,对应的协议是nacos。 2. 配置服务提供者 为了让服务注册到注册中心上,服务提供者需要在dubbo的配置文件中指定服务名称和端口号等信息,例如: ```xml <dubbo:service interface="com.example.demo.service.UserService" ref="userService" timeout="5000" version="1.0.0" protocol="dubbo" group="test"/> ``` 其中,interface指定了服务的接口,ref指定了服务的实现类,timeout指定了超时时间,version指定了版本号,protocol指定了协议,group指定了分组名称。 3. 配置服务消费者 服务消费者需要在dubbo的配置文件中指定服务提供者的服务名称和地址等信息,例如: ```xml <dubbo:reference interface="com.example.demo.service.UserService" id="userService" version="1.0.0" protocol="dubbo" check="false"/> ``` 其中,interface指定了要消费的服务接口,id指定了对应的reference的id,version指定了服务的版本号,protocol指定了协议,check指定了是否检查服务提供者是否已经启动。 以上是一些基本的配置信息,具体的配置内容可能因项目而异。希望这些信息可以帮助到您。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值