goroutine并发MySQL_golang/goroutine 和 swoole/coroutine 协程性能测试对比

协程的一些特性和优点我就不说了,网上很多文章都讲述的很透彻。

协程可以理解为纯用户态的线程,其通过协作而不是抢占来进行切换。相对于进程或者线程,协程所有的操作都可以在用户态完成,创建和切换的消耗更低。开发者可以无感知的用同步的代码编写方式达到异步IO的效果和性能,避免了传统异步回调所带来的离散的代码逻辑和陷入多层回调中导致代码无法维护。

1、golang::goroutine

最近在学习 go,一些高大上的特性果然是为高并发而生,自带的 net/http 包对请求的处理也透明的放在了协程上下文中,真开箱即用。

server.go

package main

import (

"fmt"

"net/http"

"time"

"log"

"runtime"

"bytes"

"strconv"

)

func main() {

// 注册请求 handler

http.HandleFunc("/", func (responseWrite http.ResponseWriter, request *http.Request) {

log.Println("goroutine: ", GetGID(), "start")

// 模拟2秒的IO耗时操作 会发生协程切换

time.Sleep(2 * time.Second)

// 协程继续执行

log.Println("goroutine: ", GetGID(), "end")

// 结束请求

fmt.Fprintln(responseWrite, "

hello world!

")

})

log.Println("server start ...")

err := http.ListenAndServe(":8081", nil)

if nil != err {

log.Fatal(err.Error())

}

}

// 获取 goroutine 的协程 id

func GetGID() uint64 {

b := make([]byte, 64)

b = b[:runtime.Stack(b, false)]

b = bytes.TrimPrefix(b, []byte("goroutine "))

b = b[:bytes.IndexByte(b, ' ')]

n, _ := strconv.ParseUint(string(b), 10, 64)

return n

}

golang 自带的 net/http 包是会自行的分配(有协程池)一个协程去处理请求的,所以模拟的业务耗时,阻塞的 2秒 并不会将主进程挂起,主进程仍在不停的接收请求并分配一个协程去处理请求。

2、swoole::coroutine

Swoole在2.0开始内置协程(Coroutine)的能力,提供了具备协程能力IO接口(统一在命名空间SwooleCoroutine*)。

server.php

$server = new Swoole\Http\Server('0.0.0.0', 8082);

// 工作进程数设为1 这样和 golang 的进程模型基本一致

// swoole worker 默认的 max_coroutine 数为 3000 可根据业务负载自行配置

// @reference https://wiki.swoole.com/wiki/page/950.html

$server->set([

'worker_num' => 1

]);

$server->on("start", function ($server) {

echo "server start ..." . PHP_EOL;

});

// 处理请求

$server->on('request', function ($request, $response) {

echo "goroutine: " . Swoole\Coroutine::getuid() . " start" . PHP_EOL;

/**

* 这里我们需要使用 Swoole\Coroutine::sleep() 来模拟IO耗时 触发协程切换

* 真实的业务场景中你可能使用的是以下协程客户端

* Coroutine\Client Coroutine\Http\Client Coroutine\Http2\Client

* Coroutine\Redis Coroutine\Socket Coroutine\MySQL Coroutine\PostgreSQL

* php 的 sleep() 是没办法触发协程切换的 会被同步阻塞

* 这也是为什么 swoole 的协程中要使用指定的 IO 客户端才能发挥协程的性能

*/

Swoole\Coroutine::sleep(2);

echo "goroutine: " . Swoole\Coroutine::getuid() . " end" . PHP_EOL;

$response->end("

Hello world!

");

});

$server->start();

swoole 的 Server 同 golang 的 net/http 一样的将协程透明化,不过我们在 swoole 中需要使用一些预先提供的方法或客户端才能触发协程切换,进而发挥协程的高性能。

swoole 的各协程客户端:https://wiki.swoole.com/wiki/...

3、ab压测

我们使用以上的业务代码,go 和 swoole 都模拟2秒的业务耗时,服务器配置略渣,vsphere上的一台小小自用服务器 1 核 2G,不要在意(ab测试结果的话简单直接的看Request Per Second)

6846f1275f3298fc22dd6b4369747776.png

200 并发 5000 请求

ab -c 200 -n 5000 -k http://127.0.0.1:8081

ab -c 200 -n 5000 -k http://127.0.0.1:8082

go

2c09e403b9012e36cdb842a5ae023921.png

swoole

c2a9b1f196e5f37d43465bd30c6c0d86.png

500 并发 5000 请求

ab -c 500 -n 5000 -k http://127.0.0.1:8081

ab -c 500 -n 5000 -k http://127.0.0.1:8082

go

a9cb588dacc8b065745d109a77a58ded.png

swoole

153a2eeda92bcb4c4a90166aad3e532f.png

1000 并发 5000 请求

ab -c 1000 -n 5000 -k http://127.0.0.1:8081

ab -c 1000 -n 5000 -k http://127.0.0.1:8082

go

c97fa00b83dc05bbef2ef8d933e77f52.png

swoole

a82dddb6eb207e6a95656226f0cf86c3.png

2000 并发 5000 请求

ab -c 2000 -n 5000 -k http://127.0.0.1:8081

ab -c 2000 -n 5000 -k http://127.0.0.1:8082

go

429924d81c82f1af14f18010bf2a60e5.png

swoole

0ad71448245ab0f03df4e9b5cdc55956.png

可以通过以上几组数据看出,golang::goroutine和swoole::coroutine两个协程的性能基本没有什么差距,而且协程在高并发下更能体现出优异的性能。

同样 5000 的请求,200 - 500 - 1000 - 2000 处理耗时越来越小,说明不是我吃不掉,是你发的太慢。当 2000 并发时,我这台 1核 2G 的服务器都能在阻塞 2 秒的场景下跑到 600- 并发。

但swoole的协程还是要占更多些的内存,我测试机内存比较小,没办法用 swoole 完美的跑 c10k,内存不够用它用的,没办法创建更多的协程去并发处理请求,但 go 还可以,后面在看下 go::goroutine 是不是占用内存更小吧,先跑一个看看。

10k 并发 200k请求

go

86bc96e02aa7c71517592d242df3a23e.png

2019-8-6 11:50:21 换了个测试机,跑完它,swoole 更新到了 4.4.2

新的测试机配置为:2Core 2G 测试代码不变

新测试机对比

go 的并发性好像没 swoole 高了...

go

a7e786c25a20a6b77cf692621294f9bf.png

swoole

ba4496ca1052ec543f747d61e835a630.png

20k 并发 1000k请求

go

1399c99fd0eab9b6cad4ba5f1a6265b8.png

ab 最大并发模拟量为 20k,仅供参考

在 C20K 的并发量下,go http server 依然可以游刃有余的提供服务,qps 可以达到 5K,要知道我模拟的2s的IO耗时可以说是比较大的IO开销了,单机1核2G的配置能压出这样的性能指数,很可以了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值