consul提供了服务的注册、发现以及健康检查等功能,webapi通过向consul服务器注册服务,consul就会对注册的服务进行管理。然后通过ocelot集成consul进行网关转发到实际的api接口。
一、首先安装consul。
下载地址https://developer.hashicorp.com/consul/downloads,下载window版本后,解压到d盘,通过cmd运行consul:
在该目录下执行cmd命令:consul agent -dev
浏览器输入:http://127.0.0.1:8500/
如此consul服务就搭建好了。
二、创建基于netcore webapi的项目并集成consul服务注册。
在Nuget包管理器安装consul包:
在appsettings.json添加配置项:
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "Ip": "Localhost", "Port": "5010", "AllowedHosts": "*" }
在Startup.cs的ConfigureServices方法里添加consul注册。
#region 注册consul string ip = Configuration["ip"] ?? "Localhost"; //configuration["ip"] 为null时取Localhost //部署到不同服务器的时候不能写成127.0.0.1或者0.0.0.0,因为这是让服务消费者调用的地址 //int port = int.Parse(configuration["Consul:ServicePort"]);//服务端口 int port = string.IsNullOrWhiteSpace(Configuration["port"]) ? 44344 : int.Parse(Configuration["port"]); ConsulClient client = new ConsulClient(obj => { obj.Address = new Uri("http://127.0.0.1:8500"); obj.Datacenter = "dcl"; }); //向consul注册服务 Task<WriteResult> result = client.Agent.ServiceRegister(new AgentServiceRegistration() { ID = "ApiServiceTest_" + Guid.NewGuid(),//服务编号,不能重复,用guid最简单 Name = "ApiServiceTest",//服务名称 Address = ip, Port = port, Tags = new string[] { },//可以用来设置权重 Check = new AgentServiceCheck() { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务停止多久后取消 Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔,或者成为心跳间隔 HTTP = $"http://{ip}:{port}/api/WeatherForecast/Check",//健康检查地址 Timeout = TimeSpan.FromSeconds(5)//检测时最长等待时间 } }); #endregion
这里我们可以基于集群以及分布式的概念多注册几个相同的服务,这些相同的服务可以是在同一台服务器上,也可以在同一台服务器的不同端口下。这里我注册了两个,一个是发布好的程序,一个是vs中调试的程序,两个端口不一样:
启动该webapi程序,可以看到consul里有一个ApiServiceTest服务:
该服务名称下有两个节点,分别是刚注册进来的两个WebApi服务。
如此就完成服务注册到consul里了。
三、ocelot集成consul实现Api网关转发。
新建一个名为APIGateway的Webapi项目,在Nuget包管理器安装ocelot和Ocelot.Provider.Consul包。
新建ocelot.json
{ "Routes": [ { //官方文档ReRoutes全节点示例 //Upstream表示上游请求,即客户端请求到API Gateway的请求 "UpstreamPathTemplate": "/ApiService/{url}", //请求路径模板 "UpstreamHttpMethod": [ "Get", "Post" ], //请求方法数组 //Downstreamb表示下游请求,即API Gateway转发的目标服务地址 "DownstreamPathTemplate": "/api/{url}", //下游请求地址模板 "DownstreamScheme": "http", //请求协议,目前应该是支持http和https "LoadBalancerOptions": { "type": "RoundRobin" // 负载均衡 RoundRobin(轮询)/LeastConnection(最少连接数) }, "UseServiceDiscovery": true, //使用服务发现,目前Ocelot只支持Consul的服务发现 "ServiceName": "ApiServiceTest" //consul服务名称-注意该名称一定要和要请求的consul服务名称一致 } ], "GlobalConfiguration": { // 网关全局配置 "BaseUrl": "http://localhost:8000", //当前项目webgateway网关的地址 "ServiceDiscoveryProvider": { // 服务发现的配置 "Scheme": "http", "Host": "localhost", //Consul 服务的访问ip "Port": 8500, //Consul 服务的访问端口 "Type": "Consul" } } }
Program
public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.AddJsonFile("ocelot.json"); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); }
Startup的ConfigureServices:
services.AddOcelot().AddConsul().AddConfigStoredInConsul();//集成consul
Startup的Configure:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "ApiGateway v1")); } app.UseOcelot(); app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
运行该APIGateway项目,请求:http://localhost:8000/ApiService/WeatherForecast/Check
轮询机制下,这两个端口会交替访问。