### 性能报告

自从 seata-golang 开源以来，社区的同学都比较关心它的性能。2020 年 12 月 12 日，我利用周末的时间用 jmeter 对它进行了测试。

#### 测试的方法

测试的 demo 为项目 `samples/at` 中的 [demo](https://github.com/opentrx/seata-golang/tree/dev/samples/at)，数据库为本地 docker 中搭建的 mysql，测试工具为 jmeter。电脑配置如下：

电脑配置：

MacBook Pro (15-inch, 2018)

处理器 2.2 GHz 六核Intel Core i7

内存 16 GB 2400 MHz DDR4

jmeter 参数如下：

![image-20201213133633210](https://github.com/opentrx/seata-golang/blob/dev/docs/pics/image-20201213133633210.png)

100 个线程循环 10 次访问 http://localhost:8003/createSoCommit。

该接口调用一个聚合服务创建订单，聚合服务分别调用订单服务写入订单，再调用库存服务分配库存。

#### 测试过程

1. 配置 demo 中的 tc server 为 seata-golang 项目中的 tc server，测试结果如下：

go client 连接 go tc server：

| Label    | # 样本 | 平均值 | 中位数 | 90% 百分位 | 95% 百分位 | 99% 百分位 | 最小值 | 最大值 | 异常 % | 吞吐量   | 接收 KB/sec | 发送 KB/sec |
| -------- | ------ | ------ | ------ | ---------- | ---------- | ---------- | ------ | ------ | ------ | -------- | ----------- | ----------- |
| HTTP请求 | 400    | 3978   | 4290   | 4566       | 4603       | 4883       | 420    | 5105   | 0.00%  | 22.34512 | 3.47        | 3.58        |
| 总体     | 400    | 3978   | 4290   | 4566       | 4603       | 4883       | 420    | 5105   | 0.00%  | 22.34512 | 3.47        | 3.58        |

2. 配置 demo 中的 tc server 为 java 版 seata 的 tc server，测试结果如下：

go client 连接 java tc server (version 1.4)：

| Label    | # 样本 | 平均值 | 中位数 | 90% 百分位 | 95% 百分位 | 99% 百分位 | 最小值 | 最大值 | 异常 % | 吞吐量   | 接收 KB/sec | 发送 KB/sec |
| -------- | ------ | ------ | ------ | ---------- | ---------- | ---------- | ------ | ------ | ------ | -------- | ----------- | ----------- |
| HTTP请求 | 400    | 4222   | 4340   | 5206       | 5490       | 5841       | 244    | 6129   | 0.00%  | 20.62175 | 3.2         | 3.3         |
| 总体     | 400    | 4222   | 4340   | 5206       | 5490       | 5841       | 244    | 6129   | 0.00%  | 20.62175 | 3.2         | 3.3         |

3. 另一个 java seata 的 [demo](https://github.com/dk-lockdown/seata-demo2) 与 seata-golang 中的 demo 做了相同的操作，即通过一个聚合服务调用订单服务、再调用库存服务创建订单，通过 jmeter 对创建订单接口进行测试，测试结果如下：

java client 连接 java tc server (version 1.4，client 设置 LOCK_RETRY_POLICY_BRANCH_ROLLBACK_ON_CONFLICT 为 false )：

| Label    | # 样本 | 平均值 | 中位数 | 90% 百分位 | 95% 百分位 | 99% 百分位 | 最小值 | 最大值 | 异常 % | 吞吐量  | 接收 KB/sec | 发送 KB/sec |
| -------- | ------ | ------ | ------ | ---------- | ---------- | ---------- | ------ | ------ | ------ | ------- | ----------- | ----------- |
| HTTP请求 | 400    | 5357   | 5152   | 6401       | 7639       | 8980       | 2805   | 9301   | 0.00%  | 16.8691 | 3.48        | 2.93        |
| 总体     | 400    | 5357   | 5152   | 6401       | 7639       | 8980       | 2805   | 9301   | 0.00%  | 16.8691 | 3.48        | 2.93        |


4. java demo 连接 go tc server，该用例存在一些问题，下面的数据仅供参考，不参与此次对比：

| Label    | # 样本 | 平均值 | 中位数 | 90% 百分位 | 95% 百分位 | 99% 百分位 | 最小值 | 最大值 | 异常 % | 吞吐量  | 接收 KB/sec | 发送 KB/sec |
| -------- | ------ | ------ | ------ | ---------- | ---------- | ---------- | ------ | ------ | ------ | ------- | ----------- | ----------- |
| HTTP请求 | 1000   | 7990   | 2660   | 30033      | 31832      | 70188      | 96     | 115046 | 0.00%  | 8.55293 | 3.5         | 1.49        |
| 总体     | 1000   | 7990   | 2660   | 30033      | 31832      | 70188      | 96     | 115046 | 0.00%  | 8.55293 | 3.5         | 1.49        |

问题：seata-golang 和 java 连接机制不同：seata-golang client 端的 tm 和 rm 是共用的和 tc server 的连接（默认一个应用和 tc server 保持一条连接），在一个连接上既传递 tm 消息也传递 rm 消息；java 版 seata 设计的 tm 会和 tc server 建立一条连接，rm 也会和 tc server 建立一条连接，（默认一个应用和 tc server 保持两条连接）这导致了 ChannelManager 管理上的复杂，并且代码也比较难以理解，代码参见 [ChannelManager.go](https://github.com/seata/seata/blob/develop/core/src/main/java/io/seata/core/rpc/netty/ChannelManager.java)。此时创建了订单，在异步提交的时候，go tc server range 随机选择一条 java client 连接发送 BranchCommitRequest 消息，如果选中了 tm 创建的连接，会导致这个消息得不到处理。



#### 结论

综合上面的测试结果，go 和 java 性能差不多，在 java client LOCK_RETRY_POLICY_BRANCH_ROLLBACK_ON_CONFLICT 设置为 false 的情况下，go 性能更好。

**对于上述测试方法和测试结果如有任何疑问或建议，欢迎在钉钉群【seata-golang 社区】讨论。**

