微服务架构- 网关(Ocelot)
微服务架构- 网关(Ocelot)
一、Gateway
1. 为什么需要网关?
有了Consul,使用服务名即可访问。但手机、web端等外部访问者仍然需要和N多服务器交互,需要记忆他们的服务器地址、端口号等。一旦内部发生修改,很麻烦,而且有时候内部服务 器是不希望外界直接访问的—需要路由功能!Ocelot就是一个提供了请求路由、安全验证等功能的API网关微服务,简单点就是对consul进行了一次封装。
2. 好处:
- 各个业务系统轻松独立维护服务器;
- 复用权限校验;
- 限流、熔断、降级、收费等。
二、差异
1. 之前版本的只使用consul时获取服务地址:
public IActionResult Info() { List<Users> userList = new List<Users>(); string resultUrl = null; #region 直接调用 { //string url = "http://localhost:5726/api/users/get"; //string result = WebApiHelperExtend.InvokeApi(url); //userList = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Users>>(result); //resultUrl = url; } #endregion #region 这么多地址你怎么管理?1 2 3 要累死--可以自行选择 #endregion #region 通过consul去发现这些服务地址 { //using (ConsulClient client = new ConsulClient(c => //{ // c.Address = new Uri("http://localhost:8500/"); // c.Datacenter = "dc1"; //})) //{ // var dictionary = client.Agent.Services().Result.Response; // string message = ""; // foreach (var keyValuePair in dictionary) // { // AgentService agentService = keyValuePair.Value; // this._logger.LogWarning($"{agentService.Address}:{agentService.Port} {agentService.ID} {agentService.Service}");//找的是全部服务 全部实例 其实可以通过ServiceName筛选 // message += $"{agentService.Address}:{agentService.Port};"; // } // //获取当前consul的全部服务 // base.ViewBag.Message = message; //} } #endregion #region 调用---负载均衡 { //string url = "http://localhost:5726/api/users/get"; //string url = "http://localhost:5727/api/users/get"; //string url = "http://localhost:5728/api/users/get"; string url = "http://UserService/api/users/get"; //consul解决使用服务名字 转换IP:Port----DNS Uri uri = new Uri(url); string groupName = uri.Host; using (ConsulClient client = new ConsulClient(c => { c.Address = new Uri("http://localhost:8500/"); c.Datacenter = "dc1"; })) { var dictionary = client.Agent.Services().Result.Response; var list = dictionary.Where(k => k.Value.Service.Equals(groupName, StringComparison.OrdinalIgnoreCase));//获取consul上全部对应服务实例 KeyValuePair<string, AgentService> keyValuePair = new KeyValuePair<string, AgentService>(); //拿到3个地址,只需要从中选择---可以在这里做负载均衡-- //{ // keyValuePair = list.First();//直接拿的第一个 //} //{ // var array = list.ToArray(); // //随机策略---平均策略 // keyValuePair = array[new Random(iSeed++).Next(0, array.Length)]; //} //{ // var array = list.ToArray(); // //轮询策略---平均策略 // keyValuePair = array[iSeed++ % array.Length]; //} { //权重---注册服务时指定权重,分配时获取权重并以此为依据 List<KeyValuePair<string, AgentService>> pairsList = new List<KeyValuePair<string, AgentService>>(); foreach (var pair in list) { int count = int.Parse(pair.Value.Tags?[0]); for (int i = 0; i < count; i++) { pairsList.Add(pair); } } keyValuePair = pairsList.ToArray()[new Random(iSeed++).Next(0, pairsList.Count())]; } resultUrl = $"{uri.Scheme}://{keyValuePair.Value.Address}:{keyValuePair.Value.Port}{uri.PathAndQuery}"; string result = WebApiHelperExtend.InvokeApi(resultUrl); userList = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Users>>(result); } } #endregion base.ViewBag.Users = userList; base.ViewBag.Url = resultUrl; return View(); }
2. 使用网关之后的调用:
2.1 安装如下几个包
2.2 修改startup文件如下:
public void ConfigureServices(IServiceCollection services) { services.AddOcelot().AddConsul().AddPolly(); //添加 //services.AddControllers(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseOcelot(); //添加 //if (env.IsDevelopment()) //{ // app.UseDeveloperExceptionPage(); //} //app.UseHttpsRedirection(); //app.UseRouting(); //app.UseAuthorization(); //app.UseEndpoints(endpoints => //{ // endpoints.MapControllers(); //}); }
2.3 修改配置文件
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration(c => //修改添加如下配置文件 { c.AddJsonFile("configuration.json", optional: false, reloadOnChange: true); }) //添加代码结束 .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
2.4 添加一个configuration.json 文件
////*****************************单地址******************************** { "ReRoutes": [ { "DownstreamPathTemplate": "/api/{url}", //服务地址--url变量 "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 5000 //服务端口 } //可以多个,自行负载均衡 ], "UpstreamPathTemplate": "/T5726/{url}", //网关地址--url变量 //冲突的还可以加权重Priority "UpstreamHttpMethod": [ "Get", "Post" ] } ] } //*****************************多地址多实例******************************** //{ // "ReRoutes": [ // { // "DownstreamPathTemplate": "/api/{url}", //服务地址--url变量 // "DownstreamScheme": "http", // "DownstreamHostAndPorts": [ // { // "Host": "localhost", // "Port": 5726 //服务端口 // } //可以多个,自行负载均衡 // ], // "UpstreamPathTemplate": "/T5726/{url}", //网关地址--url变量 //冲突的还可以加权重Priority // "UpstreamHttpMethod": [ "Get", "Post" ] // }, // { // "DownstreamPathTemplate": "/api/{url}", //服务地址--url变量 // "DownstreamScheme": "http", // "DownstreamHostAndPorts": [ // { // "Host": "localhost", // "Port": 5727 //服务端口 // } // ], // "UpstreamPathTemplate": "/T5727/{url}", //网关地址--url变量 // "UpstreamHttpMethod": [ "Get", "Post" ] // }, // { // "DownstreamPathTemplate": "/api/{url}", //服务地址--url变量 // "DownstreamScheme": "http", // "DownstreamHostAndPorts": [ // { // "Host": "localhost", // "Port": 5728 //服务端口 // } // ], // "UpstreamPathTemplate": "/T5728/{url}", //网关地址--url变量 // "UpstreamHttpMethod": [ "Get", "Post" ] // } // ] //} ////*****************************单地址多实例负载均衡******************************** //{ // "ReRoutes": [ // { // "DownstreamPathTemplate": "/api/{url}", //服务地址--url变量 // "DownstreamScheme": "http", // "DownstreamHostAndPorts": [ // { // "Host": "localhost", // "Port": 5726 //服务端口 // } //可以多个,自行负载均衡 // , // { // "Host": "localhost", // "Port": 5727 //服务端口 // }, // { // "Host": "localhost", // "Port": 5728 //服务端口 // } // ], // "UpstreamPathTemplate": "/T5/{url}", //网关地址--url变量 //冲突的还可以加权重Priority // "UpstreamHttpMethod": [ "Get", "Post" ], // "LoadBalancerOptions": { // "Type": "RoundRobin" //轮询 LeastConnection-最少连接数的服务器 NoLoadBalance不负载均衡 // } // } // ] //} ////*****************************单地址多实例负载均衡+Consul******************************** //{ // "ReRoutes": [ // { // "DownstreamPathTemplate": "/api/{url}", //服务地址--url变量 // "DownstreamScheme": "http", // "UpstreamPathTemplate": "/TConsul/{url}", //网关地址--url变量 // "UpstreamHttpMethod": [ "Get", "Post" ], // "ServiceName": "ZhaoxiUserService", //consul服务名称 // "LoadBalancerOptions": { // "Type": "RoundRobin" //轮询 LeastConnection-最少连接数的服务器 NoLoadBalance不负载均衡 // }, // "UseServiceDiscovery": true // } // ], // "GlobalConfiguration": { // "BaseUrl": "http://127.0.0.1:6299", //网关对外地址 // "ServiceDiscoveryProvider": { // "Host": "localhost", // "Port": 8500, // "Type": "Consul" //由Consul提供服务发现 // } // } //} //*****************************单地址多实例负载均衡+Consul+Polly******************************** //{ // "ReRoutes": [ // { // "DownstreamPathTemplate": "/api/{url}", //服务地址--url变量 // "DownstreamScheme": "http", // "UpstreamPathTemplate": "/consul/{url}", //网关地址--url变量 // "UpstreamHttpMethod": [ "Get", "Post" ], // "ServiceName": "ZhaoxiUserService", //consul服务名称 // "LoadBalancerOptions": { // "Type": "RoundRobin" //轮询 LeastConnection-最少连接数的服务器 NoLoadBalance不负载均衡 // }, // "UseServiceDiscovery": true, // "QoSOptions": { // "ExceptionsAllowedBeforeBreaking": 3, //允许多少个异常请求 // "DurationOfBreak": 10000, // 熔断的时间,单位为ms // "TimeoutValue": 10000 //如果下游请求的处理时间超过多少则自如将请求设置为超时 默认90秒 // } // //"RateLimitOptions": { // // "ClientWhitelist": [], //白名单 // // "EnableRateLimiting": true, // // "Period": "5m", //1s, 5m, 1h, 1d jeffzhang // // "PeriodTimespan": 5, //多少秒之后客户端可以重试 // // "Limit": 5 //统计时间段内允许的最大请求数量 // //}, // //"FileCacheOptions": { // // "TtlSeconds": 10 // //} //"缓存" // } // ], // "GlobalConfiguration": { // "BaseUrl": "http://127.0.0.1:6299", //网关对外地址 // "ServiceDiscoveryProvider": { // "Host": "localhost", // "Port": 8500, // "Type": "Consul" //由Consul提供服务发现 // }, // //"RateLimitOptions": { // // "QuotaExceededMessage": "Too many requests, maybe later? 11", // 当请求过载被截断时返回的消息 // // "HttpStatusCode": 666 // 当请求过载被截断时返回的http status // //} // } //}
2.5 请求地址示例:
http://127.0.0.1:6299/T5726/WeatherForecast
以上就是网关相关的总结!!!谢谢学习,共同进步