日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

手动造轮子——为Ocelot集成Nacos注册中心

發布時間:2023/12/4 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 手动造轮子——为Ocelot集成Nacos注册中心 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

????近期在看博客的時候或者在群里看聊天的時候,發現很多都提到了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/Ocelot

Nacos

????關于Nacos我之前的文章搭建一套ASP.NET Core+Nacos+Spring Cloud Gateway項目已經有過介紹了。Nacos是阿里巴巴開源的致力于服務發現、配置和管理微服務的框架。提供了一組簡單易用的特性集,幫助您快速實現動態服務發現、服務配置、服務元數據及流量管理。一般用到的最多的就是當做配置中心和注冊中心。

  • 中文官網地址:https://nacos.io/zh-cn/

  • 官方GitHub地址:https://github.com/alibaba/nacos

Ocelot.Provider.Nacos

開發環境

  • 基于.Net Core 3.1,這個是必須的,因為最新穩定版的Ocelot是在.Net Core 3.1上構建的,而我恰好選擇的是這個版本的Ocelot

  • Ocelot選擇的是目前最新的穩定版本 v16.0.1

  • Nacos訪問組件實用的是nacos-sdk-csharp,具體引用的是

<PackageReference Include="nacos-sdk-csharp-unofficial" Version="0.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 Include="Ocelot.Provider.Nacos" Version="1.0.0" />

然后在ConfigureServices中添加注冊方法AddNacosDiscovery

public 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.AddSingleton<ServiceDiscoveryFinderDelegate>(NacosProviderFactory.Get);//根據Ocelot配置文件相關內容設置處理服務發現相關builder.Services.AddSingleton<OcelotMiddlewareConfigurationDelegate>(NacosMiddlewareConfigurationProvider.Get);return builder; }

其次,將自定義的注冊發現相關操作提供出來,其實主要就是獲取服務地址

public static class NacosProviderFactory {public static ServiceDiscoveryFinderDelegate Get = (provider, config, route) =>{//Nacos相關服務類var client = provider.GetService<INacosServerManager>();//判斷類型是否為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 Task<List<Service>> Get(){var services = new List<Service>();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 List<string>())));}return await Task.FromResult(services);} }

最后,根據Ocelot配置相關的信息判斷是否啟動Nacos相關服務

public class NacosMiddlewareConfigurationProvider {public static OcelotMiddlewareConfigurationDelegate Get = builder =>{var internalConfigRepo = builder.ApplicationServices.GetService<IInternalConfigurationRepository>();var config = internalConfigRepo.Get();var hostLifetime = builder.ApplicationServices.GetService<IHostApplicationLifetime>();//判斷服務注冊類型是否為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 Response<IServiceDiscoveryProvider> GetServiceDiscoveryProvider(ServiceProviderConfiguration config, DownstreamRoute route) {if (config.Type?.ToLower() == "servicefabric"){var sfConfig = new ServiceFabricConfiguration(config.Host, config.Port, route.ServiceName);return new OkResponse<IServiceDiscoveryProvider>(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 OkResponse<IServiceDiscoveryProvider>(provider);}}//2.否則就會返回這異常信息return new ErrorResponse<IServiceDiscoveryProvider>(new UnableToFindServiceDiscoveryProviderError($"Unable to find service discovery provider for type: {config.Type}")); }

后來把我的實現類名稱改成了Nacos果然可以了,當時出這個異常的時候非常困惑,還好我沒放棄。

總結

????總之,通過本次擴展,踩了很多坑,也加深了相應的了解,希望能為有自定義擴展注冊中心的同學提供一點幫助。Ocelot本身文檔非常詳細,但是對于擴展這一塊沒有過多的介紹,只能通過查看相關源碼去了解。我覺得許多東西既然開源了,需要有自定義需求的可以通過查看源碼解決問題。雖然查看源碼其實并不容易,如果有針對性的話,相對來說還不是很復雜。重點是遇到問題你怎么解決,能否扛得住這種無助的心情,只能靠自己,說不定堅持一下就找到思路了。

總結

以上是生活随笔為你收集整理的手动造轮子——为Ocelot集成Nacos注册中心的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。