大并发下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

相关文章

sysmain服务可以禁用吗? 电脑sysmain服务关闭后的影响与操作指南

《sysmain服务可以禁用吗?电脑sysmain服务关闭后的影响与操作指南》在Windows系统中,SysMain服务(原名Superfetch)作为一个旨在提升系统性能的关键组件,一直备受用户关... 在使用 Windows 系统时,有时候真有点像在「开盲盒」。全新安装系统后的「默认设置」,往往并不尽编

Web服务器-Nginx-高并发问题

《Web服务器-Nginx-高并发问题》Nginx通过事件驱动、I/O多路复用和异步非阻塞技术高效处理高并发,结合动静分离和限流策略,提升性能与稳定性... 目录前言一、架构1. 原生多进程架构2. 事件驱动模型3. IO多路复用4. 异步非阻塞 I/O5. Nginx高并发配置实战二、动静分离1. 职责2

Redis实现高效内存管理的示例代码

《Redis实现高效内存管理的示例代码》Redis内存管理是其核心功能之一,为了高效地利用内存,Redis采用了多种技术和策略,如优化的数据结构、内存分配策略、内存回收、数据压缩等,下面就来详细的介绍... 目录1. 内存分配策略jemalloc 的使用2. 数据压缩和编码ziplist示例代码3. 优化的

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

Python 基于http.server模块实现简单http服务的代码举例

《Python基于http.server模块实现简单http服务的代码举例》Pythonhttp.server模块通过继承BaseHTTPRequestHandler处理HTTP请求,使用Threa... 目录测试环境代码实现相关介绍模块简介类及相关函数简介参考链接测试环境win11专业版python

Python实战之SEO优化自动化工具开发指南

《Python实战之SEO优化自动化工具开发指南》在数字化营销时代,搜索引擎优化(SEO)已成为网站获取流量的重要手段,本文将带您使用Python开发一套完整的SEO自动化工具,需要的可以了解下... 目录前言项目概述技术栈选择核心模块实现1. 关键词研究模块2. 网站技术seo检测模块3. 内容优化分析模

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

Java实现复杂查询优化的7个技巧小结

《Java实现复杂查询优化的7个技巧小结》在Java项目中,复杂查询是开发者面临的“硬骨头”,本文将通过7个实战技巧,结合代码示例和性能对比,手把手教你如何让复杂查询变得优雅,大家可以根据需求进行选择... 目录一、复杂查询的痛点:为何你的代码“又臭又长”1.1冗余变量与中间状态1.2重复查询与性能陷阱1.

Python内存优化的实战技巧分享

《Python内存优化的实战技巧分享》Python作为一门解释型语言,虽然在开发效率上有着显著优势,但在执行效率方面往往被诟病,然而,通过合理的内存优化策略,我们可以让Python程序的运行速度提升3... 目录前言python内存管理机制引用计数机制垃圾回收机制内存泄漏的常见原因1. 循环引用2. 全局变

Nginx中配置使用非默认80端口进行服务的完整指南

《Nginx中配置使用非默认80端口进行服务的完整指南》在实际生产环境中,我们经常需要将Nginx配置在其他端口上运行,本文将详细介绍如何在Nginx中配置使用非默认端口进行服务,希望对大家有所帮助... 目录一、为什么需要使用非默认端口二、配置Nginx使用非默认端口的基本方法2.1 修改listen指令