当前位置: 移动技术网 > IT编程>开发语言>.net > 针对 Ocelot 网关的性能测试

针对 Ocelot 网关的性能测试

2019年02月20日  | 移动技术网IT编程  | 我要评论

相框制作,bovod,我最讨厌别人黑小米了

一、背景

目前我们项目是采用的 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": "localhost",
          "port": 6000
        },
        {
          "host": "localhost",
          "port": 7000
        }
      ],
      "upstreampathtemplate": "/{everything}",
      "upstreamhttpmethod": [ "get", "post" ],
      "loadbalanceroptions": {
        "type": "roundrobin"
      }
    }
  ],
  "globalconfiguration": {
    // "baseurl": "https://api.yilezhu.cn"
  }
}

测试项目的编写:

两个测试项目的监听端口分别为 60007000 ,都建立一个 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.csprogram.cs 文件内容基本一致,区别只是监听的端口分别是 60007000 而已。

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: 我也不想换啊,多希望是我测错了)

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网