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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

Ocelot简易教程(七)之配置文件数据库存储插件源码解析

發布時間:2024/4/17 数据库 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Ocelot简易教程(七)之配置文件数据库存储插件源码解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者:依樂祝
原文地址:https://www.cnblogs.com/yilezhu/p/9852711.html

上篇文章給大家分享了如何集成我寫的一個Ocelot擴展插件把Ocelot的配置存儲到數據庫中。并沒有對實現原理進行相應的闡述。今天抽空把實現的原理給大家說道說道。明白原理后,大家就可以自行改寫進行擴展來滿足自身需要了!
再次感覺張隊的審稿,并給出的修改意見!

源碼解析過程

大家可以自行分析Ocelot的源碼,我通過分析ocelot的源碼得出,如果要實現重寫配置文件的方式,只需要寫一個類來實現IFileConfigurationRepository這個接口即可。

代碼如下:

/// <summary>/// yilezhu/// 2018.10.22/// 實現從SQLSERVER數據庫中提取配置信息/// </summary>public class SqlServerFileConfigurationRepository : IFileConfigurationRepository{private readonly IOcelotCache<FileConfiguration> _cache;private readonly IOcelotLogger _logger;private readonly ConfigAuthLimitCacheOptions _option;public SqlServerFileConfigurationRepository(ConfigAuthLimitCacheOptions option, IOcelotCache<FileConfiguration> cache, IOcelotLoggerFactory loggerFactory){_option = option;_cache = cache;_logger = loggerFactory.CreateLogger<SqlServerFileConfigurationRepository>();}public Task<Response> Set(FileConfiguration fileConfiguration){_cache.AddAndDelete(_option.CachePrefix + "FileConfiguration", fileConfiguration, TimeSpan.FromSeconds(1800), "");return Task.FromResult((Response)new OkResponse());}/// <summary>/// 提取配置信息/// </summary>/// <returns></returns>public async Task<Response<FileConfiguration>> Get(){var config = _cache.Get(_option.CachePrefix + "FileConfiguration", "");if (config != null){return new OkResponse<FileConfiguration>(config);}#region 提取配置信息var file = new FileConfiguration();string glbsql = "select top 1 * from OcelotGlobalConfiguration where IsDefault=1";//提取全局配置信息using (var connection = new SqlConnection(_option.DbConnectionStrings)){var result = await connection.QueryFirstOrDefaultAsync<OcelotGlobalConfiguration>(glbsql);if (result != null){var glb = new FileGlobalConfiguration();glb.BaseUrl = result.BaseUrl;glb.DownstreamScheme = result.DownstreamScheme;glb.RequestIdKey = result.RequestIdKey;if (!String.IsNullOrEmpty(result.HttpHandlerOptions)){glb.HttpHandlerOptions = result.HttpHandlerOptions.ToObject<FileHttpHandlerOptions>();}if (!String.IsNullOrEmpty(result.LoadBalancerOptions)){glb.LoadBalancerOptions = result.LoadBalancerOptions.ToObject<FileLoadBalancerOptions>();}if (!String.IsNullOrEmpty(result.QoSOptions)){glb.QoSOptions = result.QoSOptions.ToObject<FileQoSOptions>();}if (!String.IsNullOrEmpty(result.ServiceDiscoveryProvider)){glb.ServiceDiscoveryProvider = result.ServiceDiscoveryProvider.ToObject<FileServiceDiscoveryProvider>();}file.GlobalConfiguration = glb;//提取路由信息string routesql = "select * from OcelotReRoutes where OcelotGlobalConfigurationId=@OcelotGlobalConfigurationId and IsStatus=1";var routeresult = (await connection.QueryAsync<OcelotReRoutes>(routesql, new { OcelotGlobalConfigurationId=result.Id })).AsList();if (routeresult != null && routeresult.Count > 0){var reroutelist = new List<FileReRoute>();foreach (var model in routeresult){var m = new FileReRoute();if (!String.IsNullOrEmpty(model.AuthenticationOptions)){m.AuthenticationOptions = model.AuthenticationOptions.ToObject<FileAuthenticationOptions>();}if (!String.IsNullOrEmpty(model.CacheOptions)){m.FileCacheOptions = model.CacheOptions.ToObject<FileCacheOptions>();}if (!String.IsNullOrEmpty(model.DelegatingHandlers)){m.DelegatingHandlers = model.DelegatingHandlers.ToObject<List<string>>();}if (!String.IsNullOrEmpty(model.LoadBalancerOptions)){m.LoadBalancerOptions = model.LoadBalancerOptions.ToObject<FileLoadBalancerOptions>();}if (!String.IsNullOrEmpty(model.QoSOptions)){m.QoSOptions = model.QoSOptions.ToObject<FileQoSOptions>();}if (!String.IsNullOrEmpty(model.DownstreamHostAndPorts)){m.DownstreamHostAndPorts = model.DownstreamHostAndPorts.ToObject<List<FileHostAndPort>>();}//開始賦值m.DownstreamPathTemplate = model.DownstreamPathTemplate;m.DownstreamScheme = model.DownstreamScheme;m.Key = model.Key;m.Priority = model.Priority ?? 0;m.RequestIdKey = model.RequestIdKey;m.ServiceName = model.ServiceName;m.Timeout = model.Timeout ?? 0;m.UpstreamHost = model.UpstreamHost;if (!String.IsNullOrEmpty(model.UpstreamHttpMethod)){m.UpstreamHttpMethod = model.UpstreamHttpMethod.ToObject<List<string>>();}m.UpstreamPathTemplate = model.UpstreamPathTemplate;reroutelist.Add(m);}file.ReRoutes = reroutelist;}}else{throw new Exception("未監測到配置信息");}}#endregionif (file.ReRoutes == null || file.ReRoutes.Count == 0){return new OkResponse<FileConfiguration>(null);}return new OkResponse<FileConfiguration>(file);}}

當然,既然我們已經重新實現了這個接口,那么就得進行相應的DI了。這里我們擴展下IOcelotBuilder方法,代碼如下,主要就是進行相應的服務的DI:

/// <summary>/// yilezhu/// 2018.10.22/// 基于Ocelot擴展的依賴注入/// </summary>public static class ServiceCollectionExtensions{/// <summary>/// 添加默認的注入方式,所有需要傳入的參數都是用默認值/// </summary>/// <param name="builder"></param>/// <returns></returns>public static IOcelotBuilder AddAuthLimitCache(this IOcelotBuilder builder, Action<ConfigAuthLimitCacheOptions> option){builder.Services.Configure(option);builder.Services.AddSingleton(resolver => resolver.GetRequiredService<IOptions<ConfigAuthLimitCacheOptions>>().Value);#region 注入其他配置信息//重寫提取Ocelot配置信息,builder.Services.AddSingleton(DataBaseConfigurationProvider.Get);//builder.Services.AddHostedService<FileConfigurationPoller>();builder.Services.AddSingleton<IFileConfigurationRepository, SqlServerFileConfigurationRepository>();//注入自定義限流配置//注入認證信息#endregionreturn builder;}}

接下來就是重寫,OcelotBuild里面配置文件的獲取方式了。這里我選擇的是對IApplicationBuilder進行擴展,因為這樣方便做一些其他的事情,比如,重寫限流,集成自定義的驗證等等。具體代碼如下:

/// <summary>/// yilezhu/// 2018.10.22/// 擴展IApplicationBuilder,新增use方法/// </summary>public static class OcelotMiddlewareExtensions{/// <summary>/// 擴展UseOcelot/// </summary>/// <param name="builder"></param>/// <returns></returns>public static async Task<IApplicationBuilder> UseAhphOcelot(this IApplicationBuilder builder){await builder.UseAhphOcelot(new OcelotPipelineConfiguration());return builder;}/// <summary>/// 重寫Ocelot,帶參數/// </summary>/// <param name="builder"></param>/// <param name="pipelineConfiguration"></param>/// <returns></returns>public static async Task<IApplicationBuilder> UseAhphOcelot(this IApplicationBuilder builder, OcelotPipelineConfiguration pipelineConfiguration){var configuration = await CreateConfiguration(builder);ConfigureDiagnosticListener(builder);return CreateOcelotPipeline(builder, pipelineConfiguration);}private static async Task<IInternalConfiguration> CreateConfiguration(IApplicationBuilder builder){// make configuration from file system?// earlier user needed to add ocelot files in startup configuration stuff, asp.net will map it to this//var fileConfig = builder.ApplicationServices.GetService<IOptionsMonitor<FileConfiguration>>();var fileConfig = await builder.ApplicationServices.GetService<IFileConfigurationRepository>().Get();// now create the configvar internalConfigCreator = builder.ApplicationServices.GetService<IInternalConfigurationCreator>();var internalConfig = await internalConfigCreator.Create(fileConfig.Data);//Configuration error, throw error messageif (internalConfig.IsError){ThrowToStopOcelotStarting(internalConfig);}// now save it in memoryvar internalConfigRepo = builder.ApplicationServices.GetService<IInternalConfigurationRepository>();internalConfigRepo.AddOrReplace(internalConfig.Data);//fileConfig.OnChange(async (config) =>//{// var newInternalConfig = await internalConfigCreator.Create(config);// internalConfigRepo.AddOrReplace(newInternalConfig.Data);//});var adminPath = builder.ApplicationServices.GetService<IAdministrationPath>();var configurations = builder.ApplicationServices.GetServices<OcelotMiddlewareConfigurationDelegate>();// Todo - this has just been added for consul so far...will there be an ordering problem in the future? Should refactor all config into this pattern?foreach (var configuration in configurations){await configuration(builder);}if (AdministrationApiInUse(adminPath)){//We have to make sure the file config is set for the ocelot.env.json and ocelot.json so that if we pull it from the //admin api it works...boy this is getting a spit spags boll.var fileConfigSetter = builder.ApplicationServices.GetService<IFileConfigurationSetter>();// await SetFileConfig(fileConfigSetter, fileConfig.Data);}return GetOcelotConfigAndReturn(internalConfigRepo);}private static bool AdministrationApiInUse(IAdministrationPath adminPath){return adminPath != null;}//private static async Task SetFileConfig(IFileConfigurationSetter fileConfigSetter, IOptionsMonitor<FileConfiguration> fileConfig)//{// var response = await fileConfigSetter.Set(fileConfig.CurrentValue);// if (IsError(response))// {// ThrowToStopOcelotStarting(response);// }//}private static bool IsError(Response response){return response == null || response.IsError;}private static IInternalConfiguration GetOcelotConfigAndReturn(IInternalConfigurationRepository provider){var ocelotConfiguration = provider.Get();if (ocelotConfiguration?.Data == null || ocelotConfiguration.IsError){ThrowToStopOcelotStarting(ocelotConfiguration);}return ocelotConfiguration.Data;}private static void ThrowToStopOcelotStarting(Response config){throw new Exception($"Unable to start Ocelot, errors are: {string.Join(",", config.Errors.Select(x => x.ToString()))}");}private static IApplicationBuilder CreateOcelotPipeline(IApplicationBuilder builder, OcelotPipelineConfiguration pipelineConfiguration){var pipelineBuilder = new OcelotPipelineBuilder(builder.ApplicationServices);//重寫自定義管道pipelineBuilder.BuildAhphOcelotPipeline(pipelineConfiguration);var firstDelegate = pipelineBuilder.Build();/*inject first delegate into first piece of asp.net middleware..maybe not like thisthen because we are updating the http context in ocelot it comes out correct forrest of asp.net..*/builder.Properties["analysis.NextMiddlewareName"] = "TransitionToOcelotMiddleware";builder.Use(async (context, task) =>{var downstreamContext = new DownstreamContext(context);await firstDelegate.Invoke(downstreamContext);});return builder;}private static void ConfigureDiagnosticListener(IApplicationBuilder builder){var env = builder.ApplicationServices.GetService<IHostingEnvironment>();var listener = builder.ApplicationServices.GetService<OcelotDiagnosticListener>();var diagnosticListener = builder.ApplicationServices.GetService<DiagnosticListener>();diagnosticListener.SubscribeWithAdapter(listener);}}

這其中最主要的代碼就是,重寫配置文件獲取這塊。我在下面進行了截圖,并圈出來了,大家自行查看吧。

代碼重寫好了。由于我們服務注冊時通過擴展IOcelotBuilder,所以,我們需要在ConfigureServices方法引入Ocelot服務的時候比Ocelot多寫一個方法,并傳入相關的配置信息,如下所示:

services.AddOcelot()//注入Ocelot服務.AddAuthLimitCache(option=> {option.DbConnectionStrings = "Server=.;Database=Ocelot;User ID=sa;Password=1;";});

這里的目的就是為了注入我們實現了IFileConfigurationRepository接口的SqlServerFileConfigurationRepository這個類。

接下來就是在管道中使用我們重寫的Ocelot服務了。如下所示,在Configure方法中按如下代碼進行使用:

app.UseAhphOcelot().Wait();

好了,以上就是實現的整個過程了。經過這么一分析是不是覺得很簡單呢。當然具體為什么按照上面處理就能夠從數據庫獲取配置了呢,這個還需要你分析了源碼后才能了解。我也只是給你引路,傳達我實現的思路。

源碼

https://github.com/yilezhu/Ocelot.ConfigAuthLimitCache

總結

今天抽空對上篇文章進行了補充說明,目的是給大家闡述下,配置文件存儲到數據庫中的實現過程及原理。讓你能夠根據自身需要來進行改寫來滿足你的業務需求。當然我也只是給你引路,具體為什么這樣實現下就能夠成功呢?答案在Ocelot的源碼中。

如果你想了解更多Ocelot的定制相關的·內容可以看我一個朋友寫的系列博客,博客地址:https://www.cnblogs.com/jackcao/p/9928879.html 【.NET Core微服務實戰-統一身份認證】網關篇,這里給你詳細介紹了如何進行自定義限流以及客戶端授權并重寫Ocelot緩存成Redis!有興趣的可以看下!

?

作者:依樂祝

出處:https://www.cnblogs.com/yilezhu

聯系:1015657114@qq.com .NET Core實戰項目交流群:637326624

本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。如有問題或建議,請多多賜教,非常感謝。

轉載于:https://www.cnblogs.com/bigmango/p/10393108.html

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的Ocelot简易教程(七)之配置文件数据库存储插件源码解析的全部內容,希望文章能夠幫你解決所遇到的問題。

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