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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...