Tcp Rpc 踩坑实践

综合技术 2018-12-08 阅读原文

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

经过讨论和分析, 最后打算 使用 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 位童鞋阅读过。

责编内容by:奔赴de博客 【阅读原文】。感谢您的支持!

您可能感兴趣的

RabbitMQ教程C#版 – 远程过程调用(RPC)... 先决条件 本教程假定 RabbitMQ 已经安装,并运行在 localhost 标准端口(5672)。如果你使用不同的主机、端口或证书,则需要调整连接设置。 从哪里获得帮助 如果您在阅读本教程时遇到困难,可以...
Python – cql – Cassandra 1.... I have a Python application using a Cassandra 1.2 cluster. The cluster has 7 physical nodes using virtual nodes, and a r...
socket心跳超时检测,快速处理新思路(适用于超大量TCP连接情况下)... 假设一种情景: TCP服务器有1万个客户端连接,如果客户端5秒钟不发数据,则要断开。服务端如何检测客户端是否超时?这看起来是一个非常简单的问题,其实不然! 最简单的处理方法是:启动一个线程,每隔一段时间,检查每个连接是否超时。...
Go语言实现RPC RPC定义,来源于百度百科 RPC(Remote Procedure Call)— 远程过程调用 ,它是一种通过 网络 从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。 RPC协议 假定某些 传输协议 的存在,如...
Linux TCP通信出现CLOSE_WAIT后导致服务端进程挂掉... 在前文中讲述了Linux服务端TCP通信出现 CLOSE_WAIT 状态的原因,这篇文章主要通过一个实例演示它个一个“恶劣”影响:直接使服务端进程Down掉。 1 CentOS服务端建立监听端口 如上图所示,在虚拟机...