performance - 使用 Docker 对简单的 Go 服务器造成巨大的性能影响
问题描述
我已经尝试了几件事来解决这个问题,但我一无所知。
这是 Go 程序。它只是一个文件,并且有一个/api/sign
接受 POST 请求的端点。这些 POST 请求在正文中有三个字段,它们记录在 sqlite3 数据库中。很基本的东西。
我写了一个简单的 Dockerfile 来容器化它。用于golang:1.7.4
构建二进制文件并将其复制到alpine:3.6
最终图像。再一次,没有什么特别的。
我用来wrk
对性能进行基准测试。使用8 个线程wrk -t8 -c1000 -d50s -s post.lua http://server.com/api/sign
和1k 个连接,持续 50 秒(在所有情况下,我都是wrk
从我的笔记本电脑上运行的,服务器位于离我很近的 DigitalOcean VPS(2 个 vCPU、2 GB RAM、SSD、Debian 9.4)中。
直接运行二进制产生2979 requests/sec。
Docker (
docker run -it -v $(pwd):/data -p 8080:8080 image
) 每秒产生179 个请求。
如您所见,Docker 版本比直接运行二进制文件慢 16 倍以上。在这两个实验中,其他一切都是相同的。
我尝试了以下方法,但 Docker 版本的性能几乎没有改善:
尝试使用主机网络而不是网桥。大约 190 个请求/秒略有增加,但仍然很糟糕。
尝试使用 .增加容器版本中文件描述符数量的限制
--ulimit nofile=262144:262144
。没提升。尝试了不同的go版本,没有。
尝试
debian:9.4
了最终的图像,而不是alpine:3.7
希望它的表现非常糟糕。这里也没有。(编辑)尝试在没有安装卷的情况下运行容器,但仍然没有性能改进。
在这一点上我没有想法。任何帮助将非常感激!
解决方案
使用内存中的 sqlite3 数据库完全解决了所有性能问题!
db, err = sql.Open("sqlite3", "file=dco.sqlite3?mode=memory")
我知道有一个与 Docker 的抽象相关的磁盘 I/O 损失(即使在 Linux 上;我听说它在 macOS 上更糟),但我不知道它会是 ~16 倍。
编辑:大多数时候使用内存数据库并不是一个真正的选择。所以我找到了另一个特定于 sqlite 的解决方案。在所有数据库操作之前,将 sqlite 切换到 WAL 模式而不是默认的回滚日志:
PRAGMA journal_mode=WAL;
PRAGMA synchronous=NORMAL;
这极大地提高了 Docker 版本的性能,超过 2.7k 请求/秒!
推荐阅读
- c - 为什么无符号变量存储负值?
- javascript - 当每个数字超过 15 位时,Nodejs / Javascript 获取开始数字和结束数字之间的数字
- c# - 如何通过以下 {Binding Model.Errors[ClassName.PropertyName]} 使用 XAML 绑定
- node.js - 用sequelize在nodejs中创建“动态查询”?
- python-3.x - keras 自定义度量函数如何将 2 个模型输出提供给单个度量评估函数
- controller - 在 magento 2 控制器中创建对象时发生类型错误
- python - Intellisense 不适用于使用 python 的 vs 代码中的 selenium
- mysql - 将一个项目链接到同一个表中的另一个项目
- json - 在 Laravel 5.8 表中显示 JSON 结果
- python - 如何结合这两个列表?