http服务器_http服务器性能大PK

最近对modern c++ http server--cinatra做了一点性能优化,优化之后做了性能测试,顺便也对比了其它一些常用的http服务器的性能,选择了一些常用的http服务器:java(netty和tomcat), go(beego), .net core3.1, rust(actix-web)的http server。想看看cinatra和其他http server的性能相比如何。

测试机器

CPU: 6 核心 Intel(R) Core(TM) i5-9400F CPU @ 2.90GHz

内存: 16G

系统:ubuntu18.04

测试方法

发送一个GET请求,返回Hello, World!字符串,类似于:

请求

 GET /plaintext HTTP/1.1
Host: server
Connection: keep-alive

响应

 HTTP/1.1 200 OK
Content-Length: 13
Content-Type: text/plain; charset=UTF-8
Server: Example
Date: Thu, 09 Jan 2020 14:14:30 GMT

Hello, World!

测试工具

测试工具选用的wrk,wrk是一个性能优异的http压测工具,很多产品都使用它作为http压测工具,相比ab来说,wrk性能更高,能做充分的压力测试,而且支持的特性更多。

测试方法

wrk命令行

wrk --latency -d10 -c200 --timeout 8 -t 6 http://127.0.0.1:8090/plaintext

命令行解释

-c200: 启动200个连接

-t6: 开启6个线程做压力测试

-d10: 压测持续10s

--timeout 8: 连接超时时间8s

示例

Running 10s test @ http://127.0.0.1:8090/plaintext
6 threads and 1024 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 6.22ms 6.29ms 97.86ms 87.97%
Req/Sec 32.44k 4.98k 60.79k 72.22%
Latency Distribution
50% 4.53ms
75% 7.82ms
90% 13.77ms
99% 31.08ms
1932505 requests in 10.07s, 235.90MB read
Requests/sec: 191933.19
Transfer/sec: 23.43MB

该测试的结果 qps为191933.19, 测试三次取最高的qps.

测试结果

测试方法、测试工具都准备好之后就开始做压力测试了,下面是压力测试的结果:

0b233930f6608b1ca7b43303c87c4567.png

可以看到cinatra的性能是最高的,达到了52w, 这就到顶了吗?远没有,让我们再突破一下,看下一组测试数据:

3c9dd9ba65fb6e8efc54cbf94753085a.png

可以看到支持了http pipeline之后cinatra性能增加了10倍以上达到了670w+。

再来看看测试命令行:

wrk --latency -d10 -c200 --timeout 8 -t 6 http://127.0.0.1:8090/plaintext -s pipeline.lua -- 32

pipeline是http1.1的特性,可以将多个request请求合并在一起发送,服务端按照请求顺序返回给用户,减少了请求次数和实现了结果合并发送从而大幅提高了性能。

测试结论

cinatra作为一个跨平台的http库的性能还是很优异的,它是基于asio开发的,也间接证明了asio的性能也是很优异的,asio会在c++23中进入标准库。

附测试源码

node.js

const Koa = require('koa')
const Router = require('koa-router');

const app = new Koa();
const router = new Router();

router.get('/test', async(ctx, next) => {
ctx.body = 'hello world';
ctx.status = 200;
next();
});

app.use(router.routes()).use(router.allowedMethods());
app.listen(8081, () => {
console.log("listen 6601")
})

java netty和tomcat

package com.octopus.websocket.web;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

@RestController
public class TestController {
@RequestMapping("/")
Mono hello(){
return Mono.just("hello c++");
}
}

go(beego)

package main

import("github.com/astaxie/beego")

type MainController struct {
beego.Controller
}

func(this*MainController)Get(){
this.Ctx.WriteString("hello world")
}

func main(){
beego.BConfig.Listen.HTTPPort =8082
beego.Router("/",&MainController{})
beego.Run()
}

.net-core3.1

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace dotnet_performanceTest {
public class Startup {
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices (IServiceCollection services) {
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure (IApplicationBuilder app, IWebHostEnvironment env) {
app.UseRouting ();

app.UseEndpoints (endpoints => {
endpoints.MapGet ("/", async context => {
await context.Response.WriteAsync ("Hello World!");
});
});
}
}
}

rust(actix-web)

use actix_web::{ web, App, HttpRequest, HttpServer};

fn index(req: HttpRequest) -> &'static str {
"Hello world!"
}

//#[actix_rt::main]
fn main() -> () {

HttpServer::new(|| {
App::new()
.service(web::resource("/").to(index))
})
.bind("0.0.0.0:8083").unwrap()
.run();
}

c++ cinatra

#include 
#include
using namespace cinatra;
int main() {
http_server server(std::thread::hardware_concurrency());
bool r = server.listen("0.0.0.0", "8090");
if (!r) {
std::cout << "listen failed\n";
return -1;
}
server.set_http_handler("/plaintext", [](request& req, response& res) {
res.set_status_and_content(status_type::ok, "Hello, World!", res_content_type::string);
});
server.run();
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值