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
  • GoF之工廠模式 @目錄GoF之工廠模式每博一文案1. 簡單說明“23種設計模式”1.2 介紹工廠模式的三種形態1.3 簡單工廠模式(靜態工廠模式)1.3.1 簡單工廠模式的優缺點:1.4 工廠方法模式1.4.1 工廠方法模式的優缺點:1.5 抽象工廠模式1.6 抽象工廠模式的優缺點:2. 總結:3 ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 本章將和大家分享ES的數據同步方案和ES集群相關知識。廢話不多說,下麵我們直接進入主題。 一、ES數據同步 1、數據同步問題 Elasticsearch中的酒店數據來自於mysql資料庫,因此mysql數據發生改變時,Elasticsearch也必須跟著改變,這個就是Elasticsearch與my ...
  • 引言 在我們之前的文章中介紹過使用Bogus生成模擬測試數據,今天來講解一下功能更加強大自動生成測試數據的工具的庫"AutoFixture"。 什麼是AutoFixture? AutoFixture 是一個針對 .NET 的開源庫,旨在最大程度地減少單元測試中的“安排(Arrange)”階段,以提高 ...
  • 經過前面幾個部分學習,相信學過的同學已經能夠掌握 .NET Emit 這種中間語言,並能使得它來編寫一些應用,以提高程式的性能。隨著 IL 指令篇的結束,本系列也已經接近尾聲,在這接近結束的最後,會提供幾個可供直接使用的示例,以供大伙分析或使用在項目中。 ...
  • 當從不同來源導入Excel數據時,可能存在重覆的記錄。為了確保數據的準確性,通常需要刪除這些重覆的行。手動查找並刪除可能會非常耗費時間,而通過編程腳本則可以實現在短時間內處理大量數據。本文將提供一個使用C# 快速查找並刪除Excel重覆項的免費解決方案。 以下是實現步驟: 1. 首先安裝免費.NET ...
  • C++ 異常處理 C++ 異常處理機制允許程式在運行時處理錯誤或意外情況。它提供了捕獲和處理錯誤的一種結構化方式,使程式更加健壯和可靠。 異常處理的基本概念: 異常: 程式在運行時發生的錯誤或意外情況。 拋出異常: 使用 throw 關鍵字將異常傳遞給調用堆棧。 捕獲異常: 使用 try-catch ...
  • 優秀且經驗豐富的Java開發人員的特征之一是對API的廣泛瞭解,包括JDK和第三方庫。 我花了很多時間來學習API,尤其是在閱讀了Effective Java 3rd Edition之後 ,Joshua Bloch建議在Java 3rd Edition中使用現有的API進行開發,而不是為常見的東西編 ...
  • 框架 · 使用laravel框架,原因:tp的框架路由和orm沒有laravel好用 · 使用強制路由,方便介面多時,分多版本,分文件夾等操作 介面 · 介面開發註意欄位類型,欄位是int,查詢成功失敗都要返回int(對接java等強類型語言方便) · 查詢介面用GET、其他用POST 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...