大并发下TCP内存消耗优化小记(86万并发业务正常服务)

2024-05-26 07:18

本文主要是介绍大并发下TCP内存消耗优化小记(86万并发业务正常服务),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

    最近在做一个大并发服务的测试(目前测到86万,当然有大量长连接,每天打的日志高到170多g,不打算继续测了),业务系统为反向代理ATS,服务的内容为动态域名,大部分的url很长,不过打开后的值只是0或1这样的标记。

    当服务器在几万并发时,一般不需要考虑TCP连接消耗内存的问题,但当服务器承载几十万并发时,会暴漏出各种的问题,因此不得不考虑TCP连接对内存资源的消耗,当然跑到86万的并发需要对业务系统、Centos做各种参数优化,牵涉面太多,今天只说TCP内存占用(由于线上系统干扰条件很多,无法特定的对某个参数去调试,只分享一下做过程的心得,抛砖引玉),出现的问题如下:


wKiom1bspJvBEOeHAABuFNFUs4I951.png

(内存不够用,kernel直接把ats的进程给杀掉了,然后out of socket memory)


wKiom1brzk-yZjfiAABDbo0h_z8458.png

 (跑着跑着,直接out of socket memory)


wKioL1bwpQeS0S8gAAAn85tOIXo230.png

(tsar的内存监控数据) 


    每一个TCP连接都会有对应的socket封装,而每个socket都要占用一个fd,现在的业务系统大都采用epoll的网络I/O模型,他可以高效的处理大批量socket句柄,而这个socket句柄的对应的TCP读写缓存再加上一个TCP控制块就是单个TCP连接所消耗的内存,当然这个读写缓存的大小是根据系统的需要动态变化的,和TCP的滑动窗口大小成正相关。

对于tcp能够使用多少缓存,centos是会有全局控制的,例如我线上的服务器(内存62G,有15个G做内存cache使用)。

 

TCP能够使用的内存:这三个值就是TCP使用内存的大小,单位是页,每个页是4K的大小,如下:


wKioL1brz0PycydHAAAJQKtWQW0638.png


这三个值分别代表

Low6179424   6179424*4/1024/1024大概23g

Pressure8239232 8239232*4/1024/1024大概31g

High12358848   echo 12358848*4/1024/1024大概47g

这个也是系统装后的默认取值,也就是说最大有47g75%的内存)可以用作TCP连接,这三个量也同时代表了三个阀值,TCP的使用小于第二个值时kernel不会有任何提示操作,当大于第二个值时进入压力模式,当高于第三个值时将不接受新的TCP连接,同时会报出“Out  of  socket memory”或者TCP:too many of orphaned sockets”。

 

TCP读缓存大小,单位是字节:第一个是最小值4K,第二个是默认值85K,第三个是最大值16M,如下:


wKioL1brz-vA-pohAAAJ6zc3ROE318.png


这个可以在sysctl.conf中net.ipv4.tcp_rmem中进行调整。

 

TCP写缓存大小,单位是字节:第一个是最小值4K,第二个是默认值64K,第三个是最大值16M,如下:


wKioL1brz_6gQCgPAAAMO0VkVyE066.png


这个可以在sysctl.conf中net.ipv4.tcp_wmem中进行调整。

 

    也就是说一个TCP在三次握手建立连接后,最小的内存消耗在8K左右,最大的内存消耗在32M左右,你可以通过MTU估算MSS,然后算出一个滑动窗口有多少个MSS。现在可以进行简单计算了,按照系统TCP的全局控制,有47个g可用作内存缓存,假设按照默认的读写缓存计算,一个TCP连接占用149K加1K的tcp控制块共150K的内存,那么系统能承受最大的并发为 47*1024*1024/150 = 32万,当然这只是理论,一个TCP连接占用的内存实际是大小混用的,根据传输的文件大小以及网络状况动态调整。那么当前是什么情况呢,是有很多的长连接,而且每个请求的数据都很小,也就是说很有大量TCP连接只占了10K左右的内存,所以可以尝试更大的并发。

 好了,我顺着思路往下想,“Out  of  socket memory”除了业务系统恶意丢弃请求、或者孤儿套接字太多、或者fd(已经优化的很大了,不存在)用完了,就可能是为新的soket分配内存资源内存不够用了,因为在之前测试到30万左右的连接的时候出过这个问题,查看内存基本跑满,当时是把ats的logbuffer改小(动态连接一个url有时到45K的长度,于是当时把log buffer改的特别大)后就不报了,后来继续跑到50万左右又报错了,内存基本跑满,后把内存cache从30G调到了15G,再腾出15G给TCP连接及其与资源使用,跑到70万左右又不行了,大量这个错误。因为当前内存使用的很杂,有ats的内存缓存,有大量的孤儿Orphan soket(占用64K左右内存),还有大量的没有释放的TCP连接,还有ats的log等线程使用的内存,七七八八算下来,TCP能使用的内存不多,长连接、小链接、大链接的比例也不好计算,只能按照经验去尝试,目前看跑到70万已经到头了吧。

可是后来又想,系统对于刚开始建连接的时候可能是默认的内存占用,之后再动态调整,按照当前域名质量情况,大多数都是小的不能再小的请求,我是否可以更改默认TCP的读写缓存呢,于是调整,读写默认缓存各变为原来的一半分别是43K和32K,第二天晚高峰检查,跑到86万,没有出现问题,好了到此为止,不再测了。


 wKiom1bsp33gERxMAAAom0_Ntus222.png


总结:其实系统单纯能跑多大并发在乎全局fd和内存,但大并发下还能继续保持业务正常服务就是技术活儿了,每个业务系统的参数、操作系统的参数都得琢磨尝试,其余方面的优化小记有空再写。


本文出自 “奔跑的linux” 博客,请务必保留此出处http://benpaozhe.blog.51cto.com/10239098/1752675

这篇关于大并发下TCP内存消耗优化小记(86万并发业务正常服务)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1003796

相关文章

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内

TP-Link PDDNS服将于务6月30日正式停运:用户需转向第三方DDNS服务

《TP-LinkPDDNS服将于务6月30日正式停运:用户需转向第三方DDNS服务》近期,路由器制造巨头普联(TP-Link)在用户群体中引发了一系列重要变动,上个月,公司发出了一则通知,明确要求所... 路由器厂商普联(TP-Link)上个月发布公告要求所有用户必须完成实名认证后才能继续使用普联提供的 D

Deepseek使用指南与提问优化策略方式

《Deepseek使用指南与提问优化策略方式》本文介绍了DeepSeek语义搜索引擎的核心功能、集成方法及优化提问策略,通过自然语言处理和机器学习提供精准搜索结果,适用于智能客服、知识库检索等领域... 目录序言1. DeepSeek 概述2. DeepSeek 的集成与使用2.1 DeepSeek API

Tomcat高效部署与性能优化方式

《Tomcat高效部署与性能优化方式》本文介绍了如何高效部署Tomcat并进行性能优化,以确保Web应用的稳定运行和高效响应,高效部署包括环境准备、安装Tomcat、配置Tomcat、部署应用和启动T... 目录Tomcat高效部署与性能优化一、引言二、Tomcat高效部署三、Tomcat性能优化总结Tom

解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)

《解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)》该文章介绍了使用Redis的阻塞队列和Stream流的消息队列来优化秒杀系统的方案,通过将秒杀流程拆分为两条流水线,使用Redi... 目录Redis秒杀优化方案(阻塞队列+Stream流的消息队列)什么是消息队列?消费者组的工作方式每

微服务架构之使用RabbitMQ进行异步处理方式

《微服务架构之使用RabbitMQ进行异步处理方式》本文介绍了RabbitMQ的基本概念、异步调用处理逻辑、RabbitMQ的基本使用方法以及在SpringBoot项目中使用RabbitMQ解决高并发... 目录一.什么是RabbitMQ?二.异步调用处理逻辑:三.RabbitMQ的基本使用1.安装2.架构

Linux内存泄露的原因排查和解决方案(内存管理方法)

《Linux内存泄露的原因排查和解决方案(内存管理方法)》文章主要介绍了运维团队在Linux处理LB服务内存暴涨、内存报警问题的过程,从发现问题、排查原因到制定解决方案,并从中学习了Linux内存管理... 目录一、问题二、排查过程三、解决方案四、内存管理方法1)linux内存寻址2)Linux分页机制3)

Java中使用Java Mail实现邮件服务功能示例

《Java中使用JavaMail实现邮件服务功能示例》:本文主要介绍Java中使用JavaMail实现邮件服务功能的相关资料,文章还提供了一个发送邮件的示例代码,包括创建参数类、邮件类和执行结... 目录前言一、历史背景二编程、pom依赖三、API说明(一)Session (会话)(二)Message编程客

Java循环创建对象内存溢出的解决方法

《Java循环创建对象内存溢出的解决方法》在Java中,如果在循环中不当地创建大量对象而不及时释放内存,很容易导致内存溢出(OutOfMemoryError),所以本文给大家介绍了Java循环创建对象... 目录问题1. 解决方案2. 示例代码2.1 原始版本(可能导致内存溢出)2.2 修改后的版本问题在