Ocelot官网文档:https://ocelot.readthedocs.io/en/latest/features/servicediscovery.html
现有微服务的几点不足:
1> 对于在微服务体系中、和Consul通讯的微服务来讲,使用服务名即可访问。但是对于手机、web端等外部访问者仍然需要和N多服务器交互,需要记忆他们的服务器地址、端口号等。一旦内部发生修改,很麻烦,而且有时候内部服务器是不希望外界直接访问的。
2> 各个业务系统的人无法自由的维护自己负责的服务器;
3> 现有的微服务都是“我家大门常打开”,没有做权限校验。如果把权限校验代码写到每个微服务上,那么开发工作量太大。(假如一个系统中存在几十个微服务,每个微服务都有自己的独立权限校验,就太麻烦了)
4> 很难做限流、收费等。(例如:我有一个台发送短信的微服务,一个用户每天可以免费发送5条短信,如果想发送6条短信就要收费)
ocelot 中文文档:https://blog.csdn.net/sD7O95O/article/details/79623654 资料:http://www.csharpkit.com/apigateway.html 官网:https://github.com/ThreeMammals/Ocelot 腾讯.Net大队长“张善友”是项目主力开发人员之一。
基于以上的问题,API网关就可以解决以上的问题
API网关有很多种(比如zuul),我们想要说的是Ocelot
Ocelot就是一个提供了请求路由、安全验证等功能的API网关微服务。
1>建一个空的asp.net core项目。(我取名叫OcelotApp)
2>安装 Install-Package Ocelot
3>项目根目录下创建configuration.json配置文件(名字自取)
configuration.json配置文件设置如下(假设我的微服务中有一个用于发送短信的MsgService微服务,一个用于提供产品的ProductService微服务,于是我在里面就配置了关于这两个微服务的转发路由)
{/*这个用到的根节点就是一个ReRoutes数组*/
"ReRoutes": [
{
//第一个路由规则
//这个路由就表示:当一个请求以MsgService为开头,后面跟具体的URL,并且这个请求是get,或者post 那么我就给他转交给localhost:5001这个地址
//例如:我的Ocelot的IP地址为113.118.195.106,监听6008端口,当一个用户请求这个地址
//例如请求:http://113.118.195.106:6008/MsgService/Home/Index?name=lily
//那么我就将请求转交给 http://localhost:5001/api/Home/Index?name=lily
"DownstreamPathTemplate": "/api/{url}", //表示在url地址的前面加一个api
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5001
}
],
"UpstreamPathTemplate": "/MsgService/{url}",
"UpstreamHttpMethod": [ "Get", "Post" ]
},
//第二个路由规则
{
"DownstreamPathTemplate": "/api/{url}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5003
}
],
"UpstreamPathTemplate": "/ProductService/{url}",
"UpstreamHttpMethod": [ "Get", "Post" ]
}
//当然我们也可以添加跟多的路由
]
}
Program类
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace OcelotApp
{
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
var config = new ConfigurationBuilder().AddCommandLine(args).Build();
string ip = config["ip"];
string port = config["port"];
return WebHost.CreateDefaultBuilder(args)
.UseStartup()
.UseUrls($"http://{ip}:{port}")
//在这里加载configuration.json配置文件
.ConfigureAppConfiguration((hostingContext, builder) =>
{
builder.AddJsonFile("configuration.json", false, true); //将configuration.json配置文件夹到IConfigurationBuilder中
});
}
}
}
Startup类
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
namespace OcelotApp
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddOcelot(Configuration);//将IConfiguration类对象Configuration加载到服务中注册
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseOcelot().Wait(); //使用Ocelot中间件
}
}
}
调用:
启用OcelotApp这个项目
然后,启动我们的的Consul服务
我们在微服务一:服务治理发现(Consul) 这节文章中创建了一个MsgServer的服务
我们现在也启动这个MsgServer的项目(设定这个项目的ip地址为 127.0.0.1,监听端口为5001)
然后我们打开Postman这个软件,在里面请求OcelotApp这个项目
http://127.0.0.1:8888/MsgService/SMS/Send_LX
我们可以看到我们请求的是http://127.0.0.1:8888/MsgService/SMS/Send_LX (OcelotApp这个项目)而这个项目最终把请求转交给了 http://127.0.0.1:5001/api/SMS/Send_LX 这个地址处理
Ocelotp配合Consul一起使用,代码跟上面的是一样的,只要将configuration.json配置文件该成如下即可
{
//官⽅方⽂文档ReRoutes全节点示例例
"ReRoutes": [
{
//Upstream表示上游请求,即客户端请求到API Gateway的请求
"UpstreamPathTemplate": "/", //请求路路径模板
"UpstreamHttpMethod": [ //请求⽅方法数组
"Get",
"POST",
"PUT",
"DELETE",
"OPTIONS"
],
//Downstreamb表示下游请求,即API Gateway转发的⽬目标服务地址
"DownstreamScheme": "http", //请求协议,⽬目前应该是⽀支持http和https
"DownstreamHostAndPorts": [
{
"Host": "localhost", //请求服务地址,应该是可以是IP及域名
"Port": 8081 //端⼝口号 }
],
"DownstreamPathTemplate": "/", //下游请求地址模板
// 以下节点可选
"RouteClaimsRequirement": { //标记该路路由是否需要认证
"UserType": "registered" //示例例,K/V形式,授权声明,授权token中 会包含⼀一些claim,如填写则会判断是否和token中的⼀一致,不不⼀一致则不不准访问
},
//以下三个是将access claims转为⽤用户的Header Claims,QueryString,该 功能只有认证后可⽤用
"AddHeadersToRequest": { //
"UserType": "Claims[sub] > value[0] > |", //示例例
"UserId": "Claims[sub] > value[1] > |" //示例例 },
"AddClaimsToRequest": {},
"AddQueriesToRequest": {},
"RequestIdKey": "", //设置客户端的请求标识key,此key在请求header中 ,会转发到下游请求中
"FileCacheOptions": { //缓存设置
"TtlSeconds": 15, //ttl秒被设置为15,这意味着缓存将在15秒后过期 。
"Region": "" //缓存region,可以使⽤用administrator API清除 },
"ReRouteIsCaseSensitive": false, //路路由是否匹配⼤大⼩小写
"ServiceName": "", //服务名称,服务发现时必填
"QoSOptions": { //断路路器器配置,⽬目前Ocelot使⽤用的Polly
"ExceptionsAllowedBeforeBreaking": 0, //打开断路路器器之前允许的例例 外数量量。
"DurationOfBreak": 0, //断路路器器复位之前,打开的时间(毫秒)
"TimeoutValue": 0 //请求超时时间(毫秒) },
"LoadBalancer": "", //负载均衡 RoundRobin(轮询)/LeastConnection( 最少连接数)
"RateLimitOptions": { //官⽅方⽂文档未说明
"ClientWhitelist": [], // 客户端⽩白明代 ?
"EnableRateLimiting": false, // 是否限流 ?
"Period": "",
"PeriodTimespan": 0,
"Limit": 0
},
"AuthenticationOptions": { //认证配置
"AuthenticationProviderKey": "", //这个key对应的是代码中.AddJW TBreark中的Key
"AllowedScopes": [] //使⽤用范围 },
"HttpHandlerOptions": {
"AllowAutoRedirect": true, //指示请求是否应该遵循重定向响应。 如果请求应该⾃自动遵循来⾃自Downstream资源的重定向响应,则将其设置为true; 否则为假。
默认值是true。
"UseCookieContainer": true //该值指示处理理程序是否使⽤用CookieCon tainer属性来存储服务器器Cookie,并在发送请求时使⽤用这些Cookie。 默认值是true。
},
"UseServiceDiscovery": false //使⽤用服务发现,⽬目前Ocelot只⽀支持Consu l的服务发现
}
],
"GlobalConfiguration": {}
}