上篇文章给大家讲解了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; }
}
  1. 接下来我们给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);
    }
    }
  2. 接下来我们分别在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
    }
  3. 在ocelot.all.json中加入聚合配置,如下所示:

      "Aggregates": [
    {
    "ReRouteKeys": [
    "Good",
    "Order"
    ],
    "UpstreamPathTemplate": "/GetOrderDetail/{id}"
    }
    ]

    注意:这里AggregatesReRoutes同级,ReRouteKeys中填写的数组就是上面步骤3中设置的Key属性对应的值。

  4. 我们分别运行起来三个项目,然后访问接口地址:http://localhost:1000/GetOrderDetail/1 会得到如下的聚合响应内容:


    格式化后代码如下:

    {
    "Good":{
    "Id":1,
    "Content":"1的关联的商品明细"
    },
    "Order":{
    "Id":1,
    "Content":"1的订单明细"
    }
    }
  5. 眼尖的朋友可能已经猜到了。聚合路由返回的内容就是json串。json串由ReRouteKeys组成,每个Key的内容就是具体下游响应的内容了!实例代码已经同步更新到Github上,地址:https://github.com/yilezhu/OcelotDemo

    Ocelot将始终使用聚合请求返回内容类型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动态路由功能也进行了简单的阐述。对于请求聚合这块进行了相关实例代码的演示,并已经更新到Github上面了!希望能对大家有所帮助!

作者:依乐祝

出处:https://www.cnblogs.com/yilezhu

联系:1015657114@qq.com .NET Core实战项目交流群:637326624

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如有问题或建议,请多多赐教,非常感谢。

[转载]Ocelot简易教程(四)之请求聚合以及服务发现的更多相关文章

  1. Ocelot简易教程(四)之请求聚合以及服务发现

    上篇文章给大家讲解了Ocelot的一些特性并对路由进行了详细的介绍,今天呢就大家一起来学习下Ocelot的请求聚合以及服务发现功能.希望能对大家有所帮助. 作者:依乐祝 原文地址:https://ww ...

  2. [转载]Ocelot简易教程(三)之主要特性及路由详解

    上篇<Ocelot简易教程(二)之快速开始2>教大家如何快速跑起来一个ocelot实例项目,也只是简单的对Ocelot进行了配置,这篇文章会给大家详细的介绍一下Ocelot的配置信息.希望 ...

  3. [转载]Ocelot简易教程(一)Ocelot是什么

    Ocelot简易教程(一)Ocelot是什么 简单的说Ocelot是一个用.NET Core实现并且开源的API网关技术. 可能你又要问了,什么是API网关技术呢?Ocelot又有什么特别呢?我们又该 ...

  4. [转载]Ocelot简易教程(五)之集成IdentityServer认证以及授权

    作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/9807125.html 最近比较懒,所以隔了N天才来继续更新第五篇Ocelot简易教程,本篇教程会先简单介 ...

  5. [转载]Ocelot简易教程(二)之快速开始2

    为什么这篇的标题叫“Ocelot简易教程(二)之快速开始2”呢,因为很多朋友跟我说上一篇“ Ocelot简易教程(二)之快速开始1”内容太少了,只是简单介绍Ocelot的一些简单配置,让Ocelot能 ...

  6. [转载]Ocelot简易教程(六)之重写配置文件存储方式并优化响应数据

    作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/9807125.html 很多人都说配置文件的配置很繁琐,如果存储在数据库就方便很多,可以通过自定义UI界面 ...

  7. [转载]Ocelot简易教程(二)之快速开始1

    Ocelot是为.net core量身定做的,目前是基于 netstandard2.0进行构建的. .NET Core 2.1中如何使用呢? 安装NuGet package 使用nuget安装Ocel ...

  8. Ocelot简易教程(七)之配置文件数据库存储插件源码解析

    作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/9852711.html 上篇文章给大家分享了如何集成我写的一个Ocelot扩展插件把Ocelot的配置存储 ...

  9. Ocelot简易教程(六)之重写配置文件存储方式并优化响应数据

    本来这篇文章在昨天晚上就能发布的,悲剧的是写了两三千字的文章居然没保存,结果我懵逼了.今天重新来写这篇文章.今天我们就一起来探讨下如何重写Ocelot配置文件的存储方式以及获取方式. 作者:依乐祝 原 ...

随机推荐

  1. java初始化过程中成员变量

    package day01; class Base{ int j; //1.j=0 Base(){ add(1); //2.调用子类add()方法 System.out.println(j); //4 ...

  2. 关于结构体COORD介绍

    COORD是windows API中定义的一种结构,表示一个字符在控制台屏幕上的坐标.其定义为: typedef struct _COORD { SHORT X; // horizontal coor ...

  3. 72.挖掘CSDN密码到链表并统计密码出现次数生成密码库

    list.h #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include & ...

  4. SpringCloud核心教程 | 第一篇: 使用Intellij中的Spring Initializr来快速构建Spring Cloud工程

    spring cloud简介 spring cloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理.服务发现.断路器.路由.微代理.事件总线.全局锁.决策竞选.分布式会话等等.它运行环 ...

  5. C++ Traits 技术

    Tarits.特性的复数. c++萃取技术就是指它. 实现方式是模板特化. STL中涉及到iterator的地方常常能用到它. gcc的STL与VS的STL略有区别. vs中下列代码,把鼠标放在ite ...

  6. 让人难过的 openssl_pkcs7_encrypt

    让人难过的 openssl_pkcs7_encrypt 用PHP.NET的范例,没有加密结果,也没有报错信息,而openssl_pkcs7_sign()函数则返回 error opening inpu ...

  7. ASP.NET MVC案例教程(基于ASP.NET MVC beta)——第三篇:ASP.NET MVC全局观

    摘要      本文对ASP.NET MVC的全局运行机理进行一个简要的介绍,以使得朋友们更好的理解后续文章. 前言      在上一篇文章中,我们实现了第一个ASP.NET MVC页面.对于没有接触 ...

  8. RMAN DUPLICATE ADG DEMO

    RMAN DUPLICATE ADG DEMO 生产环境谨慎使用,建议生产环境采用RMAN备份恢复的方式. 本演示案例所用环境:   primary standby OS Hostname pry s ...

  9. Jszip的使用和打包下载图片

    因为canvas总结到后面又想到了jszip的一些事情,那就索性也回去看看吧.试过,至少谷歌和火狐都是支持jszip的. 1.  jszip的使用 官方文档说的很清楚了,而且也有读取zip文件.生成z ...

  10. GO语言学习(十七)Go 语言类型转换

    Go 语言类型转换 类型转换用于将一种数据类型的变量转换为另外一种类型的变量.Go 语言类型转换基本格式如下: type_name(expression) type_name 为类型,expressi ...