环境:
window10 x64vs2019 企业版 16.7.4asp.net core 3.1consul_1.8.4_windows_amd64.zipConsul 1.6.1.1Ocelot.Provider.Consul 16.0.1关于Consul和Ocelot: Consul参照:c#:Consul初步体验 Ocelot参照:c#:Ocelot初体验
实验代码下载:https://download.csdn.net/download/u010476739/13008990
Consul是用来做服务注册和发现的,我们写的WebApi项目运行起来后需要向Consul注册服务名称和访问地址。
Ocelot是用来做网关的,所有客户端的请求都应该发送到Ocelot,然后由Ocelot内部转发(非http重定向)到具体的WebApi项目。
Ocelot集成Consul后,我们开发的项目就只管向Consul注册服务,而浏览器只管向Ocelot发送请求,Ocelot会自动向Consul查询请求的服务地址,然后将请求内部转发到具体的WebApi服务上。
下面是本地实现的架构图:
启动后,浏览器观察:http://localhost:8500/
我们先新建空白解决方案ocelot-consul-trial,然后新建两个WebApi项目:ocelot-consul-trial和OrderApi。
ocelot-consul-trial是ocelot网关项目,负责接收客户端请求。 OrderApi是正常的WebApi项目,启动时向Consul注册。这个项目编译后,使用命令行参数指定端口启动两个实例。
新建后如下: 操作OrderApi项目:
引入Consul包:
<ItemGroup> <PackageReference Include="Consul" Version="1.6.1.1" /> </ItemGroup>修改Startup.cs代码,加入向Consul注册的代码:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); #region 向Consul注册服务 //获取命令行指定的参数( --urls="http://localhost:5001/") var urls = Configuration["urls"]; var client = new ConsulClient(_ => _.Address = new Uri("http://localhost:8500")); var httpCheck = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册 Interval = TimeSpan.FromSeconds(10),//间隔固定的时间访问一次 HTTP = $"{urls}/api/Health",// Timeout = TimeSpan.FromSeconds(5) }; var port = int.Parse(urls.Split(":")[2].Trim('/')); AgentServiceRegistration registration = new AgentServiceRegistration() { Checks = new[] { httpCheck }, ID = Guid.NewGuid().ToString(), Name = "OrderApi", Address = "localhost",//注意:这里不要写成 http://localhost形式 Port = port }; client.Agent.ServiceRegister(registration).Wait(); #endregion }添加健康检查控制器HealthController.cs:
using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace OrderApi.Controllers { [ApiController] [Route("api/[controller]")] public class HealthController : ControllerBase { [HttpGet] public string Get() => "ok"; } }添加测试api接口DemoController.cs:
using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace OrderApi.Controllers { [ApiController] [Route("api/[controller]/[action]")] public class DemoController : ControllerBase { private readonly IConfiguration configuration; public DemoController(IConfiguration configuration) { this.configuration = configuration; } public string GetHello() => "来自: " + configuration["urls"] + "的应答"; } }编译OrderApi项目,并用如下命令启动两个实例:
.\OrderApi.exe --urls="http://localhost:5001" .\OrderApi.exe --urls="http://localhost:5002"此时观察Consul管理页面:
操作 ocelot-consul-trial项目:
引入Ocelot.Provider.Consul包:
<ItemGroup> <PackageReference Include="Ocelot.Provider.Consul" Version="16.0.1" /> </ItemGroup>添加ocelot.json的配置文件:
{ "Routes": [ { //GeteWay转发=>Downstream "DownstreamPathTemplate": "/{url}", //服务地址--url变量 "DownstreamScheme": "http", "UpstreamPathTemplate": "/order/{url}", //网关地址--url变量 冲突的还可以加权重Priority "UpstreamHttpMethod": [ "Get", "Post" ], "UseServiceDiscovery": true, //使用服务发现 "ServiceName": "OrderApi", //Consul服务名称 "LoadBalancerOptions": { "Type": "RoundRobin" //轮询 //"LeastConnection":最少连接数服务器 "NoloadBalance":不负载均衡 "CookieStickySession":会话粘滞 } } ], "GlobalConfiguration": { "ServiceDiscoveryProvider": { "Host": "127.0.0.1", "Port": 8500, "Type": "Consul" //由Consul提供服务发现,每次请求去Consul } } }修改Program.cs文件载入ocelot.json配置文件:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace ocelot_consul_trial { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration(conf => { conf.AddJsonFile("ocelot.json", true, true); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); } }修改Startup.cs文件,启用 Ocelot并去掉其他的功能:
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Ocelot.DependencyInjection; using Ocelot.Middleware; using Ocelot.Provider.Consul; namespace ocelot_consul_trial { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddOcelot().AddConsul(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseHttpsRedirection(); app.UseOcelot().Wait(); } } }编译ocelot-consul-trial项目并用如下命令启动:
.\ocelot-consul-trial.exe --urls="https://localhost:5000/"在浏览器中输入:https://localhost:5000/order/api/demo/gethello,效果如下: 刷新网页,显示如下: