本文只讲步骤不讲原理,先搭建成功再自行找资料看具体配置是什么意思!
环境:win10,vs2022 , .net6 ,neget包(Ocelot和Ocelot.Provider.Consul皆为18.0.0版本,Consul1.6.10.8版本),consul_1.14.2_windows_386
配置ocelot + consul花了一天时间,主要问题在于ocelot访问的坑,consul注册的时候,Node Name为计算机名称,consul访问直接的计算机名称,而并非127.0.0.1或者localhost,导致报错,提示目标计算机积极拒绝。同时注意你的访问协议是https还是http,本文用的全是http
只需要将consul的Node Name改为127.0.0.1即可
还需要注意项目启动和注册的地址是否一致,如项目启动用的是:localhost,注册时使用的ip是:127.0.0.1,也会出现上述目标计算机积极拒绝的错误。
问题解决方案:
注意consul所在文件夹地址
第一种:在启动consul的时候,node参数可以写成 -node=127.0.0.1
如:consul agent -server -ui -bootstrap-expect=1 -data-dir=D:\Tools\consul_1.14.2_windows_386 -node=127.0.0.1 -client=0.0.0.0 -bind=127.0.0.1 -datacenter=dc1 -join 127.0.0.1
第二种:在启动consul的时候,node参数可写成"hostname",在Hosts文件中对,node参数添加dns解析.
consul agent -server -ui -bootstrap-expect=1 -data-dir=D:\Tools\consul_1.14.2_windows_386 -node=hostname -client=0.0.0.0 -bind=127.0.0.1 -datacenter=dc1 -join 127.0.0.1
win7 hosts文件位置:C:\Windows\System32\drivers\etc
在hosts文件中添加一行"127.0.0.1 hostname",即可
https://www.cnblogs.com/huyougurenxinshangguo/p/15246313.html
https://blog.csdn.net/salty_oy/article/details/119636278
下面说一下实现
S1,S2引用了consul包,APIGateway引用了Ocelot包,Ocelot.Provider.Consul包
创建3个webapi,其中S1,S2为相同代码,只修改了配置文件appsettings.json,一个端口为7000,一个端口为7001
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"Consul": {
"IP": "127.0.0.1",
"Port": "8500"
},
"Service": {
"Name": "consul_test"
},
"ip": "127.0.0.1",
"port": "7000",
"AllowedHosts": "*"
}
launchSettings.json也把端口改一下,一个7000,一个7001,同时注意一下sslport这个key
{ "$schema": "https://json.schemastore.org/launchsettings.json", "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { "applicationUrl": "http://127.0.0.1:7000", "sslPort": 0 } }, "profiles": { "S2": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, "launchUrl": "swagger", "applicationUrl": "http://127.0.0.1:7000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, "launchUrl": "swagger", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } } } }
webapi页面WeatherForecastController
using Microsoft.AspNetCore.Mvc; namespace S1.Controllers { [ApiController] [Route("api/[controller]/[action]")] public class WeatherForecastController : ControllerBase { private static readonly string[] Summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; private readonly IConfiguration _IConfiguration; private readonly ILogger<WeatherForecastController> _logger; public WeatherForecastController(ILogger<WeatherForecastController> logger, IConfiguration iConfiguration) { _logger = logger; _IConfiguration = iConfiguration; } [HttpGet] public string GetTest() { string ip = _IConfiguration["IP"]; string port = _IConfiguration["Port"]; return $@"{ip} {port}"; } //[HttpGet(Name = "GetWeatherForecast")] //public IEnumerable<WeatherForecast> Get() //{ // return Enumerable.Range(1, 5).Select(index => new WeatherForecast // { // Date = DateTime.Now.AddDays(index), // TemperatureC = Random.Shared.Next(-20, 55), // Summary = Summaries[Random.Shared.Next(Summaries.Length)] // }) // .ToArray(); //} } }
然后在S1,S2两个api中注入consulhelper类
using Consul; namespace S2 { public static class ConsulHelper { /// <summary> /// 将当前站点注入到Consul /// </summary> /// <param name="configuration"></param> public static void ConsulRegister(this IConfiguration configuration) { //初始化Consul服务 ConsulClient client = new ConsulClient(c => { c.Address = new Uri("http://127.0.0.1:8500"); c.Datacenter = "dc1"; }); //站点做集群时ip和端口都会不一样,所以我们通过环境变量来确定当前站点的ip与端口 string ip = configuration["ip"]; int port = int.Parse(configuration["port"]); client.Agent.ServiceRegister(new AgentServiceRegistration { ID = "service" + Guid.NewGuid(), //注册进Consul后给个唯一id, Name = "consul_test", //站点做集群时,Name作为该集群的群名, //Address = ip, Address = "127.0.0.1", Port = port, Tags = null, //这个就是一个随意的参数,文章后面做负载均衡的时候说 Check = new AgentServiceCheck { Interval = TimeSpan.FromSeconds(10), //HTTP = $"http://{ip}:{port}/api/health", HTTP = $"http://{ip}:{port}/api/WeatherForecast/GetTest", Timeout = TimeSpan.FromSeconds(5), DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5) } }); } } }
Program类中注入
using S2; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); app.Configuration.ConsulRegister(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseAuthorization(); app.MapControllers(); app.Run();
S1,S2代码完全一样,区别只修改了launchSettings.json,appsettings.json配置文件的端口号
再说一下ocelot吧,
Program类注入Ocelot
using Ocelot.DependencyInjection; using Ocelot.Middleware; using Ocelot.Provider.Consul; using Ocelot.Values; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddOcelot(new ConfigurationBuilder() .AddJsonFile("Ocelot.json") .Build()).AddConsul(); builder.Host.ConfigureLogging(c => { c.ClearProviders(); c.AddConsole(); }); //builder.Host.ConfigureAppConfiguration((context, config) => //{ // config.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true); //}).ConfigureWebHostDefaults(c => c.UseUrls("http://localhost:5000")); //builder.Services.AddSwaggerGen(); var app = builder.Build(); app.UseOcelot(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { //app.UseSwagger(); //app.UseSwaggerUI(); } app.UseAuthorization(); app.MapControllers(); app.Run();
Ocelot.json
{ "Routes": [ { "DownstreamPathTemplate": "/api/{url}", //下游服务地址--url变量 "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "127.0.0.1", "Port": 7000 } , { "Host": "127.0.0.1", "Port": 7001 } ], "UpstreamPathTemplate": "/{url}", //上游请求路径,网关地址--url变量 "UpstreamHttpMethod": [ "Get", "Post" ], //consul "UseServiceDiscovery": true, //使用服务发现 "ServiceName": "consul_test", //consul服务名称
"LoadBalancerOptions": { "Type": "RoundRobin" //轮询 LeastConnection-最少连接数的服务器 NoLoadBalance不负载均衡 }, "GlobalConfiguration": { "RequestIdKey": "OcRequestId", "BaseUrl": "http://127.0.0.1:5000", //网关对外地址 //配置consul地址 "ServiceDiscoveryProvider": { "Host": "127.0.0.1", "Port": 8500, "Type": "Consul" //由consul提供服务发现,ocelot也支持etc等 } } } ] }
launchSettings.json
{ "$schema": "https://json.schemastore.org/launchsettings.json", "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { "applicationUrl": "http://127.0.0.1:5001", "sslPort": 0 } }, "profiles": { "ApiGateway": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, "applicationUrl": "http://127.0.0.1:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, "launchUrl": "swagger", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } } } }
完成之后,先启动S1,S2,看看consul注入成功没有,
然后启动ApiGateway,使用其对外地址进行访问,http://127.0.0.1:5000,注意看地址,这里和Ocelot.json里面的配置有关
"DownstreamPathTemplate": "/api/{url}", //下游服务地址--url变量
"UpstreamPathTemplate": "/{url}", //上游请求路径,网关地址--url变量
没配置成功请仔细看加粗加红部分
源码:https://gitee.com/yuanrang123/ocelot-consul