怎么把自己电脑建设网站,wordpress附件图标,济宁网上做科目一的网站,电商基地推广前言近期在看博客的时候或者在群里看聊天的时候#xff0c;发现很多都提到了Ocelot网关的问题。我之前也研究过一点#xff0c;网关本身是一种通用的解决方案#xff0c;主要的工作就是拦截请求统一处理#xff0c;比如认证、授权、熔断、限流、注册发现、负载均衡等等。随… 前言 近期在看博客的时候或者在群里看聊天的时候发现很多都提到了Ocelot网关的问题。我之前也研究过一点网关本身是一种通用的解决方案主要的工作就是拦截请求统一处理比如认证、授权、熔断、限流、注册发现、负载均衡等等。随着服务化的不断盛行服务拆分负载均衡等已成为当今软件行业随处可谈的名词了因此注册中心也随之流行了起来。Ocelot作为网关自然可以集成许多注册中心官方文档给出了集成Eureka和Consul的解决方案Eureka可能有的人不是很熟悉它是Spring Cloud的核心组件之一其功能就是服务注册发现。随着.Net Core的不断成熟不知道为啥Consul突然成了.Net Core注册中心和配置中心的主要选择甚至可以说是首选了可能是因为功能比较强大而且是基于GO开发的。Nacos作为后起之秀功能也非常强大。那天无意中翻了一下发下网上居然没有Ocelot集成到Nacos注册中心的组件由于我个人非常喜欢通用解决方案,于是决定自己扩展一个Ocelot.Provider.Nacos代码已经放到了我的GitHub上https://github.com/softlgl/Ocelot.Provider.Nacos有兴趣的可自行查阅。概念介绍Ocelot Ocelot是一个用.NET Core实现并且开源的API网关它具备了许多强大实用的功能包括了路由、请求聚合、服务发现、认证、鉴权、限流熔断、并内置了负载均衡器与Service Fabric、Butterfly Tracing集成。它是由asp.net core middleware组成的一个管道。当获取请求之后会用request builder来构造一个HttpRequestMessage转发到下游的真实服务器等下游的服务返回response之后再由一个middleware将它返回的HttpResponseMessage映射到HttpResponse上。官方文档地址 https://ocelot.readthedocs.io/en/latest/官方GitHub地址 https://github.com/ThreeMammals/OcelotNacos 关于Nacos我之前的文章搭建一套ASP.NET CoreNacosSpring Cloud Gateway项目已经有过介绍了。Nacos是阿里巴巴开源的致力于服务发现、配置和管理微服务的框架。提供了一组简单易用的特性集帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。一般用到的最多的就是当做配置中心和注册中心。中文官网地址https://nacos.io/zh-cn/官方GitHub地址https://github.com/alibaba/nacosOcelot.Provider.Nacos开发环境基于.Net Core 3.1这个是必须的因为最新稳定版的Ocelot是在.Net Core 3.1上构建的而我恰好选择的是这个版本的OcelotOcelot选择的是目前最新的稳定版本 v16.0.1Nacos访问组件实用的是nacos-sdk-csharp具体引用的是PackageReference Includenacos-sdk-csharp-unofficial Version0.2.7 /它其实是有另一个nacos-sdk-csharp-unofficial.AspNetCore版本的这个是针对Asp.Net Core程序集成Nacos使用的Ocelot也是基于Asp.Net Core搭建起来的但是我没有选用nacos-sdk-csharp-unofficial.AspNetCore主要是因为虽然AspNetCore版本的集成起来更方便但是为了让它能更好的适配到Ocelot服务注册和发现上我需要自己改造一下原本的使用方式。集成到Ocelot将Ocelot.Provider.Nacos的方式非常简单基本上和Ocelot.Provider.Eureka和Ocelot.Provider.Consul是一致的首先新建一个已经集成了Ocelot的Asp.Net Core项目这里就不演示如何搭建的了如果有不熟悉的可以查看我的demo示例https://github.com/softlgl/Ocelot.Provider.Nacos/tree/master/demo/ApiGatewayDemo项目搭建好之后引入Ocelot.Provider.Nacos包PackageReference IncludeOcelot.Provider.Nacos Version1.0.0 /
然后在ConfigureServices中添加注册方法AddNacosDiscoverypublic void ConfigureServices(IServiceCollection services)
{//注册服务发现services.AddOcelot().AddNacosDiscovery();
}
代码上做这么多就可以了其他的主要工作就在配置上了近期新版本的Ocelot相对于之前老版本有些地方改动还是非常大的网上很多示例都是老版本的所以参考官方文档搭建还是比较靠谱的。接下来我们打开Ocelot的配置文件配置注册中心相关的{Routes: [{// 用于服务发现的名称也就是注册到nacos上的名称ServiceName: productservice,DownstreamScheme: http,DownstreamPathTemplate: /productapi/{everything},UpstreamPathTemplate: /productapi/{everything},UpstreamHttpMethod: [ Get, Post ],LoadBalancerOptions: {Type: RoundRobin },// 使用服务发现UseServiceDiscovery: true}],GlobalConfiguration: {ServiceDiscoveryProvider: {// 这里是重点Type: Nacos}}
}
这里只是为Ocelot配置使用配置中心接下来我们要配置Nacos访问地址相关的打开appsettings.json当然你自定义的配置文件也可以只要程序可以加载得到nacos: {ServerAddresses: [ http://localhost:8848 ],DefaultTimeOut: 15000,Namespace: ,ListenInterval: 1000,// 网关注册的服务名称ServiceName: apigateway
}
具体如何配置保留了和nacos-sdk-csharp一致的方式可以到nacos-sdk-csharp项目源码中去查看nacos-sdk-csharp文档不是特别详细但是源码注释非常给力。所以直接去配置类源码里查看就好了。在这之前如果你已经启动了Nacos然后就可以直接运行Ocelot网关项目启动完成后打开Nacos如果出现如图所示说明已经注册成功你也可以直接运行我提供的demo需要启动ApiGatewayDemo和ProductApi两个项目一个是OcelotDemo一个是服务Demo输入网关地址和需要转发的url后可展示如下数据自定义扩展代码代码基本上我是参考着Ocelot.Provider.Eureka和Ocelot.Provider.Consul相关代码写的。其中入口类就一个是针对IOcelotBuilder的扩展类。首先,将自定义的服务发现相关的服务注册进来。只展示Ocelot适配相关的我自己写的关于服务注册发现相关的就不做展示了有兴趣的可自行查阅public static IOcelotBuilder AddNacosDiscovery(this IOcelotBuilder builder)
{//添加注册自定义的NacosDiscovery相关的服务builder.Services.AddNacosDiscovery(builder.Configuration);//添加自定义服务发现代理builder.Services.AddSingletonServiceDiscoveryFinderDelegate(NacosProviderFactory.Get);//根据Ocelot配置文件相关内容设置处理服务发现相关builder.Services.AddSingletonOcelotMiddlewareConfigurationDelegate(NacosMiddlewareConfigurationProvider.Get);return builder;
}
其次将自定义的注册发现相关操作提供出来其实主要就是获取服务地址public static class NacosProviderFactory
{public static ServiceDiscoveryFinderDelegate Get (provider, config, route) {//Nacos相关服务类var client provider.GetServiceINacosServerManager();//判断类型是否为nacosif (config.Type?.ToLower() nacos client ! null){//返回自定义服务提供操作route.ServiceName是命中的Route的配置的服务发现的名称return new Nacos(route.ServiceName, client);}return null;};
}public class Nacos : IServiceDiscoveryProvider
{private readonly INacosServerManager _client;private readonly string _serviceName;public Nacos(string serviceName, INacosServerManager client){_client client;_serviceName serviceName;}public async TaskListService Get(){var services new ListService();var instances await _client.GetServerAsync(_serviceName);if (instances ! null instances.Any()){//将发现的地址组装成Service集合即可services.AddRange(instances.Select(i new Service(i.InstanceId, new ServiceHostAndPort(i.Ip, i.Port), , , new Liststring())));}return await Task.FromResult(services);}
}
最后根据Ocelot配置相关的信息判断是否启动Nacos相关服务public class NacosMiddlewareConfigurationProvider
{public static OcelotMiddlewareConfigurationDelegate Get builder {var internalConfigRepo builder.ApplicationServices.GetServiceIInternalConfigurationRepository();var config internalConfigRepo.Get();var hostLifetime builder.ApplicationServices.GetServiceIHostApplicationLifetime();//判断服务注册类型是否为nacosif (UsingNacosServiceDiscoveryProvider(config.Data)){//启动nacos相关服务builder.UseNacosDiscovery(hostLifetime).GetAwaiter().GetResult();}return Task.CompletedTask;};private static bool UsingNacosServiceDiscoveryProvider(IInternalConfiguration configuration){//判断配置的服务发现类型是否为nacosreturn configuration?.ServiceProviderConfiguration ! null configuration.ServiceProviderConfiguration.Type?.ToLower() nacos;}
}
涉及到的相关代码并不多而且比较清晰了解到相关规则后还是比较简单的。开发中遇到困难Ocelot.Provider.Nacos一共大概有十个类左右集成到Ocleot本身相关类有四个吧其他的类都是集成Nacos相关的。首先我找错代码了仓库刚开始我是顺着Nuget包上的地址找到了https://github.com/ThreeMammals/Ocelot.Provider.Eureka但是其实这是一个废弃的老仓库它最后更改的日期是18年9月我当时还很好奇这么长时间居然没有改动过但是当我仿着这个写的时候遇到了转发相关路由的问题后来我又到了nuget上看了一下发现Ocelot.Provider.Eureka还一直在更新后来我想会不会把代码移植到了Ocelot仓库中果然不出所料在https://github.com/ThreeMammals/Ocelot/tree/master/src/Ocelot/ServiceDiscovery发现了这个文件夹后来仿着这个继续改造。后来写的差不多的时候准备调试输入具体转发路径的时候一直报UnableToFindServiceDiscoveryProviderError:Unable to find service discovery provider for type: nacos刚开始我一直没有找到原因明明我已经给IServiceDiscoveryProvider注册了NacosDiscovery实例它却还是说找不到找了老长时间后来我想到了去Ocelot源码查到UnableToFindServiceDiscoveryProviderError的引用最后在ServiceDiscoveryProviderFactory类看到了如下代码Ocelot的规则就是注册的Type类型要和自定义的IServiceDiscoveryProvider实现类名称一致才可以private ResponseIServiceDiscoveryProvider GetServiceDiscoveryProvider(ServiceProviderConfiguration config, DownstreamRoute route)
{if (config.Type?.ToLower() servicefabric){var sfConfig new ServiceFabricConfiguration(config.Host, config.Port, route.ServiceName);return new OkResponseIServiceDiscoveryProvider(new ServiceFabricServiceDiscoveryProvider(sfConfig));}if (_delegates ! null){var provider _delegates?.Invoke(_provider, config, route);//1.自定义的IServiceDiscoveryProvider实现类名称要和ServiceDiscoveryProvider里的Type名称一致if (provider.GetType().Name.ToLower() config.Type.ToLower()){return new OkResponseIServiceDiscoveryProvider(provider);}}//2.否则就会返回这异常信息return new ErrorResponseIServiceDiscoveryProvider(new UnableToFindServiceDiscoveryProviderError($Unable to find service discovery provider for type: {config.Type}));
}
后来把我的实现类名称改成了Nacos果然可以了当时出这个异常的时候非常困惑还好我没放弃。总结 总之通过本次扩展踩了很多坑也加深了相应的了解希望能为有自定义扩展注册中心的同学提供一点帮助。Ocelot本身文档非常详细但是对于扩展这一块没有过多的介绍只能通过查看相关源码去了解。我觉得许多东西既然开源了需要有自定义需求的可以通过查看源码解决问题。虽然查看源码其实并不容易如果有针对性的话相对来说还不是很复杂。重点是遇到问题你怎么解决能否扛得住这种无助的心情只能靠自己说不定坚持一下就找到思路了。