go解决c10k problem(二)–db版下单场景

TL;DR

前言

这是一篇去年8月写的文章,本来是希望达到10k, 不过实际测试并没有成功,最终达到了1000+的事务,完成C10K的一个K,还有9个 :(

DB选择

DB 类型 业务 io
Mysql sql,支持事务,有缓存 强sql,强类型,类似java B & B+
Postgres sql,支持事务
Mongo nosql,key-value DB,读很快 弱sql,非强制,类似js B+
Redis nosql just kv,代码复杂
sqlite3 sql 强sql,支持事务 Btree

初步结论,理论上是随便用,先用sqlite3把,如果性能达不到,再来排查原因和更改DB

业务场景

我们设计一个sticker网站,可以售卖sticker,用户可以购买sticker,sticker是有库存的,如果用户的余额足够,则可以售卖,另外售卖的过程中,如果库存没了的话,需要回滚订单。

主要对象

  • 用户
  • 商品,库存字段也在商品身上
  • 订单

主要流程

  • 商品的详情页面,get v1/api/sticker/:id
  • 商品的点赞+1接口,post v1/api/sticker/likes
  • 下单接口,post v1/api/order
  • 订单查看接口,get v1/api/order/:id

表现

get 接口 读

load

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 
10154 ubuntu 20 0 1757000 36888 10020 R 362.7 0.1 2:48.41 main 
9046 ubuntu 20 0 2125668 31976 9876 S 346.3 0.1 2:51.78 server

QPS表现

Read more →

go解决c10k problem(一)

零:缘起

最近两个事情

一个是easeprobe,haocl 对其http probe 做了一个10k的benchmark easeprobe benchmark

一个是读到go memory这篇文章 go-memory-ballast

谈到技术,并发是一个绕不过的话题,从第一家公司单机2万qps,到一个50w+ tps的超大型分布式交易系统。

那么自己能否来简单来测试一下呢? 跑一个web server,来个10k 并发,再来个可观测,看下瓶颈到底在哪里? 如何提升? 说干就干。

一:go http server

goroutine的存在,让go在网络编程这块很高效,也有很多优秀的http 框架,比如 gin echo fasthttp

fasthttp 比较快,我们先不读取db和其他,仅让cpu是一个瓶颈,仅写个hello world,收到请求后,返回一行文本。

示例代码

package main

import (
	"fmt"
	"github.com/valyala/fasthttp"
)

// request handler in fasthttp style, i.e. just plain function.
func fastHTTPHandler(ctx *fasthttp.RequestCtx) {
	fmt.Fprintf(ctx, "Hi there! RequestURI is %q", ctx.RequestURI())
}

func main() {
	fasthttp.ListenAndServe(":8087", fastHTTPHandler)
}

二:go http client 压测的client

2.1 压测client选择

  • 简单实现版本,使用time.Sleep 函数,来均匀分布所有的请求到一个server。
  • 复杂实现版本,来一个goroutine的pool,一个http connect的pool,分别控制最大连接数和最大goroutine数目,并且根据请求耗时,动态调整两个pool的大小,然后到一个稳定的状态。
  • 别人现有的,找到一个 go-strees-testing 的项目,可以先用起来

2.2 先选择现有的试试效果

https://github.com/link1st/go-stress-testing

Read more →