【NET CORE微服務一條龍應用】第一章 閘道器使用與配置
簡介
微服務的系統應用中,閘道器係統使用的是ocelot,ocelot目前已經比較成熟了
ocelot就不做介紹了,等整體介紹完後再進行各類擴充套件介紹,ocelot原始碼地址:
ocelot目前由很多功能元件組成,每個元件都可以根據自己的實際情況進行擴充套件(暫時不做過多介紹)
本文主要介紹ocelot閘道器使用中個人認為應該最先處理的東西
健康檢查
在實際的應用中閘道器專案都會部署多臺,然後透過nginx進行軟負載,在更新部署閘道器專案的過程中服務肯定是無法使用,這個時候我們就需要利用nginx的健康檢查機制進行控制
閘道器需要給nginx提供一個健康檢查地址,ocelot使用的url path地址進行路由匹配,當匹配不到時會返回404,所以我們需要單獨處理一個健康檢查地址
Ocelot提供了一箇中介軟體配置替換的方法OcelotPipelineConfiguration,我們對OcelotPipelineConfiguration的PreErrorResponderMiddleware中介軟體方法進行擴充套件,程式碼如下:
1 var conf = new OcelotPipelineConfiguration() 2 { 3 PreErrorResponderMiddleware = async (ctx, next) => 4 { 5 if (ctx.HttpContext.Request.Path.Equals(new PathString("/"))) 6 { 7 await ctx.HttpContext.Response.WriteAsync("ok"); 8 } 9 else10 {11 await next.Invoke();12 }13 }14 };15 app.UseOcelot(conf).Wait();
閘道器和路由配置
閘道器的配置包含四個部分,ReRoutes、DynamicReRoutes、Aggregates、GlobalConfiguration,
ocelot配置的獲取預設是使用配置檔案的方式,上面已經說了閘道器一般都會部署多臺,使用檔案配置還是存在一定弊端
ocelot的配置獲取方法是IFileConfigurationRepository介面,所以如果我們實現了此介面就可以滿足配置儲存方式的擴充套件,目前已擴充套件mysql和redis,程式碼如下
redis:
1 public class RedisFileConfigurationRepository: IFileConfigurationRepository 2 { 3 private readonly RedisClient _redisClient; 4 private readonly string _apiGatewayKey; 5 private readonly string _redisConnection; 6 7 public RedisFileConfigurationRepository(RedisClient redisClient, string apiGatewayKey, string redisConnection) 8 { 9 _redisClient = redisClient;10 _apiGatewayKey = apiGatewayKey;11 _redisConnection = redisConnection;12 }13 14 public async Task<Response<FileConfiguration>> Get()15 {16 var redis = _redisClient.GetDatabase(_redisConnection, 11);17 18 var json = await redis.StringGetAsync($"ApiGatewayConfig:{_apiGatewayKey}");19 20 if(json.IsNullOrEmpty)21 return new OkResponse<FileConfiguration>(new FileConfiguration { });22 23 var fileConfig = JsonConvert.DeserializeObject<FileConfiguration>(json);24 25 return new OkResponse<FileConfiguration>(fileConfig);26 }27 28 public async Task<Response> Set(FileConfiguration fileConfiguration)29 {30 return await Task.FromResult(new OkResponse());31 }32 }
mysql:
1 public class MySqlFileConfigurationRepository : IFileConfigurationRepository 2 { 3 private readonly IDbRepository<ConfigurationInfo> _configDbRepository; 4 private readonly IDbRepository<ReRouteInfo> _routeDbRepository; 5 private readonly string _apiGatewayKey; 6 7 public MySqlFileConfigurationRepository(IDbRepository<ConfigurationInfo> configDbRepository, IDbRepository<ReRouteInfo> routeDbRepository, string apiGatewayKey) 8 { 9 _configDbRepository = configDbRepository; 10 _routeDbRepository = routeDbRepository; 11 _apiGatewayKey = apiGatewayKey; 12 } 13 14 public async Task<Response<FileConfiguration>> Get() 15 { 16 var st = DateTime.Now; 17 var fileConfig = new FileConfiguration(); 18 var configInfo = await _configDbRepository.GetFirstAsync(it => it.GatewayKey == _apiGatewayKey); 19 if (configInfo != null) 20 { 21 // config 22 var fgc = new FileGlobalConfiguration 23 { 24 BaseUrl = configInfo.BaseUrl, 25 DownstreamScheme = configInfo.DownstreamScheme, 26 RequestIdKey = configInfo.RequestIdKey, 27 }; 28 if (!string.IsNullOrWhiteSpace(configInfo.HttpHandlerOptions)) 29 fgc.HttpHandlerOptions = ToObject<FileHttpHandlerOptions>(configInfo.HttpHandlerOptions); 30 if (!string.IsNullOrWhiteSpace(configInfo.LoadBalancerOptions)) 31 fgc.LoadBalancerOptions = ToObject<FileLoadBalancerOptions>(configInfo.LoadBalancerOptions); 32 if (!string.IsNullOrWhiteSpace(configInfo.QoSOptions)) 33 fgc.QoSOptions = ToObject<FileQoSOptions>(configInfo.QoSOptions); 34 if (!string.IsNullOrWhiteSpace(configInfo.RateLimitOptions)) 35 fgc.RateLimitOptions = ToObject<FileRateLimitOptions>(configInfo.RateLimitOptions); 36 if (!string.IsNullOrWhiteSpace(configInfo.ServiceDiscoveryProvider)) 37 fgc.ServiceDiscoveryProvider = ToObject<FileServiceDiscoveryProvider>(configInfo.ServiceDiscoveryProvider); 38 fileConfig.GlobalConfiguration = fgc; 39 40 // reroutes 41 var reRouteResult = await _routeDbRepository.GetListAsync(it => it.GatewayId == configInfo.GatewayId && it.State == 1); 42 if (reRouteResult.Count > 0) 43 { 44 var reroutelist = new List<FileReRoute>(); 45 foreach (var model in reRouteResult) 46 { 47 var m = new FileReRoute() 48 { 49 UpstreamHost = model.UpstreamHost, 50 UpstreamPathTemplate = model.UpstreamPathTemplate, 51 52 DownstreamPathTemplate = model.DownstreamPathTemplate, 53 DownstreamScheme = model.DownstreamScheme, 54 55 ServiceName = model.ServiceName, 56 Priority = model.Priority, 57 RequestIdKey = model.RequestIdKey, 58 Key = model.Key, 59 Timeout = model.Timeout, 60 }; 61 if (!string.IsNullOrWhiteSpace(model.UpstreamHttpMethod)) 62 m.UpstreamHttpMethod = ToObject<List<string>>(model.UpstreamHttpMethod); 63 if (!string.IsNullOrWhiteSpace(model.DownstreamHostAndPorts)) 64 m.DownstreamHostAndPorts = ToObject<List<FileHostAndPort>>(model.DownstreamHostAndPorts); 65 if (!string.IsNullOrWhiteSpace(model.SecurityOptions)) 66 m.SecurityOptions = ToObject<FileSecurityOptions>(model.SecurityOptions); 67 if (!string.IsNullOrWhiteSpace(model.CacheOptions)) 68 m.FileCacheOptions = ToObject<FileCacheOptions>(model.CacheOptions); 69 if (!string.IsNullOrWhiteSpace(model.HttpHandlerOptions)) 70 m.HttpHandlerOptions = ToObject<FileHttpHandlerOptions>(model.HttpHandlerOptions); 71 if (!string.IsNullOrWhiteSpace(model.AuthenticationOptions)) 72 m.AuthenticationOptions = ToObject<FileAuthenticationOptions>(model.AuthenticationOptions); 73 if (!string.IsNullOrWhiteSpace(model.RateLimitOptions)) 74 m.RateLimitOptions = ToObject<FileRateLimitRule>(model.RateLimitOptions); 75 if (!string.IsNullOrWhiteSpace(model.LoadBalancerOptions)) 76 m.LoadBalancerOptions = ToObject<FileLoadBalancerOptions>(model.LoadBalancerOptions); 77 if (!string.IsNullOrWhiteSpace(model.QoSOptions)) 78 m.QoSOptions = ToObject<FileQoSOptions>(model.QoSOptions); 79 if (!string.IsNullOrWhiteSpace(model.DelegatingHandlers)) 80 m.DelegatingHandlers = ToObject<List<string>>(model.DelegatingHandlers); 81 reroutelist.Add(m); 82 } 83 fileConfig.ReRoutes = reroutelist; 84 } 85 } 86 Console.WriteLine((DateTime.Now - st).TotalMilliseconds); 87 return new OkResponse<FileConfiguration>(fileConfig); 88 } 89 90 public async Task<Response> Set(FileConfiguration fileConfiguration) 91 { 92 return await Task.FromResult(new OkResponse()); 93 } 94 95 /// <summary> 96 /// 將Json字串轉換為物件 97 /// </summary> 98 /// <param name="json">Json字串</param> 99 private T ToObject<T>(string json)100 {101 if (string.IsNullOrWhiteSpace(json))102 return default(T);103 return JsonConvert.DeserializeObject<T>(json);104 }105 }
可以看到四項配置裡並不是全部都進行可配置化,如果有需求可以自行增加欄位實現
redis的儲存是大json方式,而mysql是一條一條的,因為配置的管理是以mysql為主,然後同步到其他儲存介質中的
閘道器配置的更新
有載入就有更新,在ocelot中配置的更新是使用自己的實現來完成配置的熱更新,方式如下
1、配置檔案方式是透過配置檔案的IOptionsMonitor的OnChange方式重新載入配置資訊
2、第三方儲存方式是透過預設實現的FileConfigurationPoller方法定時(預設1s)取獲取配置資訊的
所以我們擴充套件的獲取配置形式,在註冊的時候要把FileConfigurationPoller HostedService一同注入進去,程式碼如下
1 public static IOcelotBuilder AddConfigStoredInRedis(this IOcelotBuilder builder, string apiGatewayKey, string redisConnectionString) 2 { 3 builder.Services.AddSingleton<RedisClient>(); 4 builder.Services.AddHostedService<FileConfigurationPoller>(); 5 builder.Services.AddSingleton<IFileConfigurationRepository>(sp => 6 { 7 return new RedisFileConfigurationRepository(sp.GetRequiredService<RedisClient>(), apiGatewayKey, redisConnectionString); 8 }); 9 return builder;10 }
其中涉及到Bucket.DbContext和Bucket.Redis元件很簡單,也可自行實現
配置的管理
其實最開始的時候,使用的是consul儲存配置,然後透過閘道器自帶的配置介面進行配置的管理,但是在ocelot的一次升級的時候出現了一個問題(配置資訊丟失),雖然當時修改了ocelot的原始碼解決了,後來還是決定擴充套件儲存方式,所以上面的獲取配置介面的set方法都不實現了
上面已經說了是已mysql進行配置儲存然後同步到其他介質上,所以我們只要維護好mysql資料庫就可以了
具體程式碼就不貼了,後續會進行具體介紹,管理專案地址:,截幾張管理圖
原文出處:https://www.cnblogs.com/tianxiangzhe/p/10336923.html
作者:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3016/viewspace-2820883/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- .NET Core 微服務—API閘道器(Ocelot) 教程 [一]微服務API
- .NET Core 微服務—API閘道器(Ocelot) 教程 [四]微服務API
- .NET Core微服務開發閘道器篇-ocelot微服務
- 第一章 微服務閘道器 - 入門微服務
- .Net Core微服務——閘道器(2):ocelot整合consul微服務
- 基於.NET CORE微服務框架 -Api閘道器服務管理微服務框架API
- .Net Core微服務——閘道器(1):ocelot整合及介紹微服務
- .NETCore微服務探尋(一) - 閘道器NetCore微服務
- 微服務閘道器微服務
- 基於.NET CORE微服務框架 -談談surging API閘道器微服務框架API
- 微服務閘道器- Nginx微服務Nginx
- Hystrix斷路器在微服務閘道器中的應用微服務
- Profinet轉ModbusTCP閘道器模組的配置與應用詳解TCP
- .Net Core微服務入門全紀錄(五)——Ocelot-API閘道器(下)微服務API
- .Net Core微服務入門全紀錄(四)——Ocelot-API閘道器(上)微服務API
- 微服務中的閘道器微服務
- 微服務閘道器Spring Cloud Gateway的應用實戰微服務SpringCloudGateway
- 微服務與閘道器技術(SIA-GateWay)微服務Gateway
- 微服務(七)Gateway服務閘道器微服務Gateway
- 微服務閘道器SIA-GateWay使用指南微服務Gateway
- 《springcloud 二》微服務動態閘道器,閘道器叢集SpringGCCloud微服務
- Asp.Net Core + Ocelot 閘道器搭建:路由簡單配置ASP.NET路由
- Janusec應用安全閘道器(WAF閘道器)
- .NET Core API閘道器Ocelot(一)【概覽,開始】API
- [譯] 使用 Go 編寫微服務及其 GraphQL 閘道器Go微服務
- 微服務閘道器 Spring Cloud Gateway微服務SpringCloudGateway
- SpringCloud 微服務閘道器 Gateway 元件SpringGCCloud微服務Gateway元件
- 微服務6:通訊之閘道器微服務
- Asp.Net Core + Ocelot 閘道器搭建:負載均衡的配置ASP.NET負載
- 為什麼微服務一定要有閘道器?微服務
- RestCloud API閘道器,無縫與原微服務框架整合RESTCloudAPI微服務框架
- 百億流量微服務閘道器的設計與實現微服務
- 微服務基礎——厲害了!API閘道器微服務API
- SpringCloud微服務治理三(Zuul閘道器)SpringGCCloud微服務Zuul
- 微服務下的閘道器如何選擇微服務
- 微服務閘道器Gateway實踐總結微服務Gateway
- 為什麼微服務需要API閘道器?微服務API
- 微服務實踐分享(2)api閘道器微服務API