Ocelot 路由 请求聚合 服务发现 认证 鉴权 限流熔断 内置负载均衡器
Consul 自动服务发现 健康检查
通过Ocelot搭建API网关 服务注册 负载均衡
1.创建三个空API项目 Api.Gateway(Ocelot网关服务器) Api.ServiceA(资源服务器A) Api.ServiceB(资源服务器B)
2.Api.Gateway项目中 添加Ocelot包 添加Ocelot.Json配置文件 Ocelot服务器端口配成5000
{ "ReRoutes": [ { //暴露出去的地址 "UpstreamPathTemplate": "/api/{controller}", "UpstreamHttpMethod": [ "Get" ], //转发到下面这个地址 "DownstreamPathTemplate": "/api/{controller}", "DownstreamScheme": "http", //资源服务器列表 "DownstreamHostAndPorts": [ { "host": "localhost", "port": 5011 }, { "host": "localhost", "port": 5012 } ], //决定负载均衡的算法 "LoadBalancerOptions": { "Type": "LeastConnection" } } ], //对外暴露的访问地址 也就是Ocelot所在的服务器地址 "GlobalConfiguration": { "BaseUrl": "http://localhost:5000" } }
LeastConnection – 将请求发往最空闲的那个服务器
RoundRobin – 轮流发送
NoLoadBalance – 总是发往第一个请求或者是服务发现
3.项目启动读取Ocelot配置
public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, builder) => { builder .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) .AddJsonFile("Ocelot.json"); }) .UseStartup(); }
把Ocelot注册到DI容器
services.AddOcelot();
管道中开启Ocelot
app.UseOcelot().Wait();
4.配置资源服务器 在Ocelot中配置好了 把对应的/api/{controller}地址会进行转发
[Route("apiservice/[controller]")] [ApiController] public class ValuesController : ControllerBase { // GET api/values [HttpGet] public string Get() { return "这是A资源服务器API"; }
5.通过localhost:5000/api/value访问 实现了负载均衡 测试的时候修改了端口或者其他的 最要先把iis对应端口进程关闭 不然可能没有更新过来
这种做法 如果其中一台服务器挂了 Ocelot没办法知道 还是会转发接口过去 如果新增服务器 就需要修改配置文件 可以通过Ocelot+Consul实现自动服务发现和服务健康监测
*********************************************************************
Ocelot+Consul实现服务发现和健康监测
下载了consul后 就是一个exe文件 通过cmd进入目录 consul agent --dev运行 consul默认ui地址 http://localhost:8500
API项目配置consul 项目启动后 自动被consul发现
1.添加consul Nuget包 启动consul服务
2.在管道中配置
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime lifetime) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } //注册项目启动的方法 lifetime.ApplicationStarted.Register(OnStart); //注册项目关闭的方法 lifetime.ApplicationStarted.Register(OnStopped); app.UseMvc(); } private void OnStart() { var client = new ConsulClient(); //健康检查 var httpCheck = new AgentServiceCheck() { //服务出错一分钟后 会自动移除 DeregisterCriticalServiceAfter = TimeSpan.FromMinutes(1), //每10秒发送一次请求到 下面的这个地址 这个地址就是当前API资源的地址 Interval = TimeSpan.FromSeconds(10), HTTP = $"http://localhost:5011/HealthCheck" }; var agentReg = new AgentServiceRegistration() { //这台资源服务的唯一ID ID = "JcbServiceA", Check = httpCheck, Address = "localhost", Name = "servicename", Port = 5011 }; client.Agent.ServiceRegister(agentReg).ConfigureAwait(false); } //关闭的时候在consul中移除 private void OnStopped() { var client = new ConsulClient(); //根据ID在consul中移除当前服务 client.Agent.ServiceDeregister("JcbServiceA"); }
3.启动项目后 进入consul发现 当前项目已经被consul发现 这样就实现了服务的自动发现
4.然后在把Consul结合到Ocelot中 在Ocelot中安装Ocelot.Provider.Consul 包
在管道中把Consul注册到DI容器
services.AddOcelot().AddConsul();
修改Ocelot.Json配置文件
{ "ReRoutes": [ { //暴露出去的地址 "UpstreamPathTemplate": "/api/{controller}", "UpstreamHttpMethod": [ "Get" ], //转发到下面这个地址 "DownstreamPathTemplate": "/api/{controller}", "DownstreamScheme": "http", //资源服务器列表 //"DownstreamHostAndPorts": [ // { // "host": "localhost", // "port": 5011 // }, // { // "host": "localhost", // "port": 5012 // } //], //决定负载均衡的算法 "LoadBalancerOptions": { "Type": "LeastConnection" }, "ServiceName": "servicename", //服务注册标识, 这个需要和资源API注册的名称相同 "UseServiceDiscovery": true //启用服务发现 //"ReRoutesCaseSensitive": false } ], //对外暴露的访问地址 也就是Ocelot所在的服务器地址 "GlobalConfiguration": { "BaseUrl": "http://localhost:5000", "ServiceDiscoveryProvider": { "Host": "localhost", // Consul Service IP "Port": 8500, // Consul Service Port //"Type": "PollConsul", //"PollingInterval": 100 //健康检查时间端 } } }
5.这样就实现了动态的服务注册
如果其中一台服务挂了 一分钟后还是连接不上 consul会自动移除这台服务 并且不会再将请求转发到这台服务上 这时候就可以动态的实现服务的新增
注意:在这里通过Consul发现服务的时候
当资源API只有一台 启用和关闭当前资源API Consul都能正常检查到
当资源API有两台的时候 关闭其中一台资源API是正常的 然后在关闭另外一台 Consul的控制台已经检测到这台API连接失败了 但是Localhost:8500界面上显示还是正常的(并且这台关闭的API会一直显示正常) 不清楚为什么
************************
Ocelot +IdentityServer4 在网关实现统一身份验证
1.在Ocelot项目中添加 IdentityServer4.AccessTokenValidation 包
DI容器添加身份验证 这里的authenticationProviderKey 要和Ocelot.Json中的authenticationProviderKey 相同
public void ConfigureServices(IServiceCollection services) { var authenticationProviderKey = "finbook"; services.AddAuthentication() .AddIdentityServerAuthentication(authenticationProviderKey, options => { options.Authority = "http://localhost:3000"; options.ApiName = "gateway_api"; options.SupportedTokens = SupportedTokens.Both; options.ApiSecret = "secret"; options.RequireHttpsMetadata = false; }); services.AddOcelot().AddConsul(); //services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }
2.修改Ocelot.Json配置文件
"AuthenticationOptions": { //这个名称要和Startup中配置的权限key相同 "AuthenticationProviderKey": "finbook", //允许访问的资源API 在IdentityServer中配置 "AllowedScopes": [ "gateway_api" ] }
https://www.cnblogs.com/weiBlog/p/9833807.html