栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

第一章 网关使用与配置

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

第一章 网关使用与配置

简介

  微服务的系统应用中,网关系统使用的是ocelot,ocelot目前已经比较成熟了

  ocelot就不做介绍了,等整体介绍完后再进行各类扩展介绍,ocelot源码地址:https://github.com/ThreeMammals/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> 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(new FileConfiguration { });22 23             var fileConfig = JsonConvert.DeserializeObject(json);24 25             return new OkResponse(fileConfig);26         }27 28         public async Task Set(FileConfiguration fileConfiguration)29         {30             return await Task.FromResult(new OkResponse());31         }32     }

mysql:

  1 public class MySqlFileConfigurationRepository : IFileConfigurationRepository  2     {  3         private readonly IDbRepository _configDbRepository;  4         private readonly IDbRepository _routeDbRepository;  5         private readonly string _apiGatewayKey;  6   7         public MySqlFileConfigurationRepository(IDbRepository configDbRepository, IDbRepository routeDbRepository, string apiGatewayKey)  8         {  9             _configDbRepository = configDbRepository; 10             _routeDbRepository = routeDbRepository; 11             _apiGatewayKey = apiGatewayKey; 12         } 13  14         public async Task> 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(configInfo.HttpHandlerOptions); 30                 if (!string.IsNullOrWhiteSpace(configInfo.LoadBalancerOptions)) 31                     fgc.LoadBalancerOptions = ToObject(configInfo.LoadBalancerOptions); 32                 if (!string.IsNullOrWhiteSpace(configInfo.QoSOptions)) 33                     fgc.QoSOptions = ToObject(configInfo.QoSOptions); 34                 if (!string.IsNullOrWhiteSpace(configInfo.RateLimitOptions)) 35                     fgc.RateLimitOptions = ToObject(configInfo.RateLimitOptions); 36                 if (!string.IsNullOrWhiteSpace(configInfo.ServiceDiscoveryProvider)) 37                     fgc.ServiceDiscoveryProvider = ToObject(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(); 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>(model.UpstreamHttpMethod); 63                         if (!string.IsNullOrWhiteSpace(model.DownstreamHostAndPorts)) 64                             m.DownstreamHostAndPorts = ToObject>(model.DownstreamHostAndPorts); 65                         if (!string.IsNullOrWhiteSpace(model.SecurityOptions)) 66                             m.SecurityOptions = ToObject(model.SecurityOptions); 67                         if (!string.IsNullOrWhiteSpace(model.CacheOptions)) 68                             m.FileCacheOptions = ToObject(model.CacheOptions); 69                         if (!string.IsNullOrWhiteSpace(model.HttpHandlerOptions)) 70                             m.HttpHandlerOptions = ToObject(model.HttpHandlerOptions); 71                         if (!string.IsNullOrWhiteSpace(model.AuthenticationOptions)) 72                             m.AuthenticationOptions = ToObject(model.AuthenticationOptions); 73                         if (!string.IsNullOrWhiteSpace(model.RateLimitOptions)) 74                             m.RateLimitOptions = ToObject(model.RateLimitOptions); 75                         if (!string.IsNullOrWhiteSpace(model.LoadBalancerOptions)) 76                             m.LoadBalancerOptions = ToObject(model.LoadBalancerOptions); 77                         if (!string.IsNullOrWhiteSpace(model.QoSOptions)) 78                             m.QoSOptions = ToObject(model.QoSOptions); 79                         if (!string.IsNullOrWhiteSpace(model.DelegatingHandlers)) 80                             m.DelegatingHandlers = ToObject>(model.DelegatingHandlers); 81                         reroutelist.Add(m); 82                     } 83                     fileConfig.ReRoutes = reroutelist; 84                 } 85             } 86             Console.WriteLine((DateTime.Now - st).TotalMilliseconds); 87             return new OkResponse(fileConfig); 88         } 89  90         public async Task Set(FileConfiguration fileConfiguration) 91         { 92             return await Task.FromResult(new OkResponse()); 93         } 94  95         ///  96         /// 将Json字符串转换为对象 97         ///  98         /// Json字符串 99         private T ToObject(string json)100         {101             if (string.IsNullOrWhiteSpace(json))102                 return default(T);103             return JsonConvert.DeserializeObject(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(); 4             builder.Services.AddHostedService(); 5             builder.Services.AddSingleton(sp => 6             { 7                 return new RedisFileConfigurationRepository(sp.GetRequiredService(), apiGatewayKey, redisConnectionString); 8             }); 9             return builder;10         }

其中涉及到Bucket.DbContext和Bucket.Redis组件很简单,也可自行实现

配置的管理

  其实最开始的时候,使用的是consul存储配置,然后通过网关自带的配置接口进行配置的管理,但是在ocelot的一次升级的时候出现了一个问题(配置信息丢失),虽然当时修改了ocelot的源码解决了,后来还是决定扩展存储方式,所以上面的获取配置接口的set方法都不实现了

  上面已经说了是已mysql进行配置存储然后同步到其他介质上,所以我们只要维护好mysql数据库就可以了

  具体代码就不贴了,后续会进行具体介绍,管理项目地址:github地址,截几张管理图

 

原文出处:https://www.cnblogs.com/tianxiangzhe/p/10336923.html 

作者:天翔者  

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/230943.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号