Ocelot是一个用.NET Core实现并且开源的API网关,它功能强大,包括了:路由、请求聚合、服务发现、认证、鉴权、限流熔断、并内置了负载均衡器与Service Fabric、Butterfly Tracing集成。这些功能只都只需要简单的配置即可完成,下面我们会对这些功能的配置一一进行说明。

介绍

简单的来说Ocelot是一堆的asp.net core middleware组成的一个管道。当它拿到请求之后会用一个request builder来构造一个HttpRequestMessage发到下游的真实服务器,等下游的服务返回response之后再由一个middleware将它返回的HttpResponseMessage映射到HttpResponse上。

API网关—— 它是系统的暴露在外部的一个访问入口。这个有点像代理访问的家伙,就像一个公司的门卫承担着寻址、限制进入、安全检查、位置引导、等等功能。

Ocelot的基本使用

用一台web service来host Ocelot,在这里有一个json配置文件,里面设置了所有对当前这个网关的配置。它会接收所有的客户端请求,并路由到对应的下游服务器进行处理,再将请求结果返回。而这个上下游请求的对应关系也被称之为路由。

集成Identity Server

当我们涉及到认证和鉴权的时候,我们可以跟Identity Server进行结合。当网关需要请求认证信息的时候会与Identity Server服务器进行交互来完成。

网关集群

只有一个网关是很危险的,也就是我们通常所讲的单点,只要它挂了,所有的服务全挂。这显然无法达到高可用,所以我们也可以部署多台网关。当然这个时候在多台网关前,你还需要一台负载均衡器。

Consul 服务发现

在Ocelot已经支持简单的负载功能,也就是当下游服务存在多个结点的时候,Ocelot能够承担起负载均衡的作用。但是它不提供健康检查,服务的注册也只能通过手动在配置文件里面添加完成。这不够灵活并且在一定程度下会有风险。这个时候我们就可以用Consul来做服务发现,它能与Ocelot完美结合。

集成网关

在asp.net core 2.0里通过nuget即可完成集成,或者命令行dotnet add package Ocelot以及通过vs2017 UI添加Ocelot nuget引用都可以。

Install-Package Ocelot

配置

我们需要添加一个.json的文件用来添加Ocelot的配置,以下是最基本的配置信息。

{"ReRoutes": [],"GlobalConfiguration": {"BaseUrl": "https://api.mybusiness.com"}
}

要特别注意一下BaseUrl是我们外部暴露的Url,比如我们的Ocelot运行在http://123.111.1.1的一个地址上,但是前面有一个 nginx绑定了域名http://api.jessetalk.cn,那这里我们的BaseUrl就是 http://api.jessetalk.cn。

将配置文件加入ASP.NET Core Configuration

我们需要通过WebHostBuilder将我们添加的json文件添加进asp.net core的配置

public static IWebHost BuildWebHost(string[] args) =>    WebHost.CreateDefaultBuilder(args)        .ConfigureAppConfiguration( (hostingContext,builder) => {            builder            .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)            .AddJsonFile("Ocelot.json");        })        .UseStartup<Startup>()        .Build();

配置依赖注入与中间件

在startup.cs中我们首先需要引用两个命名空间

using Ocelot.DependencyInjection;using Ocelot.Middleware;

接下来就是添加依赖注入和中间件

public void ConfigureServices(IServiceCollection services) {    services.AddOcelot(); }
public void Configure(IApplicationBuilder app, IHostingEnvironment env) {    if (env.IsDevelopment())    {        app.UseDeveloperExceptionPage();    }    app.UseOcelot().Wait(); }

Ocelot功能介绍

通过配置文件可以完成对Ocelot的功能配置:路由、服务聚合、服务发现、认证、鉴权、限流、熔断、缓存、Header头传递等。在配置文件中包含两个根节点:ReRoutes和GlobalConfiguration。ReRoutes是一个数组,其中的每一个元素代表了一个路由,我们可以针对每一个路由进行以上功能配置。下面是一个完整的路由配置

{"DownstreamPathTemplate": "/","UpstreamPathTemplate": "/","UpstreamHttpMethod": [              "Get"          ],          "AddHeadersToRequest": {},          "AddClaimsToRequest": {},          "RouteClaimsRequirement": {},          "AddQueriesToRequest": {},          "RequestIdKey": "",          "FileCacheOptions": {              "TtlSeconds": 0,              "Region": ""          },          "ReRouteIsCaseSensitive": false,          "ServiceName": "",          "DownstreamScheme": "http",          "DownstreamHostAndPorts": [              {                  "Host": "localhost",                  "Port": 51876,              }          ],          "QoSOptions": {              "ExceptionsAllowedBeforeBreaking": 0,              "DurationOfBreak": 0,              "TimeoutValue": 0          },          "LoadBalancer": "",          "RateLimitOptions": {              "ClientWhitelist": [],              "EnableRateLimiting": false,              "Period": "",              "PeriodTimespan": 0,              "Limit": 0          },          "AuthenticationOptions": {              "AuthenticationProviderKey": "",              "AllowedScopes": []          },          "HttpHandlerOptions": {              "AllowAutoRedirect": true,              "UseCookieContainer": true,              "UseTracing": true          },          "UseServiceDiscovery": false      }
  • Downstream是下游服务配置

  • UpStream是上游服务配置

  • Aggregates 服务聚合配置

  • ServiceName, LoadBalancer, UseServiceDiscovery 配置服务发现

  • AuthenticationOptions 配置服务认证

  • RouteClaimsRequirement 配置Claims鉴权

  • RateLimitOptions为限流配置

  • FileCacheOptions 缓存配置

  • QosOptions 服务质量与熔断

  • DownstreamHeaderTransform头信息转发

我们接下来将对这些功能一一进行介绍和配置

路由

路由是API网关最基本也是最核心的功能、ReRoutes下就是由多个路由节点组成。

{"ReRoutes": []
}

而每一个路由由以下几个基本信息组成:

下面这个配置信息就是将用户的请求 /post/1 转发到 localhost/api/post/1

{"DownstreamPathTemplate": "/api/post/{postId}","DownstreamScheme": "https","DownstreamHostAndPorts": [            {                "Host": "localhost",                "Port": 80,            }        ],    "UpstreamPathTemplate": "/post/{postId}",    "UpstreamHttpMethod": [ "Get"] }
  • DownstreamPathTemplate:下游戏

  • DownstreamScheme:下游服务http schema

  • DownstreamHostAndPorts:下游服务的地址,如果使用LoadBalancer的话这里可以填多项

  • UpstreamPathTemplate: 上游也就是用户输入的请求Url模板

  • UpstreamHttpMethod: 上游请求http方法,可使用数组

万能模板

万能模板即所有请求全部转发,UpstreamPathTemplate 与DownstreamPathTemplate 设置为 “/{url}”

{"DownstreamPathTemplate": "/{url}","DownstreamScheme": "https","DownstreamHostAndPorts": [            {                "Host": "localhost",                "Port": 80,            }        ],    "UpstreamPathTemplate": "/{url}",    "UpstreamHttpMethod": [ "Get" ] }

万能模板的优先级最低,只要有其它的路由模板,其它的路由模板则会优先生效。

上游Host
上游Host也是路由用来判断的条件之一,由客户端访问时的Host来进行区别。比如当a.jesetalk.cn/users/{userid}和b.jessetalk.cn/users/{userid}两个请求的时候可以进行区别对待。

{"DownstreamPathTemplate": "/","DownstreamScheme": "https","DownstreamHostAndPorts": [            {                "Host": "10.0.10.1",                "Port": 80,            }        ],    "UpstreamPathTemplate": "/",    "UpstreamHttpMethod": [ "Get" ],    "UpstreamHost": "a.jessetalk.cn" }

Prioirty优先级
对多个产生冲突的路由设置优化级

{"UpstreamPathTemplate": "/goods/{catchAll}"    "Priority": 0
}
{"UpstreamPathTemplate": "/goods/delete"    "Priority": 1
}

比如你有同样两个路由,当请求/goods/delete的时候,则下面那个会生效。也就是说Prority是大的会被优先选择。

路由负载均衡

当下游服务有多个结点的时候,我们可以在DownstreamHostAndPorts中进行配置。

{"DownstreamPathTemplate": "/api/posts/{postId}","DownstreamScheme": "https","DownstreamHostAndPorts": [            {                "Host": "10.0.1.10",                "Port": 5000,            },            {                "Host": "10.0.1.11",                "Port": 5000,            }        ],    "UpstreamPathTemplate": "/posts/{postId}",    "LoadBalancer": "LeastConnection",    "UpstreamHttpMethod": [ "Put", "Delete" ] }

LoadBalancer将决定负载均衡的算法

  • LeastConnection – 将请求发往最空闲的那个服务器

  • RoundRobin – 轮流发送

  • NoLoadBalance – 总是发往第一个请求或者是服务发现

在负载均衡这里,我们还可以和Consul结合来使用服务发现,我们将在后面的小节中进行详述。

请求聚合

即将多个API请求结果合并为一个返回。要实现请求聚合我们需要给其它参与的路由起一个Key。

{"ReRoutes": [{"DownstreamPathTemplate": "/","UpstreamPathTemplate": "/laura",            "UpstreamHttpMethod": [                "Get"            ],            "DownstreamScheme": "http",            "DownstreamHostAndPorts": [                {                    "Host": "localhost",                    "Port": 51881                }            ],            "Key": "Laura"        },        {            "DownstreamPathTemplate": "/",            "UpstreamPathTemplate": "/tom",            "UpstreamHttpMethod": [                "Get"            ],            "DownstreamScheme": "http",            "DownstreamHostAndPorts": [                {                    "Host": "localhost",                    "Port": 51882                }            ],            "Key": "Tom"        }    ],    "Aggregates": [        {            "ReRouteKeys": [                "Tom",                "Laura"            ],            "UpstreamPathTemplate": "/"        }    ] }

当我们请求/的时候,会将/tom和/laura两个结果合并到一个response返回

{"Tom":{"Age": 19},"Laura":{"Age": 25}}

需要注意的是:

  • 聚合服务目前只支持返回json

  • 目前只支持Get方式请求下游服务

  • 任何下游的response header并会被丢弃

  • 如果下游服务返回404,聚合服务只是这个key的value为空,它不会返回404

有一些其它的功能会在将来实现

  • 下游服务很慢的处理

  • 做一些像 GraphQL的处理对下游服务返回结果进行处理

  • 404的处理

限流

对请求进行限流可以防止下游服务器因为访问过载而崩溃,这个功能就是我们的张善友张队进添加进去的。非常优雅的实现,我们只需要在路由下加一些简单的配置即可以完成。

"RateLimitOptions": {    "ClientWhitelist": [],    "EnableRateLimiting": true,    "Period": "1s",    "PeriodTimespan": 1,    "Limit": 1 }
  • ClientWihteList 白名单

  • EnableRateLimiting 是否启用限流

  • Period 统计时间段:1s, 5m, 1h, 1d

  • PeroidTimeSpan 多少秒之后客户端可以重试

  • Limit 在统计时间段内允许的最大请求数量

在 GlobalConfiguration下我们还可以进行以下配置

"RateLimitOptions": {  "DisableRateLimitHeaders": false,  "QuotaExceededMessage": "Customize Tips!",  "HttpStatusCode": 999,  "ClientIdHeader" : "Test" }
  • Http头  X-Rate-Limit 和 Retry-After 是否禁用

  • QuotaExceedMessage 当请求过载被截断时返回的消息

  • HttpStatusCode 当请求过载被截断时返回的http status

  • ClientIdHeader 用来识别客户端的请求头,默认是 ClientId

服务质量与熔断

熔断的意思是停止将请求转发到下游服务。当下游服务已经出现故障的时候再请求也是功而返,并且增加下游服务器和API网关的负担。这个功能是用的Pollly来实现的,我们只需要为路由做一些简单配置即可

"QoSOptions": {    "ExceptionsAllowedBeforeBreaking":3,    "DurationOfBreak":5,    "TimeoutValue":5000 }
  • ExceptionsAllowedBeforeBreaking 允许多少个异常请求

  • DurationOfBreak 熔断的时间,单位为秒

  • TimeoutValue 如果下游请求的处理时间超过多少则自如将请求设置为超时

缓存

Ocelot可以对下游请求结果进行缓存 ,目前缓存的功能还不是很强大。它主要是依赖于CacheManager 来实现的,我们只需要在路由下添加以下配置即可

"FileCacheOptions": { "TtlSeconds": 15, "Region": "somename" }

Region是对缓存进行的一个分区,我们可以调用Ocelot的 administration API来移除某个区下面的缓存 。

认证

如果我们需要对下游API进行认证以及鉴权服务的,则首先Ocelot 网关这里需要添加认证服务。这和我们给一个单独的API或者ASP.NET Core Mvc添加认证服务没有什么区别。

public void ConfigureServices(IServiceCollection services) {    var authenticationProviderKey = "TestKey";    services.AddAuthentication()        .AddJwtBearer(authenticationProviderKey, x =>        {        }); }

然后在ReRoutes的路由模板中的AuthenticationOptions进行配置,只需要我们的AuthenticationProviderKey一致即可。

"ReRoutes": [{        "DownstreamHostAndPorts": [{                "Host": "localhost",                "Port": 51876,            }        ],        "DownstreamPathTemplate": "/",        "UpstreamPathTemplate": "/",        "UpstreamHttpMethod": ["Post"],        "ReRouteIsCaseSensitive": false,        "DownstreamScheme": "http",        "AuthenticationOptions": {            "AuthenticationProviderKey": "TestKey",            "AllowedScopes": []        }    }]

JWT Tokens

要让网关支持JWT 的认证其实和让API支持JWT  Token的认证是一样的

public void ConfigureServices(IServiceCollection services) {    var authenticationProviderKey = "TestKey";    services.AddAuthentication()        .AddJwtBearer(authenticationProviderKey, x =>        {            x.Authority = "test";            x.Audience = "test";        });    services.AddOcelot(); }

Identity Server Bearer Tokens

添加Identity Server的认证也是一样

public void ConfigureServices(IServiceCollection services) {    var authenticationProviderKey = "TestKey";    var options = o =>        {            o.Authority = "https://whereyouridentityserverlives.com";            o.ApiName = "api";            o.SupportedTokens = SupportedTokens.Both;            o.ApiSecret = "secret";        };    services.AddAuthentication()        .AddIdentityServerAuthentication(authenticationProviderKey, options);    services.AddOcelot(); }

Allowed Scopes

这里的Scopes将从当前 token 中的 claims中来获取,我们的鉴权服务将依靠于它来实现 。当前路由的下游API需要某个权限时,我们需要在这里声明 。和oAuth2中的 scope意义一致。

鉴权

我们通过认证中的AllowedScopes 拿到claims之后,如果要进行权限的鉴别需要添加以下配置

"RouteClaimsRequirement": {    "UserType": "registered"
}

当前请求上下文的token中所带的claims如果没有 name=”UserType” 并且 value=”registered” 的话将无法访问下游服务。

请求头转化

请求头转发分两种:转化之后传给下游和从下游接收转化之后传给客户端。在Ocelot的配置里面叫做Pre  Downstream Request和Post Downstream Request。目前的转化只支持查找和替换。我们用到的配置主要是 UpstreamHeaderTransform 和 DownstreamHeaderTransform

Pre Downstream Request

"Test": "http://www.bbc.co.uk/, http://ocelot.com/"

比如我们将客户端传过来的Header中的 Test 值改为 http://ocelot.com/之后再传给下游

 "UpstreamHeaderTransform": {    "Test": "http://www.bbc.co.uk/, http://ocelot.com/"
},

Post Downstream Request

而我们同样可以将下游Header中的Test再转为 http://www.bbc.co.uk/之后再转给客户端。

"DownstreamHeaderTransform": {    "Test": "http://www.bbc.co.uk/, http://ocelot.com/"
},

变量

在请求头转化这里Ocelot为我们提供了两个变量:BaseUrl和DownstreamBaseUrl。BaseUrl就是我们在GlobalConfiguration里面配置的BaseUrl,后者是下游服务的Url。这里用301跳转做一个示例如何使用这两个变量。

默认的301跳转,我们会返回一个Location的头,于是我们希望将http://www.bbc.co.uk 替换为 http://ocelot.com,后者者网关对外的域名。

"DownstreamHeaderTransform": {    "Location": "http://www.bbc.co.uk/, http://ocelot.com/"
}, "HttpHandlerOptions": {    "AllowAutoRedirect": false, },

我们通过DownstreamHeaderTranfrom将下游返回的请求头中的Location替换为了网关的域名,而不是下游服务的域名。所以在这里我们也可以使用BaseUrl来做为变量替换。

"DownstreamHeaderTransform": {    "Location": "http://localhost:6773, {BaseUrl}"
}, "HttpHandlerOptions": {    "AllowAutoRedirect": false, },

当我们的下游服务有多个的时候,我们就没有办法找到前面的那个http://localhost:6773,因为它可能是多个值。所以这里我们可以使用DownstreamBaseUrl。

"DownstreamHeaderTransform": {    "Location": "{DownstreamBaseUrl}, {BaseUrl}"
}, "HttpHandlerOptions": {    "AllowAutoRedirect": false, },

Claims转化

Claims转化功能可以将Claims中的值转化到请求头、Query String、或者下游的Claims中,对于Claims的转化,比较特殊的一点是它提供了一种对字符串进行解析的方法。举个例子,比如我们有一个sub的claim。这个claims的 name=”sub” value=”usertypevalue|useridvalue”,实际上我们不会弄这么复杂的value,它是拼接来的,但是我们为了演示这个字符串解析的功能,所以使用了这么一个复杂的value。

Ocelot为我们提供的功能分为三段,第一段是Claims[sub],很好理解[] 里面是我们的claim的名称。第二段是  > 表示对字符串进行拆分, 后面跟着拆分完之后我们要取的那个数组里面的某一个元素用 value[index]来表示,取第0位元素也可以直接用value。第三段也是以 > 开头后面跟着我们的分隔符,在我们上面的例子分隔符是 |

所以在这里如果我们要取  usertype这个claim就会这样写: Claims[sub] > value[0] > |

Claim取到之后我们如果要放到请求头、QueryString、以及Claim当中对应有以下三个配置。

Claims to Claims 

"AddClaimsToRequest": {    "UserType": "Claims[sub] > value[0] > |",    "UserId": "Claims[sub] > value[1] > |" }

Claims to Headers 

"AddHeadersToRequest": {    "CustomerId": "Claims[sub] > value[1] > |"
}

这里我们还是用的上面那个 sub = usertypevalue|useridvalue 的claim来进行处理和转化。

Claims to Query String

"AddQueriesToRequest": {    "LocationId": "Claims[LocationId] > value",
}

这里没有进行分隔,所以直接取了value。

Consul服务发现

由于Consul服务发现更多的是Consul的安装、配置、以及使用,所以本小节内容将由另一篇文章来进行详细介绍,欢迎关注。

相关文章:

  • Ocelot——初识基于.Net Core的API网关

  • Ocelot API网关的实现剖析

  • 微服务网关Ocelot

  • API网关Ocelot 使用Polly 处理部分失败问题

  • 谈谈微服务中的 API 网关(API Gateway)

  • Ocelot网关

  • Ocelot统一权限验证

  • 应用监控怎么做?

  • ASP.NET Core之跨平台的实时性能监控

  • .Net Core 2.0+ InfluxDB+Grafana+App Metrics 实现跨平台的实时性能监控

  • 应用程序的8个关键性能指标以及测量方法

  • 使用Metrics监控应用程序的性能

  • 下一个计划 : .NET/.NET Core应用性能管理

  • Ocelot监控

  • Ocelot 集成Butterfly 实现分布式跟踪

  • Ocelot中使用Butterfly实践

  • Ocelot + Consul实践

原文地址:http://www.jessetalk.cn/2018/03/19/net-core-apigateway-ocelot-docs/


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com 

.NET Core开源API网关 – Ocelot中文文档相关推荐

  1. Ocelot中文文档-缓存

    Ocelot中文文档-缓存 原文:Ocelot中文文档-缓存 目前Ocelot使用CacheManager项目提供了一些非常基本的缓存.这是一个了不起的项目,它解决了很多缓存问题. 我会推荐这个软件包 ...

  2. Ocelot中文文档-微服务ServiceFabric

    Ocelot中文文档-微服务ServiceFabric 原文:Ocelot中文文档-微服务ServiceFabric 如果您在Service Fabric中部署了服务,则通常会使用命名服务来访问它们. ...

  3. Ocelot中文文档入门

    入门 Ocelot仅适用于.NET Core,目前是根据netstandard2.0构建的,如果Ocelot适合您,这个文档可能会有用. .NET Core 2.1 安装NuGet包 使用nuget安 ...

  4. ArcGIS API for Javascript 中文文档 百度网盘链接

    对于arcgis api for javascript 学习,最令人头痛的头疼的是中文文档的缺失,这边是我整理的中文文档,用于共同学习. 链接:https://pan.baidu.com/s/1YE_ ...

  5. 『Ocelot』.NET开源API网关 – Ocelot详细使用及其说明(可当文档收藏使用)

    Ocelot是一个用.NET Core实现并且开源的API网关,它功能强大,包括了:路由.请求聚合.服务发现.认证.鉴权.限流熔断.并内置了负载均衡器与Service Fabric.Butterfly ...

  6. nodeJS 中文API node.js 中文文档

    Node.js Manual & Documentation Table Of Contents Synopsis 概要 Global Objects 全局对象 global process ...

  7. lavaral中文手册_Laravel-mix 中文文档

    概览 基本示例 larave-mix 是位于webpack顶层的一个简洁的配置层,在 80% 的情况下使用 laravel mix 会使操作变的非常简单.尽管 webpack 非常的强大,但大部分人都 ...

  8. API网关—Ocelot

    API网关-Ocelot API网关 Ocelot Ocelot的基本使用 API网关 我们知道在微服务架构中,后端会有许许多多的服务实例,但是在UI上进行展示的时候,我们通常需要在一个界面上展示很多 ...

  9. 【Blog.Core开源】网关自定义认证鉴权与传参

    书接上文,上回咱们说到了<[Blog.Core开源]网关统一集成下游服务文档>,已经将多个下游服务统一集成到了网关里,并且也把接口文档Swagger给集成了,那今天就说一下认证和鉴权相关的 ...

最新文章

  1. 《用Python进行自然语言处理》第2章 获得文本语料和词汇资源
  2. golang应用部署
  3. addActionListener(this)
  4. 从零开始的Python学习Episode 4——列表
  5. 在Winform程序中设置管理员权限及为用户组添加写入权限
  6. jert oracle 统计说明,Oracle JET简单入门(一)Oracle JET介绍
  7. iOS7初体验(2)——单元测试
  8. 劝你要看一些有门槛的机会
  9. RabbitMQ TTL、死信队列在订单支付场景的应用
  10. 北美互联网公司“隐藏福利”大盘点:看完我彻底酸了...
  11. 前端代码的整洁之道 | 技术头条
  12. 机器视觉:CMOS图像传感器
  13. 未初始化的类,通过指针调用其非静态函数
  14. HRTF音频3D定位技术
  15. 05JavaScript输出
  16. 微信小程序实现微信企业付款到零钱功能的流程
  17. 异常:HRESULT: 0x80070057 (E_INVALIDARG) 的处理
  18. 【Unity入门】3.3D物体
  19. 计算机专业在线杂志,计算机类的cscd期刊汇总
  20. java方法重写[详解]

热门文章

  1. WCF分布式开发常见错误(25):The certificate 'CN=WCFHTTPS' must have a private key
  2. 《统计会犯错——如何避免数据分析中的统计陷阱》—第2章置信区间的优势
  3. linux centos7 root密码重置
  4. 纯IPv6环境App适配的坑
  5. php 利用http上传协议(表单提交上传图片 )
  6. 【转】URL编码(encodeURIComponent和decodeURIComponent)
  7. MDT部署中命令行脚本的使用。
  8. 专题1.1——Exchange2013部署前准备条件
  9. 为什么这个SQL Server DBA学习PowerShell--SQL任务
  10. C#断点续传原理与实现