一、简介前一篇Consul中有个问题是,所有客户端都要和Consul进行连接,且直接拿到了所有的服务实例,这就直接把全部的服务实例暴露出来了,所以需要用网关来隔离客户端和服务实例,
所有api请求都从网关进入。
Ocelot作为一个网关应用,主要的功能有路由、请求聚合、服务发现、统一认证、统一鉴权、限流熔断、并内置了负载均衡器等的集成。而且这些功能都只需要简单的配置即可完成。
二、使用Ocelot
2.1应用配置
新建一个.NetCore项目作网关应用。
安装NuGet包
Ocelot
Startup.cs中把ConfigureServices(),Configure()里面的代码都去掉,加上Ocelot接管代码。
public void ConfigureServices(IServiceCollection services)
{
services.AddOcelot();
}
// 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();
}
这些操作完,程序就再也不是asp.net core,也不是什么webApi的程序了,就是一个Ocelot网关应用。
2.2路由配置
网关最重要的功能就是路由,根据路由把功能转发到其它应用去,它本身的应用有ip地址,别人可能访问它,但它怎么知道哪个请求转到哪个应用去呢,这些全靠配置。
首先在 Program.cs里的CreateHostBuilder()加入配置文件信息
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(c =>
{
c.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
根目录下增加配置文件ocelot.json。
{
"Routes": [
{
//转发到下游服务地址--url变量
"DownstreamPathTemplate": "/api/{url}",
//下游http协议
"DownstreamScheme": "http",
//负载方式,
"LoadBalancerOptions": {
"Type": "RoundRobin" // 轮询
},
"DownstreamHostAndPorts": [
{
"Host": "172.16.2.9",
"Port": 5201 //服务端口
}, //可以多个,自行负载均衡
{
"Host": "172.16.2.9",
"Port": 5202 //服务端口
},
{
"Host": "172.16.2.9",
"Port": 5203 //服务端口
}
],
//上游地址
"UpstreamPathTemplate": "/T1/{url}", //网关地址--url变量 //冲突的还可以加权重Priority
"UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ]
}
]
}
这里的是路由配置,注释说明已经很清楚,假如网关程序启动后的地址为http://172.16.2.9:5200
当访问:http://172.16.2.9:5200/T1/Test/GetName 网关会把请求转发到http://172.16.2.9:5201/api/Test/GetName,http://172.16.2.9:5202/api/Test/GetName,http://172.16.2.9:5203/api/Test/GetName,根据负载算法决定转发规则。
LoadBalancer是来决定负载的算法
- LeastConnection:将请求发往最空闲的那个服务器
- RoundRobin:轮流转发
- NoLoadBalance:总是发往第一个请求或者是服务发现
Routes里面可以配多个路由转发。
2.3验证
在前面的Consul注册的程序中(5201,5202,5203端口程序)加入一个接口
[Route("api/[controller]/[action]")]
public class TestController : Controller
{
private IConfiguration _configuration;
public TestController(IConfiguration configuration)
{
_configuration = configuration;
}
public IActionResult GetName()
{
string port = _configuration["port"];
return Json($"端口:{port},姓名:张三");
}
}
启动Ocelot的网关程序,端口为5200
访问地址:http://ip:5200/T1/Test/GetName
刷新一下
可以看到,已经成功转发到上面配置好的路由地址。
2.4Ocelot结合Consul进行服务发现
上面的示例是没有经过Consul的,是直接转发到相应地址,这显然又面临了服务地址管理的问题了,所以需要结合Consul自动发现服务的地址。
把ocelot.json的文件加入consul配置信息
{
"Routes": [
{
//转发到下游服务地址--url变量
"DownstreamPathTemplate": "/api/{url}",
//下游http协议
"DownstreamScheme": "http",
//负载方式,
"LoadBalancerOptions": {
"Type": "RoundRobin" // 轮询
},
//"DownstreamHostAndPorts": [
// {
// "Host": "172.16.2.9",
// "Port": 5201 //服务端口
// }, //可以多个,自行负载均衡
// {
// "Host": "172.16.2.9",
// "Port": 5202 //服务端口
// },
// {
// "Host": "172.16.2.9",
// "Port": 5203 //服务端口
// }
//],
//上游地址
"UpstreamPathTemplate": "/T1/{url}", //网关地址--url变量 //冲突的还可以加权重Priority
"UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ],
"UseServiceDisConvery": true, //使用服务发现
"ServiceName": "api"//Consul服务名称
}
],
"GlobalConfiguration": {
//Ocelot应用地址
"BaseUrl": "http://172.16.2.9:5200",
"ServiceDiscoveryProvider": {
//Consul地址
"Host": "172.16.2.84",
//Consul端口
"Port": 8500,
"Type": "Consul"//由Consul提供服务发现,每次请求Consul
}
}
}
可以看到,这里已经把写死的下游地址去掉了,加入了Consul的信息。
安装NuGet包
Ocelot.Provider.Consul
Startup.cs中ConfigureServices(IServiceCollection services)加入.AddConsul();
public void ConfigureServices(IServiceCollection services)
{
services.AddOcelot()
.AddConsul();
}
配置完成,验证效果,启动项目。
再次访问http://ip:5200/T1/Test/GetName
刷新一下
控制台信息
到这就已经成功完成 Ocelot+Consul的网关和服务发现功能了。
源码地址:https://github.com/weixiaolong325/Ocelot-Consul-Polly-Id4.Demo