36

Tcp Rpc 踩坑实践

 5 years ago
source link: https://www.swoole.org.cn/index.php/archives/328/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

最近接到需求, 目前项目满足不了, 需要通过中间件实现.

经过讨论和分析, 最后打算 使用 swoole 构建一个 Tcp Rpc 服务.

正常的Rpc 轮子遍地都是 , 但是我们的需求很独特, 需要根据 参数 将请求分配至指定 进程 . 构建出一套 同步堵塞 的服务.

场景举例:

修改用户A的资产, 通过参数 `uid` 分配器将 请求发送至固定 进程. 使得用户资产都在单进程内排队更新.

上面的场景是很好实现的, 我们也已经在线上运行了一段时间, 基本告别了 过去的mysql 存储用户资产, 并发操作用户资产造成的死锁问题.

重点场景:

两个用户交易资产, 通过参数 `uid`, `bak_uid` 分配器将请求发送到固定 进程.....
显然不现实, 高并发场景下, 两个uid 分配到固定进程, 有些扯淡, 所以需要写个算法提供给两个uid 指定进程 `x`, 并且保证接下来的请求带有之前的参数都必须都往这个执行进程 `x` 打

第一个场景 单用户 进程分配方式固定 取模 即可实现

第二个场景 多用户 进程分配方式动态算法 实现 中间坑很多 但也最终实现, 但性能堪忧, 有待测试调优.

说下开发中的坑 技术选型 swoole go

因为是phper 所以默认选 swoole

使用swoole 的 自定义分配方法 dispatch_func 参数 实现 放在在这里相当于所有请求都经过这里, 这是一个分配进程的好地方.

之前使用 dispatch_func 方法 踩了 return -1; 的坑, 结果死循环, 前面文章有提到过.

在调优过程中 通过观察 server->stats 参数如下

[stats] => Array
    (
        [start_time] => 1544262210
        [connection_num] => 14889
        [accept_count] => 14889
        [close_count] => 0
        [tasking_num] => 0
        [request_count] => 518771
        [worker_request_count] => 5
    )

connection_num 当前连接数 竟然都没有释放

配合 netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' 查看 CLOSE_WAIT

TIME_WAIT 4969
CLOSE_WAIT 13494
ESTABLISHED 1045

果然大量客户端异常断链 导致服务端仍保持连接

问题解决 :

// 心跳相关                     https://wiki.swoole.com/wiki/page/284.html
    // 'heartbeat_idle_time' => 60,
    // 'heartbeat_check_interval' => 10,


    //  开启 TCP keepalive                          https://wiki.swoole.com/wiki/page/p-tcp_keepalive.html
    'open_tcp_keepalive' => 1,                      // 死连接检测
    'tcp_keepidle' => 60,                           // 单位秒,连接在n秒内没有数据请求,将开始对此连接进行探测。
    'tcp_keepcount' => 6,                           // 探测的次数,超过次数后将close此连接。
    'tcp_keepinterval' => 10,                       // 探测的间隔时间,单位秒。

使用 tcp keepalive 保持连接 客户端起定时器 ping 服务端即可 , 但使用同样定时ping的方法并不能有效维持连接 1分钟后连接全部断了;

未完待续...

最后更新于 2018-12-08 13:08:37 并被添加「swoole」标签,已有 2 位童鞋阅读过。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK