consul:啥?我被優化沒了?AgileConfig+Yarp替代Ocelot+Consul實現服務發現和自動網關配置

来源:https://www.cnblogs.com/xdq-zh/p/18122481
-Advertisement-
Play Games

現在軟體就業環境不景氣,各行各業都忙著裁員優化。作為一個小開發,咱也不能光等著別人來優化咱,也得想辦法優化下自己。就拿手頭上的工作來說吧,我發現我的微服務應用里,既有AgileConfig這個配置中心組件,又有一個Consul 服務發現組件。本來吧他倆也沒啥事,各幹個的。但是,我在操作AgileCo ...


現在軟體就業環境不景氣,各行各業都忙著裁員優化。作為一個小開發,咱也不能光等著別人來優化咱,也得想辦法優化下自己。就拿手頭上的工作來說吧,我發現我的微服務應用里,既有AgileConfig這個配置中心組件,又有一個Consul 服務發現組件。本來吧他倆也沒啥事,各幹個的。但是,我在操作AgileConfig的時候發現了一個事image
然後我又一百度發現了這個AgileConfig 1.6.0 發佈 - 支持服務註冊與發現 - Agile.Zhou - 博客園 (cnblogs.com),有點意思。稍微一思索,我們現在的微服務解決方案里網關用的ocelot+consul 作為HTTP api網關,同時 還是用了 yarp做 grpc的網關,明顯可以看出來有一套多餘的網關在這裡。基於目前的情況,我是一直想優化掉 ocelot+consul這個組合。改用 agileConfig+yarp,奈何前期對微服務機制不是很熟悉,有堆坑要填。現在看到agileconfig的服務列表,又勾起了我這個優化的想法。說乾就乾,我理想的目標是可以直接從agileconfig上獲取到所有註冊的服務,然後用代碼來動態給yarp添加代理配置。這樣既可以優化掉一個consul服務,又可以免去每次服務部署時繁瑣的網關配置。

首先第一個任務就是解決yarp如何用代碼實現動態配置的問題。bing 里搜索 yarp 動態配置 ,優先看博客園的博主發的文章,事實上我也就只看了這一篇Welcome to YARP - 2.2 配置功能 - 配置提供者(Configuration Providers) - coding-y - 博客園 (cnblogs.com) 。完美,問題解決。下麵就是代碼時間。

通過上面兩篇文章我們知道,agileconfig會提供一個IDiscoveryService 介面來供程式獲取註冊的服務信息。同時 yarp也提供了從記憶體中提供配置的 InMemoryConfigProvider ,那我們只需要在agileconfig 註冊之後 通過 IDisconverService介面 獲取所有已註冊服務,然後再讓yarp應用上記憶體中的配置即可實現服務註冊後自動配置代理的需求。

下麵我們動動手指頭 按下 ctrl c ,ctrl v實現如下代碼:代碼不具備通用性 需要進一步優化 建議已給出。

using AgileConfig.Client;
using AgileConfig.Client.RegisterCenter;
using Newtonsoft.Json.Linq;

using Yarp.ReverseProxy.Configuration;
using Yarp.ReverseProxy.Transforms;

namespace Microsoft.Extensions.DependencyInjection
{
    public static class AgileConfigProxyConfigProviderExtend
    {
        const string NotProxyStr = "notProxy";
        const string TransformsStr = "Transforms";
        static readonly ILogger _Logger = LoggerFactory.Create(b => { }).CreateLogger("AgileConfigProxyConfigProviderExtend");
        public static RouteConfig[] GetRoutes(this IDiscoveryService discoveryService)
        {
            var routes = new List<RouteConfig>();
            foreach (var item in discoveryService.Services)
            {
                if (item.MetaData.Any(r=>r.Equals(NotProxyStr, StringComparison.OrdinalIgnoreCase)))
                {
                    continue;
                }
                var route = new RouteConfig
                {
                    RouteId = item.ServiceId,
                    ClusterId = item.ServiceName,
                    Match = new RouteMatch
                    {
                        Path = $"/{item.ServiceName}/{{**all}}"
                    }
                };
                //.WithTransformPathRouteValues(pattern: new PathString("/{**all}"))
                try
                {
                    var transformStr = item.MetaData.FirstOrDefault(r => r.StartsWith(TransformsStr));
                    if (transformStr is not null)
                    {
                        var jobj = JObject.Parse(transformStr.Split(':')[1]);
                        foreach (var k in jobj)
                        {
                            route.WithTransform(d => d.Add(k.Key, k.Value?.ToString() ?? ""));
                        }
                    }
                }
                catch (Exception e)
                {
                    _Logger.LogError(e,"生成路由【轉換】配置時出錯");
                }

                routes.Add(route);
                _Logger.LogTrace("添加路由{RouteId}", route.RouteId);
            }
            return routes.ToArray();
        }
        public static ClusterConfig[] GetClusters(this IDiscoveryService discoveryService)
        {
            var clusters = new List<ClusterConfig>();
            var proxyServices = discoveryService.Services
                                    .Where(r => !r.MetaData.Any(r => r.Equals(NotProxyStr, StringComparison.OrdinalIgnoreCase)))
                                    .GroupBy(p => p.ServiceName);

            foreach (var item in proxyServices)
            {
                var destinations = new Dictionary<string, DestinationConfig>(StringComparer.OrdinalIgnoreCase);
                foreach (var service in item)
                {
                    destinations.Add(service.ServiceId, new DestinationConfig() {
                        Address=service.AsHttpHost()
                    });
                }

                clusters.Add(new ClusterConfig
                {
                    ClusterId = item.Key,
                    Destinations = destinations
                });
            }

            return clusters.ToArray();
        }
        //可以再加一個重載 支持傳入一個委托 來自定義構造配置。
        public static IReverseProxyBuilder LoadFromAgileConfigByInMemoryConfigProvider(this IReverseProxyBuilder builder, ConfigClient client)
        {
            var discoveryService = client.DiscoveryService();
            discoveryService ??= new DiscoveryService(client, LoggerFactory.Create(b => b.SetMinimumLevel(LogLevel.Information)));

            var configProvider = new InMemoryConfigProvider(discoveryService.GetRoutes(), discoveryService.GetClusters());

            builder.Services.AddSingleton(configProvider);
            builder.Services.AddSingleton<IProxyConfigProvider>(configProvider);

            discoveryService.ReLoaded += () =>
            {
                configProvider.Update(discoveryService.GetRoutes(), discoveryService.GetClusters());
            };
            return builder;
        }
    }
}

現在只需要調用如下代碼,即可給原有的yarp服務加上自動生成代理配置的功能了。

builder.Services.AddReverseProxy()//添加ReverseProxy相關服務到DI

.LoadFromAgileConfigByInMemoryConfigProvider((ConfigClient)client);

註意:註冊AgileConfig時候請使用 UseAgileConfig()方法註冊。Addxxx方法會導致無法獲取到agileConfig上的已註冊服務對信息。
代碼已傳gitee:https://gitee.com/dotnetfans/yarp-auto-proxy.-agile-config
同時也個給agileConfig 提交了合併請求。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 永久激活支持全家桶所有軟體,包括 Pycharm、IDEA、WebStorm、Phpstorm、Datagrip、RubyMine、CLion、AppCode 下麵以 Intellij IDEA 作為演示。 準備工作:下載插件包 https://qweree.cn/index.php/259/(如果 ...
  • 本文介紹基於Python中ArcPy模塊,實現Excel數據讀取並生成矢量圖層,同時進行IDW插值與批量掩膜的方法。 1 任務需求 首先,我們來明確一下本文所需實現的需求。 現有一個記錄有北京市部分PM2.5濃度監測站點在2019年05月18日00時至23時(其中不含19時)等23個逐小時PM2.5 ...
  • (適用於.NET/.NET Core/.NET Framework) 【目錄】0.前言1.第一個AOP程式2.Aspect橫切麵編程3.一個橫切麵程式攔截多個主程式4.多個橫切麵程式攔截一個主程式5.AOP的泛型處理(擴充)6.AOP的非同步處理(擴充)7.優勢總結8.展望 0.前言 AOP(Aspe ...
  • 使用 Quartz.NET,你可以很容易地安排任務在應用程式啟動時運行,或者每天、每周、每月的特定時間運行,甚至可以基於更複雜的調度規則。 官網:http://www.quartz-scheduler.net/ 實現任務類 創建一個實現了 IJob 介面的類(MailJobTest),該介面包含一個 ...
  • Avalonia是一個跨平臺的.NET UI框架,它允許開發者使用C#和XAML來創建豐富的桌面應用程式。在Avalonia中,Alignment、Margin和Padding是非常重要的佈局屬性,它們與Panel元素一起使用,可以構建出各種複雜的用戶界面。 Alignment、Margin 和 P ...
  • 開發了TensorRT C# API 2.0版本,該版本在開發時充分考慮了上一版本應用時出現的問題,併進行了改進。為了更加方便開發者使用,在本次更新中增加了對動態輸入模型的支持,將在本技術文中詳細介紹本次更新內容以及應用案例。 ...
  • 概述:在C#中,正則表達式`\d`相對於`[0-9]`可能效率稍低,因為`\d`包含更廣泛的Unicode數字字元。為提高性能,可使用`[0-9]`並結合編譯優化。以下示例演示性能測試及優化,適用於提高正則表達式匹配效率的場景。 在C#中,正則表達式\d涵蓋更廣泛的 Unicode 數字字元範圍,而 ...
  • 對於 API 壓測:舊電腦輕鬆就打滿CPU,主要是被ab和其它應用吃了資源,所以壓測上不去,去掉虛擬機兩核後,還能壓出2萬3的qps,已經很不容易了。新電腦上限太高,連 wrk 都壓不住,都上10萬+了,CPU也才20%左右,可見一個高效的CPU對併發的提升是多麼明顯。最後部署在 Linux,可以感... ...
一周排行
    -Advertisement-
    Play Games
  • 前言 插件化的需求主要源於對軟體架構靈活性的追求,特別是在開發大型、複雜或需要不斷更新的軟體系統時,插件化可以提高軟體系統的可擴展性、可定製性、隔離性、安全性、可維護性、模塊化、易於升級和更新以及支持第三方開發等方面的能力,從而滿足不斷變化的業務需求和技術挑戰。 一、插件化探索 在WPF中我們想要開 ...
  • 歡迎ReaLTaiizor是一個用戶友好的、以設計為中心的.NET WinForms項目控制項庫,包含廣泛的組件。您可以使用不同的主題選項對項目進行個性化設置,並自定義用戶控制項,以使您的應用程式更加專業。 項目地址:https://github.com/Taiizor/ReaLTaiizor 步驟1: ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • Channel 是乾什麼的 The System.Threading.Channels namespace provides a set of synchronization data structures for passing data between producers and consume ...
  • efcore如何優雅的實現按年分庫按月分表 介紹 本文ShardinfCore版本 本期主角: ShardingCore 一款ef-core下高性能、輕量級針對分表分庫讀寫分離的解決方案,具有零依賴、零學習成本、零業務代碼入侵適配 距離上次發文.net相關的已經有很久了,期間一直在從事java相關的 ...
  • 前言 Spacesniffer 是一個免費的文件掃描工具,通過使用樹狀圖可視化佈局,可以立即瞭解大文件夾的位置,幫助用戶處理找到這些文件夾 當前系統C盤空間 清理後系統C盤空間 下載 Spacesniffer 下載地址:https://spacesniffer.en.softonic.com/dow ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • 一、ReZero簡介 ReZero是一款.NET中間件 : 全網唯一開源界面操作就能生成API , 可以集成到任何.NET6+ API項目,無破壞性,也可讓非.NET用戶使用exe文件 免費開源:MIT最寬鬆協議 , 一直從事開源事業十年,一直堅持開源 1.1 純ReZero開發 適合.Net Co ...
  • 一:背景 1. 講故事 停了一個月沒有更新文章了,主要是忙於寫 C#內功修煉系列的PPT,現在基本上接近尾聲,可以回頭繼續更新這段時間分析dump的一些事故報告,有朋友微信上找到我,說他們的系統出現了大量的http超時,程式不響應處理了,讓我幫忙看下怎麼回事,dump也抓到了。 二:WinDbg分析 ...
  • 開始做項目管理了(本人3年java,來到這邊之後真沒想到...),天天開會溝通整理需求,他們講話的時候忙裡偷閑整理一下常用的方法,其實語言還是有共通性的,基本上看到方法名就大概能猜出來用法。出去打水的時候看到外面太陽好好,真想在外面坐著曬太陽,回來的時候好兄弟三年前送給我的鍵盤D鍵不靈了,在打"等待 ...