记一次优化基于ThriftJ的RPC调用优化过程

原创
2023/07/13 17:24
阅读数 70

 

我们是自己手撸的一套微服务框架,RPC调用基于ThriftJ,服务注册与发现使用ZooKeeper。访问控制ZooKeeper基于CuratorFramework。

以上是项目背景。

1、问题描述:项目本来是一个分布式的项目,需要3台zk做一个集群,后台服务程序最少3台做集群。然后用nginx做负载均衡转发。但是有一个客户因为暂时服务器资源未到位,只能勉强在一台机器上安装zk,后台服务程序。然后就遇到程序在运行一会儿后,出现一定量的ThriftJ网络调用抛出来的Read Timeout的异常。然后就必须重启后台程序。

2、问题猜测:因为在集群模式下未发现这个异常。但单机就发现异常了。于是怀疑是访问量大,ThriftJ在调用callRemoteMethod的方法时候,出现网络阻塞引起的网络超时。

3、定位问题:使用JMeter做压力测试,开100个线程,重复100次,跑一会儿就开始出现一些请求报Read Timeout异常。使用netstat -na命令查看rpc服务器端监听端口(默认是8500),发现大量的TIME_WAIT状态的网络连接。于是想到缩短TIME_WAIT的释放时间,及时释放出来可用端口。

3.1、针对3的问题,解决方法如下:

3.1.1:Linux系统做如下修改:

# vi /etc/sysctl.conf  //加入以下内容,net.ipv4.tcp_syncookies默认就有,不需要再添加
# Controls the use of TCP syncookies
net.ipv4.tcp_syncookies = 1

# The TIME-WAIT sockets for new connections can be reused
net.ipv4.tcp_tw_reuse = 1

# Enable fast recycling of TIME-WAIT sockets status
net.ipv4.tcp_tw_recycle = 1

# Decrease the time default value for tcp_fin_timeout connection
net.ipv4.tcp_fin_timeout = 30

然后执行 /sbin/sysctl -p 让参数生效

/sbin/sysctl -p

 3.1.2:Windows系统做如下修改:

在HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters,添加名为TcpTimedWaitDelay的
DWORD键,设置为30,最短30秒,以缩短TIME_WAIT的等待时间。

4:再次深入:经过上述第三步的操作,问题得到改善,但情况并不乐观。继续翻看ThriftJ的相关API,我使用的是TNonblockingServerTransport创建Transport,然后使用TThreadedSelectorServer创建TServer。其中,TThreadedSelectorServer.Args里提供了如下几个方法:

// 配置selector线程池线程个数
tArgs.selectorThreads(4);
// 配置worker线程池线程个数
tArgs.workerThreads(Runtime.getRuntime().availableProcessors() * 2);
// 设置新建的connection处理策略
tArgs.acceptPolicy(TThreadedSelectorServer.Args.AcceptPolicy.FAST_ACCEPT);
// 每个selector线程接收新建connection的队列容量
tArgs.acceptQueueSizePerThread(8);

上诉几个方法明显增加ThriftJ的吞吐量的。毫不犹豫增加进去。

5:问题得到明显提升:经过上述优化,现在单机用jmeter做压力测试100线程,间隔1秒,重复100测,能正常完成所有调用。问题得到改善。

6:其他问题:在使用100线程重复100次做压测的时候,还出现了zk的too many connections的异常,这种情况,需要到zk的配置文件里修改如下配置:

maxClientCnxns=1000

或则

maxClientCnxns=0 

表示不限制连接数

 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部