一、背景

目前我们项目是采用的 Ocelot 作为 API 网关,并且在其基础上结合 IdentityServer4 开发了一套 API 开放平台。由于部分项目是基于 ABP 框架进行开发的,接口的平均 QPS 基本是在 2K~3K /S 左右 (E3 1231 16G)。采用 Ocelot 进行请求转发之后,前端反馈接口调用速度变慢了,也没有太过在意,以为是项目接口的问题,一直在接口上面尝试进行优化。

极限优化接口后仍然没有显著改善,故针对 Ocelot 的性能进行压力测试,得到的结果也是让我比较惊讶。

二、准备工作

2.1 测试项目准备

首先新建了一个解决方案,其名字为 OcelotStudy ,其下面有三个项目,分别是两个 API 项目和一个网关项目。

网关项目编写:

为 OcelotStudy 项目引入 Ocelot 的 NuGet 包。

在 OcelotStudy 项目的 Program.cs 文件当中显式指定我们网关的监听端口。

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting; namespace OcelotStudy
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
} public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
// 指定监听端口为 5000
webBuilder.UseStartup<Startup>()
.UseKestrel(x=>x.ListenAnyIP(5000));
});
}
}

在 Startup.cs 类当中注入 Ocelot 的服务,并应用 Ocelot 的中间件。

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Ocelot.DependencyInjection;
using Ocelot.Middleware; namespace OcelotStudy
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// 禁用日志的控制台输出,防止由于线程同步造成的性能损失
services.AddLogging(op => op.ClearProviders());
services.AddMvc();
services.AddOcelot(new ConfigurationBuilder().AddJsonFile("Ocelot.json").Build());
} public async void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
await app.UseOcelot();
app.UseMvc();
}
}
}

在 OcelotStudy 项目下建立 Ocelot.json 文件,内容如下。

{
"ReRoutes": [
{
"DownstreamPathTemplate": "/api/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "API 1 服务器IP",
"Port": 6000
},
{
"Host": "API 2 服务器IP",
"Port": 7000
}
],
"UpstreamPathTemplate": "/{everything}",
"UpstreamHttpMethod": [ "Get", "Post" ],
"LoadBalancerOptions": {
"Type": "RoundRobin"
}
}
],
"GlobalConfiguration": { }
}

测试项目的编写:

两个测试项目的监听端口分别为 6000 与 7000 ,都建立一个 ValuesController 控制器,返回一个字符串用于输出当前请求的 API 服务器信息。

ApiService01 的文件信息:

using Microsoft.AspNetCore.Mvc;

namespace ApiService01.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<string> Get()
{
return "当前请求的 API 接口是 1 号服务器。";
} // GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return "value";
} // POST api/values
[HttpPost]
public void Post([FromBody] string value)
{
} // PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
} // DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
}

ApiService02 的文件信息:

using Microsoft.AspNetCore.Mvc;

namespace ApiService02.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<string> Get()
{
return "当前请求的 API 接口是 2 号服务器。";
} // GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return "value";
} // POST api/values
[HttpPost]
public void Post([FromBody] string value)
{
} // PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
} // DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
}

他们两个的 Startup.cs 与 Program.cs 文件内容基本一致,区别只是监听的端口分别是 6000 和 7000 而已。

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting; namespace ApiService02
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
} public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
webBuilder.UseKestrel(x => x.ListenAnyIP(6000)); // 或者 7000
});
}
}
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; namespace ApiService02
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
} public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// 禁用日志的控制台输出,防止由于线程同步造成的性能损失
services.AddLogging(op => op.ClearProviders());
services.AddMvc();
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseRouting(routes => { routes.MapApplication(); });
}
}
}

以上三个项目都采用 Release 版本进行发布。

dotnet publish -c Release

ApiService01 部署在单独的 E3 1231 v3 16G DDR3 服务器。

ApiService02 部署在单独的 i3-7100 16G DDR4 服务器。

OcelotStudy 部署在单独的 E3 1231 v3 16G DDR3 服务器。

三、开始测试

这里我使用的是 WRK 来进行压力测试,OcelotStudy 网关项目的 IP 地址为 172.31.61.41:5000 ,故使用以下命令进行测试。

./wrk -t 10 -c 10000 -d 20s --latency --timeout 3s "http://172.31.61.41:5000/values"

测试结果:

我将 ApiService01 项目放在网关的服务器,直接调用 ApiService01 的接口,其压力测试情况。

四、结语

最后 Ocelot 的 QPS 结果为:3461.53

直接请求 API 接口的 QPS 结果为:38874.50

这样的结果让我感到很意外,不知道是由于 Ocelot 实现机制的原因,还是我的使用方法不对。这样的性能测试结果数据对于 API 网关来说确实不太好看,但也希望今后 Ocelot 能够继续努力。

如果大家对于我的测试方式有疑问的话,可以在评论区指出,我将按照你所提供的方法再次进行测试。(PS: 我也不想换啊,多希望是我测错了)

五、原生 API、Ocelot、Kong API 性能比较

针对于评论区各位朋友所提出的建议,以及我最近针对 Ocelot 的再次测试,整理出来一份测试结果的表格。以下结果均是单节点进行部署,如果使用 LB + API 集群的话是可以有效提升吞吐量。

使用的网关 测试时间 并发数 总请求 QPS 超时数量 平均响应
没有使用网关 1 分钟 15000 2495541 41518.07 1592 115.98 ms
Kong API 1 分钟 15000 690141 11478.06 43997 860.31 ms
Ocelot 1 分钟 15000 277627 4618.98 1795 1.7 s
没有使用网关 1 分钟 5000 2530107 42111.44 0 115.48 ms
Kong API 1 分钟 5000 866449 14418.25 3090 383.75 ms
Ocelot 1 分钟 5000 307226 5113.09 78 932.19 ms
没有使用网关 10 分钟 8000 13080964 21797.98 103 364.97 ms
Kong API 10 分钟 8000 4809613 8014.7 305503 636.41 ms
Ocelot 10 分钟 8000 2558431 4263.34 2137 1.84 s

Ocelot 与 Kong 均部署在一台 32G 12C 3.0Ghz 的 CentOS 服务器上,API 1 与 API 2 部署在 8C 16G 3.0 Ghz 的服务器上,所有环境都是基于 Docker CE 进行部署。

另外针对于 Kong API 不知道是我使用方式不对还是什么情况,其网络吞吐量经常波动,如下图,还请不吝赐教。

网关服务器:

API 1 与 API 2 服务器:

针对 Ocelot 网关的性能测试的更多相关文章

  1. .net core下,Ocelot网关与Spring Cloud Gateway网关的对比测试

    有感于 myzony 发布的 针对 Ocelot 网关的性能测试 ,并且公司下一步也需要对.net和java的应用做一定的整合,于是对Ocelot网关.Spring Cloud Gateway网关做个 ...

  2. 庐山真面目之六微服务架构Consul集群、Ocelot网关集群和Nginx版本实现

    庐山真面目之六微服务架构Consul集群.Ocelot网关集群和Nginx版本实现 一.简介      在上一篇文章<庐山真面目之五微服务架构Consul集群.Ocelot网关和Nginx版本实 ...

  3. .Net Core 商城微服务项目系列(三):Ocelot网关接入Grafana监控

    使用网关之后我们面临的一个问题就是监控,我们需要知道网关的实时状态,比如当前的请求吞吐量.请求耗费的时间.请求峰值甚至需要知道具体哪个服务的哪个方法花费了多少时间.网关作为请求的中转点是监控品牌的要塞 ...

  4. Ocelot网关+IdentityServer4实现API权限认证

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

  5. 庐山真面目之七微服务架构Consul集群、Ocelot网关集群和IdentityServer4版本实现

    庐山真面目之七微服务架构Consul集群.Ocelot网关集群和IdentityServer4版本实现 一.简介      在上一篇文章<庐山真面目之六微服务架构Consul集群.Ocelot网 ...

  6. 庐山真面目之十二微服务架构基于Docker搭建Consul集群、Ocelot网关集群和IdentityServer版本实现

    庐山真面目之十二微服务架构基于Docker搭建Consul集群.Ocelot网关集群和IdentityServer版本实现 一.简介      在第七篇文章<庐山真面目之七微服务架构Consul ...

  7. 微服务之十四如何在 Ocelot 网关中配置多实例 Swagger 访问

    一.介绍 当我们开发基于微服务的应用程序的时候,有一个环节总是跳不过去的,那就是要创建 WebApi,然后,我们的应用程序基于 WebApi 接口去访问.在没有 Swagger 以前,我们开发好了 W ...

  8. 针对C#程序做性能测试的一些基本准则

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:针对C#程序做性能测试的一些基本准则.

  9. 基于.NET平台的Ocelot网关框架教程汇总

    Ocelot 框架是基于.NET 开发的 API 网关,API网关是系统内部服务暴露在外部的一个访问入口,类似于代理服务器,就像一个公司的门卫承担着寻址.限制进入.安全检查.位置引导等工作,我们可以形 ...

随机推荐

  1. 局域网IP地址

    A类: 10.X.X.X是私有地址(私有地址就是在互联网上不使用,而被用在局域网络中的地址). 127.X.X.X是保留地址,用做循环测试用的. B类: 172.16.0.0---172.31.255 ...

  2. 如何从Eclipse导入github上的项目源码--转载

    [转载出处声明:hil2000的专栏] 1.首先在github.com上申请一个账号,比如笔者的账号为puma0072.Eclipse需要安装egit插件,在Eclipse中选择help->Ma ...

  3. pythonpipinstallpymongo报错

    1.安装pymongo模块,报错pip版本低,升级版本又报错找不到合适的版本,网友说网络问题,要使用国内的镜像源来加速:pip install pymongo -i http://pypi.douba ...

  4. C#代码总结04---通过创建临时表DataTable进行临时编辑删除

    <script type="text/javascript"> //删除 function Delete(hdGuid) { $("#hdGuid" ...

  5. 关于resharper激活

    resharper 是一款非常强大的vs辅助开发插件,提供了很多快捷操作功能,本人已经离不开它了,但是resharper总会遇到lincese过期,需要激活的问题,现在提供以下方式,仅供参考 1.打开 ...

  6. sqlzoo:4

    列出每個國家的名字 name,當中人口 population 是高於俄羅斯'Russia'的人口. SELECT name FROM world WHERE population > (SELE ...

  7. centOS7.3新安装后,设置IP,以及Putty远程和Xshell远程 (学习是个持续的过程,也许中途放松过,但是仍然能重新捡起来,并学以致用,方为真勇士)

    有一段时间没有写学习心得了:现在开始加油,再接再励. 从最基础的开始 1.安装centOS7.3之后设置IP地址.一般linux的系统都是作为服务器的系统来使用,服务器的属性注定了他的IP不能随意的更 ...

  8. 数据分析——numpy

    DIKW DATA-->INFOMATION-->KNOWLEDGE-->WISDOM 数据-->信息-->知识-->智慧 爬虫-->数据库-->数据分 ...

  9. Ubuntu ARM更改为国内源

    关键词:ubuntu  arm  ubuntu-ports  国内源  镜像  阿里源  apt apt-get install update  0%working  速度慢  rk3399  开发板 ...

  10. python语法_json_pickle

    ---恢复内容开始--- dic = {"name":"kevin","age":"20"} f = open(&quo ...