在上篇.Net微服务实践(二):Ocelot介绍和快速开始中我们介绍了Ocelot,创建了一个Ocelot Hello World程序,接下来,我们会介绍Oclot的主要特性路由和另外一个特性请求聚合。这些特性都是通过配置来实现的。

配置

{
"ReRoutes": [],
"GlobalConfiguration": {}
}

Ocelot的配置文件包含两个节点: ReRoutes和GlobalConfiguration

  • ReRoutes - 告诉Ocelot如何处理上游的请求
  • GlobalConfiguration - 全局配置,此节点的配置允许覆盖ReRoutes里面的配置,你可以在这里进行通用的一些配置信息

Ocelot的完整配置项如下

{
"DownstreamPathTemplate": "/",
"UpstreamPathTemplate": "/",
"UpstreamHttpMethod": [
"Get"
],
"DownstreamHttpMethod": "",
"DownstreamHttpVersion": "",
"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,
"MaxConnectionsPerServer": 100
},
"DangerousAcceptAnyServerCertificateValidator": false
}

完整配置项中的每一项具体含义和作用接下来会一一介绍,大的配置项的主要含义如下:

  • Downstream - 下游服务配置
  • UpStream - 上游服务配置
  • Aggregates - 服务聚合配置
  • ServiceName, LoadBalancer, UseServiceDiscovery - 配置服务发现
  • AuthenticationOptions - 配置服务认证
  • RouteClaimsRequirement - 配置Claims鉴权
  • RateLimitOptions - 限流配置
  • FileCacheOptions - 缓存配置
  • QosOptions - 服务质量与熔断
  • DownstreamHeaderTransform - 头信息转发

路由

基本配置

在上一篇的hello world程序中使用的就是基本配置

{
"ReRoutes": [
{
"DownstreamPathTemplate": "/api/orders",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5001
}
],
"UpstreamPathTemplate": "/api/orders",
"UpstreamHttpMethod": [ "Get" ]
}
],
"GlobalConfiguration": {
"BaseUrl": "http://localhost:5000"
}
}
  • BaseUrl - Ocelot的服务运行地址,要特别注意一下BaseUrl是我们外部暴露的Url,比如我们的Ocelot运行在http://localhost:5000,但是前面有一个 nginx绑定了域名http://api.demo.com,那这里我们的BaseUrl就是 http://api.demo.com
  • UpstreamPathTemplate、UpstreamHttpMethod - 配置上游服务器请求URL
  • DownstreamPathTemplate、DownstreamScheme、DownstreamHostAndPorts - 配置下游服务器请求URL

在基本配置的示例中:要实现的功能就是将 http://localhost:5000/api/orders GET 请求路由到 http://localhost:5001/api/orders GET

占位符

在Ocelot中,可以以{something}的形式将变量的占位符添加到模板中。占位符变量需要同时出现在DownstreamPathTemplate和UpstreamPathTemplate属性中。请求时Ocelot将尝试请求时进行替换

{
"DownstreamPathTemplate": "/api/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5002
}
],
"UpstreamPathTemplate": "/api/{everything}",
"UpstreamHttpMethod": [ "Get" ]
}

示例说明:所有http://localhost:5000/api/XXXXXX的请求都会路由到http://localhost:5002/api/XXXXXX


例如http://localhost:5000/api/products 路由到 http://localhost:5002/api/products


例如http://localhost:5000/api/products/1 路由到 http://localhost:5002/api/products/1

验证

修改配置,运行示例程序, 访问http://localhost:5000/api/products,返回了产品数据

注意:在添加Ocelot.json文件时 .AddJsonFile("Ocelot.json",false,true), 第三个参数是指定文件发生变化时,是否重新加载,示例程序中是true. 所以我们只要修改运行目录下的配置文件,不用重新运行示例程序。

万能模板

既然占位符可以做通用匹配,自然而然就有一种配置可以匹配所有请求

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

示例说明: 转发所有的请求到http://localhost:5002

验证

修改配置,运行示例程序, 访问http://localhost:5000/api/products,返回了产品数据

优先级

如果一个上游请求有多个路由配置都能匹配,到底该使用哪个路由呢? 路由可以配置优先级(Priority), 0最小,路由会使用优先级高的(说明:如果多个匹配路由优先级一样,则按顺序使用第一个)

  • 在product-api中添加一个category api
[ApiController]
public class CategoryController : ControllerBase
{
// GET: api/Product
[Route("api/categories")]
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "电子产品", "医护用品" };
}
}
  • 修改Ocelot.json配置文件如下
{
"DownstreamPathTemplate": "/api/products",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5002
}
],
"UpstreamPathTemplate": "/api/products",
"UpstreamHttpMethod": [ "Get" ],
"Priority": 0
},
{
"DownstreamPathTemplate": "/api/categories",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5002
}
],
"UpstreamPathTemplate": "/api/{everything}",
"UpstreamHttpMethod": [ "Get" ],
"Priority": 1
}

如果这时访问http://localhost:5000/api/products, 大家猜一下,是返回产品数据还是类别数据?

验证

修改配置,运行示例程序, 访问http://localhost:5000/api/products,返回了类别数据, 因为类别路由的优先级是1, 优先级更高

查询参数

  • 在order-api中添加一个订单明细的api\
[Route("api/orders/{id}")]
[HttpGet]
public string Get(int id)
{
string order = string.Empty;
switch(id)
{
case 1:
order = "刘明的订单";
break;
case 2:
order = "王天的订单";
break;
default:
order = "没有找到订单";
break;
}
return order; }
  • 修改Ocelot.json配置如下
{
"DownstreamPathTemplate": "/api/orders/{id}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5001
}
],
"UpstreamPathTemplate": "/api/orders?id={id}",
"UpstreamHttpMethod": [ "Get" ]
}

我们期望的结果是,当访问http://localhost:5000/api/orders?id=1 (下游服务实际没这个接口)时 路由到http://localhost:5001/api/orders/1返回订单明细

验证

修改配置,运行示例程序, 访问http://localhost:5000/api/orders?id=1,返回了订单明细数据

请求聚合

有一种场景,前端一个页面,调用了多个API,要同时开多个连接几次调用才能全部所需要的数据,为了减少不必要的请求和开销,Ocelot也支持请求聚合

默认聚合

  • 修改配置文件,在ReRoutes 添加如下配置
{
"DownstreamPathTemplate": "/api/orders",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5001
}
],
"UpstreamPathTemplate": "/api/orders",
"UpstreamHttpMethod": [ "Get" ],
"Key": "Orders"
},
{
"DownstreamPathTemplate": "/api/products",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5002
}
],
"UpstreamPathTemplate": "/api/products",
"UpstreamHttpMethod": [ "Get" ],
"Priority": 0,
"Key": "Products"
}

大家注意一下,这和之前的配置有什么区别? 区别就是再每一个路由配置下多了一个 Key, Key的值可以任意定义(但建议还是按业务含义定义)

  • 在Ocelot.json中添加如下配置
"Aggregates": [
{
"ReRouteKeys": [
"Orders",
"Products"
],
"UpstreamPathTemplate": "/api/aggregates"
}
]

注意Aggregates配置是和在ReRoutes配置平级的

{
"ReRoutes": [],
"Aggregates": [],
"GlobalConfiguration": {}
}

示例说明: 当访问http://localhost:5000/api/aggregates, 会同时返回订单数据和产品数据

运行示例进行验证

既然是多个请求聚合,那么问题来了:

  • 如果其中一个服务宕机,会怎么样?


    我们停止订单服务,再次当访问http://localhost:5000/api/aggregates, 结果返回500
  • 如果其中一个服务不是宕机,而是返回500,会怎么样?


    我们修改order-api代码,在其中抛出异常
// GET: api/Product
[Route("api/orders")]
[HttpGet]
public IEnumerable<string> Get()
{
throw new Exception("获取所有订单出错");
}

再次运行示例,访问http://localhost:5000/api/aggregates,Response是200, 但是body中Products节点是正常的产品数据,Orders节点里面的数据是异常信息

自定义聚合

如果默认的聚合返回的结果数据结构不是我们想要的,想要修改怎么办?答案是使用自定义聚合

  • 在ocelot-gateway中, 添加一个自动以聚合器FakeDefinedAggregator, 必须实现IDefinedAggregator接口。这个聚合器的功能很简单,就是将两个聚合请求的结果,用逗号拼接起来返回
public class FakeDefinedAggregator : IDefinedAggregator
{
public FakeDefinedAggregator(FakeDepdendency dep)
{
} public async Task<DownstreamResponse> Aggregate(List<DownstreamContext> responses)
{
var one = await responses[0].DownstreamResponse.Content.ReadAsStringAsync();
var two = await responses[1].DownstreamResponse.Content.ReadAsStringAsync(); var merge = $"{one}, {two}";
var headers = responses.SelectMany(x => x.DownstreamResponse.Headers).ToList();
return new DownstreamResponse(new StringContent(merge), HttpStatusCode.OK, headers, "some reason");
}
}
  • 注入自定义聚合器
services.AddOcelot()
.AddSingletonDefinedAggregator<FakeDefinedAggregator>();
  • 在Ocelot.json中修改配置,指定自定义聚合器
"Aggregates": [
{
"ReRouteKeys": [
"Orders",
"Products"
],
"UpstreamPathTemplate": "/api/aggregates",
"Aggregator": "FakeDefinedAggregator"
}
],

与之前的配置相比,多了如下的配置,就是指定自定义聚合器的

"Aggregator": "FakeDefinedAggregator"

验证

修改配置,运行示例程序, 访问http://localhost:5000/api/aggregate, 验证返回结果

最后

本篇我们介绍了Ocelot配置,只要特性路由,以及请求聚合。接下里我们会介绍Ocelot的其他特性:限流熔断、负载均衡 .Net微服务实践(四)[网关]:Ocelot限流熔断、缓存以及负载均衡

示例代码下载地址: https://github.com/lcyhjx/ocelot-demo/tree/master

.Net微服务实践(三):Ocelot配置路由和请求聚合的更多相关文章

  1. Python微服务实践-集成Consul配置中心

    A litmus test for whether an app has all config correctly factored out of the code is whether the co ...

  2. spring cloud微服务实践三

    上篇文章里我们实现了spring cloud中的服务提供者和使用者.接下来我们就来看看spring cloud中微服务的其他组件. 注:这一个系列的开发环境版本为 java1.8, spring bo ...

  3. .Net微服务实践(二):Ocelot介绍和快速开始

    目录 介绍 基本原理 集成方式 快速开始 创建订单服务 创建产品服务 创建网关 运行验证 最后 上篇.Net微服务实践(一):微服务框架选型 我们对微服务框架整体做了介绍,接下来我们从网关Ocelot ...

  4. .Net微服务实践(四)[网关]:Ocelot限流熔断、缓存以及负载均衡

    目录 限流 熔断 缓存 Header转化 HTTP方法转换 负载均衡 注入/重写中间件 后台管理 最后 在上篇.Net微服务实践(三)[网关]:Ocelot配置路由和请求聚合中我们介绍了Ocelot的 ...

  5. ASP.NET Core OceLot 微服务实践

    1.OceLot中间件介绍 在传统的BS应用中,随着业务需求的快速发展变化,需求不断增长,迫切需要一种更加快速高效的软件交付方式.微服务可以弥补单体应用不足,是一种更加快速高效软件架构风格.单体应用被 ...

  6. .NET Core 微服务—API网关(Ocelot) 教程 [三]

    前言: 前一篇文章<.NET Core 微服务—API网关(Ocelot) 教程 [二]>已经让Ocelot和目录api(Api.Catalog).订单api(Api.Ordering)通 ...

  7. .NET Core微服务之基于Ocelot实现API网关服务

    Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.啥是API网关? API 网关一般放到微服务的最前端,并且要让API 网关变成由应用所发起的每个请求的入口.这样就可以明显的简化客户端 ...

  8. QCon技术干货:个推基于Docker和Kubernetes的微服务实践

    2016年伊始,Docker无比兴盛,如今Kubernetes万人瞩目.在这个无比需要创新与速度的时代,由容器.微服务.DevOps构成的云原生席卷整个IT界.在近期举办的QCon全球软件开发大会上, ...

  9. SFDC 微服务实践之路 2016.12.10 杭州(整理)--转

    原文地址:http://mp.weixin.qq.com/s/8cC4Ewt6yPjnxdYxuNZlFQ 微服务是什么? 微服务是一种细粒度(Fine-Grain)的SOA 或许在座的高朋了解过其概 ...

随机推荐

  1. CSS3详解:border color

    继续我们的 ,大家觉得怎么样呢?

  2. python社区要放弃了pip?版本信息里带警告很不寻常哦

    pip是python的一个包管理器. 今天再查询Pip3 -V 时,除了正常的版本信息外,多了几行信息 WARNING: pip is being invoked by an old script w ...

  3. TARS基金会:构建微服务开源生态

    导语 在20世纪60至70年代,软件开发人员通常在大型机和小型机上使用单体架构进行软件开发,没有一个应用程序能够满足大多数最终用户的需求.垂直行业使用的软件代码量更小,与其他应用程序的接口更简单,而可 ...

  4. 在Linux上查询物理机信息-不用去拆机器了

    目录 一.查看系统信息(包含机器型号) 1.1 查看机型和品牌 二.查看CPU 信息 2.1 查看CPU 型号 2.2 查看CPU的物理数量 2.3 查看 CPU核心数量(非逻辑CPU) 2.4 查看 ...

  5. 死磕Lambda表达式(三):更简洁的Lambda

    我们都是阴沟里的虫子,但总还是得有人仰望星空.--<三体> 在之前的文章中介绍了Lambda表达式的基本语法和正确使用姿势,这次我来介绍一些Lambda更简洁的用法. 欢迎关注微信公众号: ...

  6. Java的反射基础技术

    今天本人给大家讲解一下Java的反射基础技术,如有不对的或者讲的不好的可以多多提出,我会进行相应的更改,先提前感谢提出意见的各位了!!! 什么是反射? 反射它是根据字节码文件可以反射出类的信息.字段. ...

  7. BJDCTF

    python3的模板注入 非常简单...就是直接执行命令就行..虽然过滤了flag,但是拼接下就好了.... payload: http://fd5883ee-b8e2-4bf1-88af-33936 ...

  8. 我用STM32MP1做了个疫情监控平台3—疫情监控平台实现

    目录 1.前言 2.数据接口的获取 3.Qt界面的实现 4.在开发板上运行Qt程序 5.使用无线模块联网 6.代码下载 @ 1.前言 之前我使用桌面版本Qt实现了肺炎疫情监控平台:基于Qt的新冠肺炎疫 ...

  9. 我的MacbookPro进水了!维修过程记录

    电脑进水与解决方案 如果事情有变坏的可能,不管这种可能性有多小,它总会发生.---墨菲定律 进水过程 2020年03月21日日下午3点左右,不小心把水杯碰倒了,水通过电脑右侧的键盘处进入了大概有10毫 ...

  10. mysql主从复制(主从同步)

    mysql主从同步 1.mysql主从同步(复制)概念 1. 将Mysql某一台主机数据复制到其它主机(slaves)上,并重新执行一遍来实现的. 2. 复制过程中一个服务器充当主服务器,而一个或多个 ...