网关介绍
网关其实就是将我们写好的API全部放在一个统一的地址暴露在公网,提供访问的一个入口。在 .NET Core下可以使用Ocelot
来帮助我们很方便的接入API 网关。与之类似的库还有ProxyKit
,微软也发布了一个反向代理的库YARP
。
关于网关的介绍不多说了,网上文章也挺多的,这些都是不错的选择,听说后期Ocelot
将会使用YARP
来重写。本篇主要实践一下在.NET Core环境下使用Ocelot
。
- Ocelot官网:https://threemammals.com/ocelot
- Ocelot文档:https://ocelot.readthedocs.io
- GitHub:https://github.com/ThreeMammals/Ocelot
- Ocelot资源汇总:https://www.cnblogs.com/shanyou/p/10363360.html
接入使用
接口示例
先创建几个项目用于测试,创建两个默认的API项目,Api_A和Api_B,在创建一个网关项目Api_Gateway
,网关项目可以选择空的模板。
现在分别在Api_A
和Api_B
中写几个api
,将默认的WeatherForecastController
中返回模型WeatherForecast
添加一个字段Source
,用于区分是哪个API返回的数据。
using System;
namespace Api_A
{
public class WeatherForecast
{
public string Source { get; set; } = "Api_A";
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string Summary { get; set; }
}
}
using System;
namespace Api_B
{
public class WeatherForecast
{
public string Source { get; set; } = "Api_B";
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string Summary { get; set; }
}
}
直接使用WeatherForecastController
默认方法,在路由中添加api前缀。
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Api_A.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
}).ToArray();
}
}
}
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Api_B.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
}).ToArray();
}
}
}
再分别在Api_A
和Api_B
中添加两个控制器:ApiAController
、ApiBController
,然后加上几个简单的restful api
。
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
namespace Api_A.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ApiAController : ControllerBase
{
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
[HttpGet("{id}")]
public string Get(int id)
{
return $"Get:{id}";
}
[HttpPost]
public string Post([FromForm] string value)
{
return $"Post:{value}";
}
[HttpPut("{id}")]
public string Put(int id, [FromForm] string value)
{
return $"Put:{id}:{value}";
}
[HttpDelete("{id}")]
public string Delete(int id)
{
return $"Delete:{id}";
}
}
}
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
namespace Api_B.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ApiBController : ControllerBase
{
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
[HttpGet("{id}")]
public string Get(int id)
{
return $"Get:{id}";
}
[HttpPost]
public string Post([FromForm] string value)
{
return $"Post:{value}";
}
[HttpPut("{id}")]
public string Put(int id, [FromForm] string value)
{
return $"Put:{id}:{value}";
}
[HttpDelete("{id}")]
public string Delete(int id)
{
return $"Delete:{id}";
}
}
}
方便查看接口,这里添加一下swagger
组件,这样我们Api_A和Api_B项目分别就有了6个接口。
接着打包docker镜像,放在docker中运行这两个api项目。这一步可以用任何你熟悉的方式,run起来即可。
docker build -t api_a:dev -f ./Api_A/Dockerfile .
docker build -t api_b:dev -f ./Api_B/Dockerfile .
build
成功后,指定两个端口运行api项目。
docker run -d -p 5050:80 --name api_a api_a:dev
docker run -d -p 5051:80 --name api_b api_b:dev
Api_A指定了5050端口,通过 http://localhost:5050/swagger打开可以看到swagger文档界面,Api_B指定了5051端口,通过 http://localhost:5051/swagger打开可以看到swagger文档界面,这样就大功告成了,接下来才是重点将两个api项目配置到Api_Gateway
网关项目中。
配置网关
在网关项目Api_Gateway
中都添加Ocelot
组件包。
Install-Package Ocelot
Ocelot
中最关键的就是配置路由信息,新建一个ocelot.json
配置文件,将我们的两个API接口匹配规则放进去。
{
"Routes": [
//ApiA
{
"DownstreamPathTemplate": "/api/WeatherForecast",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5050
}
],
"UpstreamPathTemplate": "/ApiA/WeatherForecast",
"UpstreamHttpMethod": [ "Get" ]
},
{
"DownstreamPathTemplate": "/api/ApiA",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5050
}
],
"UpstreamPathTemplate": "/ApiA",
"UpstreamHttpMethod": [ "Get", "POST" ]
},
{
"DownstreamPathTemplate": "/api/ApiA/{id}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5050
}
],
"UpstreamPathTemplate": "/ApiA/{id}",
"UpstreamHttpMethod": [ "Get", "Put", "Delete" ]
},
//ApiB
{
"DownstreamPathTemplate": "/api/WeatherForecast",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5051
}
],
"UpstreamPathTemplate": "/ApiB/WeatherForecast",
"UpstreamHttpMethod": [ "Get" ]
},
{
"DownstreamPathTemplate": "/api/ApiB",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5051
}
],
"UpstreamPathTemplate": "/ApiB",
"UpstreamHttpMethod": [ "Get", "POST" ]
},
{
"DownstreamPathTemplate": "/api/ApiB/{id}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5051
}
],
"UpstreamPathTemplate": "/ApiB/{id}",
"UpstreamHttpMethod": [ "Get", "Put", "Delete" ]
}
],
"GlobalConfiguration": {
"BaseUrl": "https://localhost:44335"
}
}
关于配置文件中的各项具体含义,可以参考官方文档中的介绍。主要就是将DownstreamPathTemplate
模板内容转换为UpstreamPathTemplate模板内容进行接口的访问,同时可以指定HTTP请求的方式等等。GlobalConfiguration
中的BaseUrl
为我们暴漏出去的网关地址。
设置好ocelot.json
后,需要在代码中使用它,在Program.cs
中添加配置文件。
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
namespace Api_Gateway
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
config.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
在Startup.cs
中使用Ocelot
。
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
namespace Api_Gateway
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddOcelot();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
app.UseOcelot().Wait();
}
}
}
完成以上操作后,我们试着去调用接口看看能否正确获取预期数据。
curl -X GET "https://localhost:44335/ApiA"
curl -X GET "https://localhost:44335/ApiB"
curl -X POST "https://localhost:44335/ApiA" -H "Content-Type: multipart/form-data" -F "value=ApiA"
curl -X POST "https://localhost:44335/ApiB" -H "Content-Type: multipart/form-data" -F "value=ApiB"
curl -X GET "https://localhost:44335/ApiA/12345"
curl -X GET "https://localhost:44335/ApiB/12345"
curl -X PUT "https://localhost:44335/ApiA/12345" -H "Content-Type: multipart/form-data" -F "value=ApiA"
curl -X PUT "https://localhost:44335/ApiB/12345" -H "Content-Type: multipart/form-data" -F "value=ApiB"
curl -X DELETE "https://localhost:44335/ApiA/12345"
curl -X DELETE "https://localhost:44335/ApiB/12345"
curl -X GET "https://localhost:44335/ApiA/WeatherForecast"
curl -X GET "https://localhost:44335/ApiB/WeatherForecast"
可以看到,两个项目中的接口全部可以通过网关项目暴露的地址进行中转,是不是很方便?
本篇只是简单的应用,对于Ocelot
的功能远不止于此,它非常强大,还可以实现请求聚合、服务发现、认证、鉴权、限流熔断、并内置了负载均衡器,而且这些功能都是只需要简单的配置即可完成。就不一一描述了,如有实际开发需求和问题,可以查看官方文档和示例。
Ocelot一个优秀的.NET API网关框架
1 什么是Ocelot?
Ocelot是一个用.NET Core
实现并且开源的API网关,它功能强大,包括了:路由、请求聚合、服务发现、认证、鉴权、限流熔断、并内置了负载均衡器与Service Fabric、Butterfly Tracing
集成。
2 如何使用Ocelot?
首先,创建2个WebApi
项目,WebApi01
和WebApi02
,地址分别https://localhost:44313
和https://localhost:44390
,其中WebApi01
当作网关,WebApi02
当作具体的微服务Api。
然后,将Ocelot的NuGet软件包安装到WebApi01
项目中。
Ocelot
注意我这里安装的是17.0.0版本,配置方面会有点不一样。
接着,在Startup.ConfigureServices
中增加services.AddOcelot;
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Autofac.WebApi", Version = "v1" });
});
services.AddOcelot();
}
接着,在Startup.Configure
中增加app.UseOcelot().Wait();
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Ocelot.WebApi01 v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseOcelot().Wait();
}
接着,创建ocelot.json
文件
{
"Routes": [ //路由配置(注16.1版本将ReRoutes换成Routes)
{
"DownstreamPathTemplate": "/{url}", // 下游(服务提供方)服务路由模板
"DownstreamScheme": "https", // 下游Uri方案,http、https
"DownstreamHostAndPorts": [ // 服务地址和端口,如果是集群就设置多个
{
"Host": "localhost",
"Port": 44390
}
],
"UpstreamPathTemplate": "/api/{url}", // 上游(客户端,服务消费方)请求路由模板
"UpstreamHttpMethod": [ "GET" ] // 允许的上游HTTP请求方法,可以写多个
}
],
"GlobalConfiguration": { //全局配置
"BaseUrl": "https://localhost:44313" //网关对外地址
}
}
最后,在Program.CreateHostBuilder
中增加AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, builder) => {
builder.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
Ok,让我们来测试看看,https://localhost:44313/api/WeatherForecast会不会跳转https://localhost:44390/WeatherForecast。
.net web api 网关入门
- dotNet 5
- ocelot + consul
ocelot 增加consul
服务发现网关访问提示404问题
ocelot
及 consul
配置经反复对比未发现问题,去除服务发现,恢复下游列表定义的方式网关是可用的(列表方式虽然可用,但负载均衡在站点服务不可用时仍然发送请求过去了,没有达到自动切换的效果),推断问题在ocelot注入端。
- 原注入
ocelot
方式
services
.AddOcelot(new ConfigurationBuilder()
.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true)
.Build())
.AddConsul();
- 需调整为
services
.AddOcelot()
.AddConsul();
ocelot.json
放在 program
中注入:
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("ocelot.json")
.AddEnvironmentVariables();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
Then runs perfect as expected.
ocelot & consul nuget package
- Ocelot
- Ocelot.Provider.Consul
ocelot config
{
"Routes": [
{
"DownstreamPathTemplate": "/api/{controller}/{action}",
"UpstreamPathTemplate": "/yourPrefix/{controller}/{action}",
"UpstreamHttpMethod": [
"Get",
"POST"
],
"DownstreamScheme": "http",
"UseServiceDiscovery": true,
"ReRouteIsCaseSensitive": false,
"ServiceName": "YourServiceName",
"LoadBalancerOptions": {
"Type": "RoundRobin"
}
},
{
"DownstreamPathTemplate": "/yourPrefix/{everything}",
"UpstreamPathTemplate": "/yourPrefix/{everything}",
"UpstreamHttpMethod": [
"Get",
"POST"
],
"DownstreamScheme": "http",
"UseServiceDiscovery": true,
"ReRouteIsCaseSensitive": false,
"ServiceName": "YourServiceName",
"LoadBalancerOptions": {
"Type": "RoundRobin"
}
}
],
"GlobalConfiguration": {
"ServiceDiscoveryProvider": {
"Scheme": "http",
"Host": "localhost",
"Port": 8500,
"Type": "Consul"
}
}
}
consul services config
{
"services": [
{
"id": "webapi1",
"name": "YourServiceName",
"tags": [ "WebApi" ],
"address": "127.0.0.1",
"port": 51012,
"checks": [
{
"id": "AbcCheck1",
"name": "Abc_Check",
"http": "http://127.0.0.1:51012/weatherforecast",
"interval": "10s",
"tls_skip_verify": false,
"method": "GET",
"timeout": "1s"
}
]
},
{
"id": "webapi2",
"name": "YourServiceName",
"tags": [ "WebApi" ],
"address": "127.0.0.1",
"port": 51013,
"checks": [
{
"id": "AbcCheck2",
"name": "Abc1_Check",
"http": "http://127.0.0.1:51013/weatherforecast",
"interval": "10s",
"tls_skip_verify": false,
"method": "GET",
"timeout": "1s"
}
]
}
]
}
Consul, Important: Run Consul as Windows Service
- 下载安装consul https://www.consul.io/.
ps: 下载很慢,超过1个小时
2. sc 创建服务(创建后到服务中更改启动方式为“自动(延迟启动)”)
sc.exe create "Consul" binPath= "D:\Consul\consul.exe agent -server -ui -bootstrap-expect=1 -data-dir=D:\Consul -node=consulNode1 -client=0.0.0.0 -bind=YourLocalIP -datacenter=dc1 -config-dir=D:\Consul\consulServices.json" start= auto
注:
(1)bootstrap-expect=1
, windows
单机
(2)不需要“&
”带入命令行,否则windows service
启动异常。
(3)延迟自动启动,该服务不能在系统重启过程启动(可能和consul.exe
系统启动过程未识别到有关)
Postman 测试
- 下游服务全部可用时,可以轮流发送。
- 下游服务部分不可用时,仍然可以全部发送到可用的服务(不加consul时,ocelot就是服务不可用也发送过去了)
创建项目(一个server
,两个webapi
)
server下载nuget Ocelot
创建Ocelot.json
参照地址
{
"ReRoutes": [//路由配置
//万能模板的优先级最低,只要有其它的路由模板,其它的路由模板则会优先生效。
{
"DownstreamPathTemplate": "/api/{url}",//下游地址
"DownstreamScheme": "https",//下游服务http
"DownstreamHostAndPorts": [//下游地址和端口
{
"Host": "localhost",
"Port": 44323
},
{
"Host": "localhost",
"Port": 44308
}
],
"UpstreamPathTemplate": "/api/{url}",//上游地址
"UpstreamHttpMethod": [ "Get","Post" ],//上游请求方式
"LoadBalancerOptions": {
"Type": "RoundRobin"//添加多个HostAndPort,时候需求指定路由负载均衡,LeastConnection – 将请求发往最空闲的那个服务器 RoundRobin – 轮流发送 NoLoadBalance – 总是发往第一个请求或者是服务发现
},
"Priority":0, //优先级 对多个产生冲突的路由设置优化级
"Key":"ThisKey", //唯一主键,聚合(Aggregates)使用,
"FileCacheOptions": {//缓存
"TtlSeconds": 0,
"Region": ""
},
"AuthenticationOptions": {//认证
"AuthenticationProviderKey": "TestKey",
"AllowedScopes": []
}
"RateLimitOptions": {//限流 对请求进行限流可以防止下游服务器因为访问过载而崩溃
"ClientWhitelist": [],//白名单
"EnableRateLimiting": true,//是否限流
"Period": "1s",//统计时间段:1s, 5m, 1h, 1d
"PeriodTimespan": 1,//多少秒之后客户端可以重试
"Limit":2 //在统计时间段内允许的最大请求数量
},
"QoSOptions": {//服务质量与熔断,需要安装Nuget包(Ocelot.Provider.Polly) 熔断的意思是停止将请求转发到下游服务。当下游服务已经出现故障的时候再请求也是功而返,并且增加下游服务器和API网关的负担。这个功能是用的Pollly来实现的
"ExceptionsAllowedBeforeBreaking": 3, //允许多少个异常请求
"DurationOfBreak": 10, //熔断的时间,单位为秒
"TimeoutValue": 5000 //如果下游请求的处理时间超过多少则自如将请求设置为超时
},
"RouteClaimsRequirement": {//鉴权 通过认证中的AllowedScopes 拿到claims之后,如果要进行权限的鉴别需要添加以下配置
"UserType": "registered"
},
//请求头转化 UpstreamHeaderTransform 和 DownstreamHeaderTransform
"UpstreamHeaderTransform": {
"Test": "http://www.bbc.co.uk/, http://ocelot.com/",
},
"DownstreamHeaderTransform": {
"Location": "{DownstreamBaseUrl}, {BaseUrl}"
},
"HttpHandlerOptions": {
"AllowAutoRedirect": false,
},
"AddClaimsToRequest": {//Claims转化Claims转化功能可以将Claims中的值转化到请求头、Query String、或者下游的Claims中,对于Claims的转化,比较特殊的一点是它提供了一种对字符串进行解析的方法。
"UserType": "Claims[sub] > value[0] > |",
"UserId": "Claims[sub] > value[1] > |"
}
},
{
"DownstreamPathTemplate": "/api/values/sex/{sex}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44308
}
],
"UpstreamPathTemplate": "/MapApi/values/sex/{sex}",
"UpstreamHttpMethod": [ "Get" ],
"Key": "sex"
},
{
"DownstreamPathTemplate": "/api/values/name/{name}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44308
}
],
"UpstreamPathTemplate": "/MapApi/values/name/{name}",
"UpstreamHttpMethod": [ "Get" ],
"Key": "name"
},
{
"DownstreamPathTemplate": "/api/values/{id}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44308
}
],
"UpstreamPathTemplate": "/MapApi/values/{id}",
"UpstreamHttpMethod": [ "Get" ],
"ReRouteIsCaseSensitive": true
},
{
"DownstreamPathTemplate": "/api/values",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
//{
// "Host": "localhost",
// "Port": 44323
//},
{
"Host": "localhost",
"Port": 44308
}
],
"UpstreamPathTemplate": "/MapApi/values",
"UpstreamHttpMethod": [ "Get" ],
"QoSOptions": {//服务质量与熔断 熔断的意思是停止将请求转发到下游服务。当下游服务已经出现故障的时候再请求也是功而返,并且增加下游服务器和API网关的负担。这个功能是用的Pollly来实现的
"ExceptionsAllowedBeforeBreaking": 3, //允许多少个异常请求
"DurationOfBreak": 10, //熔断的时间,单位为秒
"TimeoutValue": 5000 //如果下游请求的处理时间超过多少则自如将请求设置为超时
},
//"HttpHandlerOptions": {
// "AllowAutoRedirect": false,
// "UseCookieContainer": false
//},
//"AuthenticationOptions": {
// "AuthenticationProviderKey": "",
// "AllowedScopes": []
//}
}
],
"Aggregates": [ //聚合操作,需要在ReRotes添加Key 聚合服务目前只支持返回json 目前只支持Get方式请求下游服务 任何下游的response header并会被丢弃 如果下游服务返回404,聚合服务只是这个key的value为空,它不会返回404
{
"ReRouteKeys": [
"sex",
"name"
],
"UpstreamPathTemplate": "/user/{sex}/{name}"
}
],
"GloabalConfiguration": {
"RateLimitOptions": {//限流
"DisableRateLimitHeaders": false,//Http头 X-Rate-Limit 和 Retry-After 是否禁用
"QuotaExceededMessage": "Customize Tips!", // 当请求过载被截断时返回的消息
"HttpStatusCode": 999, //当请求过载被截断时返回的http status
"ClientIdHeader" : "Test" //用来识别客户端的请求头,默认是 ClientId
}
// "RequestIdKey": "OcrequestId",
// "AdministrationPath": "/administration",
//"BaseUrl": "https://api.mybusiness.com" 网关入口
}
}
添加 consul
,Nuget导入Ocelot.Provider.Consul
,本人重新创建了个OcelotConsul.json
{
"ReRoutes": [
{
"DownstreamPathTemplate": "/api/{url}",
"DownstreamScheme": "http",
"UpstreamPathTemplate": "/api/{url}",
"UpstreamHttpMethod": [ "Get" ],
"ServiceName": "servicea",//consul node
"LoadBalancerOptions": {
"Type": "RoundRobin"//负责均衡
},
"UseServiceDiscovery": true
}
],
"GlobalConfiguration": {
// "BaseUrl": "http://127.0.0.1:8887/"
"ServiceDiscoveryProvider": {//全局地址
"Host": "localhost",
"Port": 8500,
"Type": "PollConsul",
"PollingInterval": 100
}
}
}
将json文件导入项目Program.cs
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, builder) =>
{
builder.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("Ocelot.json", false, true);
//.AddJsonFile("OcelotConsul.json", false, true);
})
.UseStartup<Startup>();
注入服务Startup.cs
var authenticationProviderKey = "TestKey";
services.AddAuthentication()
.AddJwtBearer(authenticationProviderKey, x =>
{
x.Authority = "test";
x.Audience = "test";
});//认证(后面详细研究)
services.AddOcelot() //基础调用(Ocelot)
.AddConsul()//添加Consul服务注册(需要添加Nuget Ocelot.Provider.Consul)
.AddPolly();//服务熔断(Ocelot.Provider.Polly)
app.UseOcelot().Wait();