Ocelot简易教程(四)之请求聚合以及服务发现
上篇文章给大家讲解了Ocelot的一些特性并对路由进行了详细的介绍,今天呢就大家一起来学习下Ocelot的请求聚合以及服务发现功能。希望能对大家有所帮助。
作者:依乐祝
原文地址:https://www.cnblogs.com/yilezhu/p/9695639.html
请求聚合
Ocelot允许你声明聚合路由,这样你可以把多个正常的ReRoutes打包并映射到一个对象来对客户端的请求进行响应。比如,你请求订单信息,订单中又包含商品信息,这里就设计到两个微服务,一个是商品服务,一个是订单服务。如果不运用聚合路由的话,对于一个订单信息,客户端可能需要请求两次服务端。实际上这会造成服务端额外的开销。这时候有了聚合路由后,你只需要请求一次聚合路由,然后聚合路由会合并订单跟商品的结果都一个对象中,并把这个对象响应给客户端。使用Ocelot的此特性可以让你很容易的实现前后端分离的架构。
为了实现Ocelot的请求功能,你需要在ocelot.json中进行如下的配置。这里我们指定了了两个正常的ReRoutes,然后给每个ReRoute设置一个Key属性。最后我们再Aggregates节点中的ReRouteKeys属性中加入我们刚刚指定的两个Key从而组成了两个ReRoutes的聚合。当然我们还需要设置UpstreamPathTemplate匹配上游的用户请求,它的工作方式与正常的ReRoute类似。
注意:不要把Aggregates中UpstreamPathTemplate设置的跟ReRoutes中的UpstreamPathTemplate设置成一样。
下面我们先上个实例例子先!演示代码已经同步更新Github上。有兴趣的朋友可以查看源码:https://github.com/yilezhu/OcelotDemo
在开始实例前先把我们的ocelot Nuget包升级到最新的12.0.0版本,当然你也可以不进行升级。这里需要注意一下,如果你升级到12.0.0的版本的话,那么你
config.AddOcelot()
的用法会发生改变,需要传入参数config.AddOcelot(hostingContext.HostingEnvironment)
1.为了演示的需要这里我们新增一个类库项目,分别新建两个类,一个是商品Good类,一个是订单Order类(这里只是为了演示的需要,所以代码很简陋)如下所示:
public class Goods
{
public int Id { get; set; }
public string Content { get; set; }
}
public class Orders
{
public int Id { get; set; }
public string Content { get; set; }
}
接下来我们给OrderApi以及GoodApi分别新建一个控制器,并返回相应的实体。如下所示:
//GoodApi项目中
[Route("api/[controller]")]
[ApiController]
public class GoodController : ControllerBase
{
// GET api/Good/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
var item = new Goods
{
Id = id,
Content = $"{id}的关联的商品明细",
};
return JsonConvert.SerializeObject(item);
}
}
//OrderApi项目中
[Route("api/[controller]")]
[ApiController]
public class OrderController : ControllerBase
{
// GET api/Order/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
var item = new Orders {
Id=id,
Content=$"{id}的订单明细",
};
return JsonConvert.SerializeObject(item);
}
}
接下来我们分别在ocelot.good.json以及ocelot.order.json中新增一个路由,并给出Keys.如下所示:
这里注意,跟上篇文章中的路由不同的是,这里多了一个Key属性。
//ocelot.good.json
{
"DownstreamPathTemplate": "/api/Good/{id}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 1001
}
],
"UpstreamPathTemplate": "/good/{id}",
"UpstreamHttpMethod": [ "Get", "Post" ],
"Key": "Good",
"Priority": 2
}
//ocelot.order.json
{
"DownstreamPathTemplate": "/api/Order/{id}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 1002
}
],
"UpstreamPathTemplate": "/order/{id}",
"UpstreamHttpMethod": [ "Get", "Post" ],
"Key": "Order",
"Priority": 2
}
在ocelot.all.json中加入聚合配置,如下所示:
"Aggregates": [
{
"ReRouteKeys": [
"Good",
"Order"
],
"UpstreamPathTemplate": "/GetOrderDetail/{id}"
}
]
注意:这里
Aggregates
跟ReRoutes
同级,ReRouteKeys
中填写的数组就是上面步骤3中设置的Key
属性对应的值。我们分别运行起来三个项目,然后访问接口地址:http://localhost:1000/GetOrderDetail/1 会得到如下的聚合响应内容:
格式化后代码如下:{
"Good":{
"Id":1,
"Content":"1的关联的商品明细"
},
"Order":{
"Id":1,
"Content":"1的订单明细"
}
}
眼尖的朋友可能已经猜到了。聚合路由返回的内容就是json串。json串由
ReRouteKeys
组成,每个Key
的内容就是具体下游响应的内容了!实例代码已经同步更新到Github上,地址:https://github.com/yilezhu/OcelotDemoOcelot将始终使用聚合请求返回内容类型application/json。还有需要注意的是聚合请求不会返回404请求。如果两个下游都返回404状态码的话,这里聚合后的响应也不会返回404,只会返回空的json串,拿上面的实例,如果两个下游都返回404的话,那么他的响应代码类似下面这样:
{
"Good": ,
"Order":
}
如果下游服务返回404,则聚合将仅为该下游服务返回任何内容。即使所有下游都返回404,它也不会将聚合响应更改为404。
服务发现
Ocelot允许您指定服务发现提供程序,并将使用它来查找Ocelot将请求转发到的下游服务的主机和端口。目前,这仅在GlobalConfiguration部分中受支持,这意味着相同的服务发现提供程序将用于为ReRoute级别指定ServiceName的所有ReRoutes。
Consul
在使用Consul前你首先要做的就是安装在Ocelot中提供Consul支持的NuGet包
Install-Package Ocelot.Provider.Consul
然后将下面的内容添加在ConfigureServices方法中
services.AddOcelot()//注入Ocelot服务
.AddConsul();
GlobalConfiguration中需要加入以下内容。如果您未指定主机和端口,则将使用Consul默认值。
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 8500,
"Type": "Consul"
}
注意:如果你采用
AddOcelot()
这种方式来自动加载ocelot配置文件的方式,那么你需要新建一个ocelot.global.json文件,然后加入上面的配置:如下所示:{
"GlobalConfiguration": {
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 8500,
"Type": "Consul"
}
}
}
然后重新运行dotnet run命令会自动合并配置信息到Ocelot.json中,生成的对应内容如下:
```C#
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 8500,
"Type": "Consul",
"Token": null,
"ConfigurationKey": null,
"PollingInterval": 0
}
这个上篇文章中已经进行了相关的介绍。
为了告诉Ocelot ReRoute是为其主机和端口使用服务发现提供程序,您必须在下游请求时添加要使用的ServiceName和负载均衡器。目前,Ocelot可以使用RoundRobin和LeastConnection算法。如果未指定负载均衡器,则Ocelot将不会对请求进行负载均衡。
{
"DownstreamPathTemplate": "/api/posts/{postId}",
"DownstreamScheme": "https",
"UpstreamPathTemplate": "/posts/{postId}",
"UpstreamHttpMethod": [ "Put" ],
"ServiceName": "product",
"LoadBalancerOptions": {
"Type": "LeastConnection"
},
}
设置此项后,Ocelot将从服务发现提供程序中查找下游主机和端口,并跨任何可用服务进行负载平衡请求。
动态路由
作者的想法是在使用服务发现提供程序时启用动态路由。在此模式下,Ocelot将使用上游路径的第一个段来与服务发现提供程序一起查找下游服务。
例如,使用https://api.yilezhu.cn/product/products 等网址调用ocelot 。Ocelot将采用产品路径的第一部分product
,并将其用作在Consul中查找服务的Key。如果consul返回一个服务,Ocelot将使用从consul返回的主机和端口以及剩余路径段组合后的Url来进行请求的响应。,如:http:// hostfromconsul:portfromconsul/products。Ocelot将正常向下游URL转发查询字符串。即query
要启用动态路由,您需要在配置中保留0个ReRoutes。目前您无法混合动态和配置ReRoutes。除此之外,您还需要指定上面概述的Service Discovery提供程序详细信息和下游http / https方案作为DownstreamScheme。
除此之外,您还可以设置RateLimitOptions,QoSOptions,LoadBalancerOptions和HttpHandlerOptions,DownstreamScheme(您可能希望在https上调用Ocelot,但可以通过http与私有服务进行通信),这些将应用于所有动态ReRoutes。
配置可能看起来像:
{
"ReRoutes": [],
"Aggregates": [],
"GlobalConfiguration": {
"RequestIdKey": null,
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 8500,
"Type": "Consul",
"Token": null,
"ConfigurationKey": null
},
"RateLimitOptions": {
"ClientIdHeader": "ClientId",
"QuotaExceededMessage": null,
"RateLimitCounterPrefix": "ocelot",
"DisableRateLimitHeaders": false,
"HttpStatusCode": 429
},
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 0,
"DurationOfBreak": 0,
"TimeoutValue": 0
},
"BaseUrl": null,
"LoadBalancerOptions": {
"Type": "LeastConnection",
"Key": null,
"Expiry": 0
},
"DownstreamScheme": "http",
"HttpHandlerOptions": {
"AllowAutoRedirect": false,
"UseCookieContainer": false,
"UseTracing": false
}
}
}
Ocelot还允许您设置DynamicReRoutes,允许您为每个下游服务设置速率限制规则。如果您有一个产品和搜索服务,并且您希望对另一个进行速率限制,则此功能非常有用。这方面的一个例子如下。
{
"DynamicReRoutes": [
{
"ServiceName": "product",
"RateLimitRule": {
"ClientWhitelist": [],
"EnableRateLimiting": true,
"Period": "1s",
"PeriodTimespan": 1000.0,
"Limit": 3
}
}
],
"GlobalConfiguration": {
"RequestIdKey": null,
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 8523,
"Type": "Consul"
},
"RateLimitOptions": {
"ClientIdHeader": "ClientId",
"QuotaExceededMessage": "",
"RateLimitCounterPrefix": "",
"DisableRateLimitHeaders": false,
"HttpStatusCode": 428
}
"DownstreamScheme": "http",
}
}
此配置意味着如果您在/product/上进入Ocelot请求,则动态路由将启动,并且ocelot将使用针对DynamicReRoutes部分中的产品服务的速率限制设置。
GitHub地址
https://github.com/yilezhu/OcelotDemo
Ocelot简易教程目录
- Ocelot简易教程(一)之Ocelot是什么
- Ocelot简易教程(二)之快速开始1
- Ocelot简易教程(二)之快速开始2
- Ocelot简易教程(三)之主要特性及路由详解
- Ocelot简易教程(四)之请求聚合以及服务发现
- Ocelot简易教程(五)之集成IdentityServer认证以及授权
- Ocelot简易教程(六)之重写配置文件存储方式并优化响应数据
- Ocelot简易教程(七)之配置文件数据库存储插件源码解析
总结
本文接着上篇文章进行了Ocelot请求聚合功能以及服务发现功能的介绍,并且对Ocelot动态路由功能也进行了简单的阐述。对于请求聚合这块进行了相关实例代码的演示,并已经更新到Github上面了!希望能对大家有所帮助!
Ocelot简易教程(四)之请求聚合以及服务发现的更多相关文章
- [转载]Ocelot简易教程(四)之请求聚合以及服务发现
上篇文章给大家讲解了Ocelot的一些特性并对路由进行了详细的介绍,今天呢就大家一起来学习下Ocelot的请求聚合以及服务发现功能.希望能对大家有所帮助. 作者:依乐祝 原文地址:https://ww ...
- Ocelot简易教程(七)之配置文件数据库存储插件源码解析
作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/9852711.html 上篇文章给大家分享了如何集成我写的一个Ocelot扩展插件把Ocelot的配置存储 ...
- Ocelot简易教程(六)之重写配置文件存储方式并优化响应数据
本来这篇文章在昨天晚上就能发布的,悲剧的是写了两三千字的文章居然没保存,结果我懵逼了.今天重新来写这篇文章.今天我们就一起来探讨下如何重写Ocelot配置文件的存储方式以及获取方式. 作者:依乐祝 原 ...
- Ocelot简易教程(五)之集成IdentityServer认证以及授权
Ocelot简易教程目录 Ocelot简易教程(一)之Ocelot是什么 Ocelot简易教程(二)之快速开始1 Ocelot简易教程(二)之快速开始2 Ocelot简易教程(三)之主要特性及路由详解 ...
- Ocelot简易教程(三)之主要特性及路由详解
作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/9664977.html 上篇<Ocelot简易教程(二)之快速开始2>教大家如何快速跑起来一个 ...
- Ocelot简易教程(二)之快速开始2
为什么这篇的标题叫"Ocelot简易教程(二)之快速开始2"呢,因为很多朋友跟我说上一篇" Ocelot简易教程(二)之快速开始1"内容太少了,只是简单介绍Oc ...
- Ocelot简易教程(二)之快速开始1
Ocelot简易教程目录 Ocelot简易教程(一)之Ocelot是什么 Ocelot简易教程(二)之快速开始1 Ocelot简易教程(二)之快速开始2 Ocelot简易教程(三)之主要特性及路由详解 ...
- Ocelot简易教程(一)之Ocelot是什么
作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/9557375.html Ocelot简易教程目录 Ocelot简易教程(一)之Ocelot是什么 Ocel ...
- [转载]Ocelot简易教程(三)之主要特性及路由详解
上篇<Ocelot简易教程(二)之快速开始2>教大家如何快速跑起来一个ocelot实例项目,也只是简单的对Ocelot进行了配置,这篇文章会给大家详细的介绍一下Ocelot的配置信息.希望 ...
随机推荐
- BaseDao.util(虎大将军)
package logistics.util; import java.sql.Connection; import java.sql.PreparedStatement; import java.s ...
- squid 透明代理配置
阿铭在教程中已经介绍过squid的安装和配置,http://study.lishiming.net/chapter22.html 教程中只介绍了初级的正向代理和反向代理,这篇文档将要介绍透明代理如何配 ...
- 20155312 张竞予 Exp2 后门原理与实践
Exp2 后门原理与实践 目录 基础问题回答 (1)例举你能想到的一个后门进入到你系统中的可能方式? (2)例举你知道的后门如何启动起来(win及linux)的方式? (3)Meterpreter有哪 ...
- poi实现Excel文件的读取
1.前端代码 $("#upload").on('click', function() { var formData = new FormData(); var name = $(& ...
- 关于分布式事务,XA协议的学习笔记
XA分布式事务协议,包含二阶段提交(2PC),三阶段提交(3PC)两种实现. 1.二阶段提交方案:强一致性 事务的发起者称协调者,事务的执行者称参与者. 处理流程: 1.准备阶段 事务协调者,向所有事 ...
- linux修改用户id,组id
一.修改用户uid usermod -u foo 二.修改用户gid groupmod -g 2005 foo usermod -g 2005 foo 三.检查 cat /etc/passwd su ...
- LOJ-10094(强连通分量)
题目链接:传送门 思路: 先缩点,然后统计入度为0的点即可. #include<iostream> #include<cstdio> #include<cstring&g ...
- 安装完Ubuntu后通过shell脚本一键安装软件
安装完Ubuntu后通过shell脚本一键安装软件 以下代码中#是单行注释 :<<! ! 是多行注释. 运行的时候需要把多行注释去掉. 比如把以下代码保存为install.sh, 那么在终 ...
- 使用IDEA进行版本控制
1.使用IDEA进行版本控制 创建git repository add-添加到暂存区 commit-提交到本地库 push-推送指定远程库(自己的) idea上的pull指的是合并(merge),并非 ...
- VMware安装xp虚拟机
VMware安装xp虚拟机 1.用到的软件: 2.安装VMware: 接受 选择自定义 要等上一小会. 输入密钥:百度一个就可以了. 安装成功: 禁用VMware网卡: 3.安装xp系统: 创建新的 ...