当前位置: 首页 > 后端技术 > PHP

MySQLChallenge-Establishing100,000Connections

时间:2023-03-30 06:02:33 PHP

本文的目的是探索一种在一台MySQL服务器上建立100,000个连接的方法。我们要建立的是一个可以执行查询的连接,而不是10w个空闲连接。你可能会问,我的MySQL服务器真的需要10w个连接吗?我见过很多不同的部署方案,比如使用连接池,在每个应用程序的连接池中放1000个连接,部署100个这样的应用服务器。还有一些非常糟糕的做法,使用“如果查询速度慢则重新连接并重试”技术。这会产生滚雪球效应,可能会在几秒钟内建立数千个连接。于是我决定定一个“小目标”,看看能不能实现。在准备阶段,我们先来看一下硬件。服务器由packet.net(云服务提供商)提供,配置如下:实例大小:c2.medium.x86PhysicalCores@2.2GHz(1XAMDEPYC7401P)Memory:64GBofECCRAMStorage:INTEL?SSDDCS4500,480GB我们需要5台这样的服务器,一台用于MySQL服务器,另外4台用于客户端。MySQL服务器使用PerconaServer的MySQL8.0.13-4,带有线程池插件,需要支持上千连接。初始化服务器配置网络设置:-{name:'net.core.somaxconn',value:32768}-{name:'net.core.rmem_max',value:134217728}-{name:'net.core.wmem_max',值:134217728}-{名称:'net.ipv4.tcp_rmem',值:'409687380134217728'}-{名称:'net.ipv4.tcp_wmem',值:'409687380134217728'}-{名称:'net.core.netdev_max_backlog',价值:300000}-{名称:'net.ipv4.tcp_moderate_rcvbuf',价值:1}-{名称:'net.ipv4.tcp_no_metrics_save',价值:1}-{名称:'net.ipv4.tcp_congestion_control',value:'htcp'}-{name:'net.ipv4.tcp_mtu_probing',value:1}-{name:'net.ipv4.tcp_timestamps',value:0}-{name:'net.ipv4.tcp_sack',值:0}-{名称:'net.ipv4.tcp_syncookies',值:1}-{名称:'net.ipv4.tcp_max_syn_backlog',值:4096}-{名称:'net.ipv4.tcp_mem',值:'505766476898152'}-{名称:'net.ipv4.ip_local_port_range',值:'400065000'}-{名称:'net.ipv4.netdev_max_backlog',值:2500}-{名称:'net.ipv4.tcp_tw_reuse',value:1}-{name:'net.ipv4.tcp_fin_timeout',value:5}系统限制设置:[Service]LimitNOFILE=1000000LimitNPROC=500000对应的MySQL配置(my.cnf文件):back_log=3500max_connections=110000clientssysbench0使用.5版本而不是1.0.x。具体原因我们后面会解释。执行命令:sysbench--test=sysbench/tests/db/select.lua--mysql-host=139.178.82.47--mysql-user=sbtest--mysql-password=sbtest--oltp-tables-count=10--report-interval=1--num-threads=10000--max-time=300--max-requests=0--oltp-table-size=10000000--rand-type=uniform--rand-init=on第一步运行,10000个连接这一步很简单,我们不需要太多的调整就可以实现。这一步只需要一台机器作为客户端,但是客户端可能会报如下错误:FATAL:error2004:Can'tcreateTCP/IPsocket(24)这是由于打开文件数的限制,限制了TCP/IP的套接字数量可以在客户端调整:ulimit-n100000现在我们观察一下性能:[26s]threads:10000,tps:0.00,reads:33367.48,writes:0.00,responsetime:3681.42ms(95%),错误:0.00,重新连接:0.00[27s]线程:10000,tps:0.00,读取:33289.74,写入:0.00,响应时间:3690.25ms(95%),错误:0.00,重新连接:第二步,25,000connections这一步会导致MySQL服务器报错:Can'tcreateanewthread(errno11);如果您没有用完可用内存,则可以查阅手册以了解有关此问题的可能与操作系统相关的错误解决方案可以在此链接中找到:https://www.percona.com/blog/...但是这个方法不适用于我们目前的情况,因为我们已经将所有的限制都调整到了最高:cat/proc/`pidofmysqld`/LimitsLimitSoftLimitHardLimitsMaxCPUTINLIMEDUnlimitedSecondsMaxFileSizeUniversityack?size????????????8388608????unlimited????????????bytesMax?core?file?size????????0??????????unlimited????????????bytesMax?resident?set??????????unlimited??unlimited????????????bytesMax?processes?????????????500000?????500000???????????????processesMax?open?files????????????1000000????1000000??????????????filesMax?locked?memory?????????16777216???16777216?????????????bytesMax?address?space?????????unlimited??unlimited????????????bytesMax?file?locks????????????unlimited??unlimited????????????locksMax?pending?signals???????255051?????255051???????????????signalsMax?msgqueue?size?????????819200819200bytesmaxnice优先级00max实时优先级00max实时超时无限无限的US这这也为什么我们我们开始要要要选择:https://wwwww.percona.com/doc/p。中加上面下面这个设置,然后重新启动服务thread_handling=pool-of-threads查看一下结果[7s]threads:25000,tps:0.00,reads:33332.57,writes:0.00,responseti我:974.56ms(95%),错误:0.00,重新连接:0.00[8s]线程:25000,tps:0.00,读取:33187.01,写入:0.00,响应时间:979.24ms(95%),0n0connects,re0。:0.00吞吐量相同,但95%响应从3690毫秒下降到979毫秒。第三步,这里50000个连接,我们遇到了最大的挑战。第一次尝试建立5w连接时,sysbench报错:FATAL:error2003:Can'tconnecttoMySQLserveron'139.178.82.47'(99)Error(99)这个错误比较神秘,意思是指定的无法分配地址。这个问题是由于应用程序可以打开的端口数量限制引起的,我们的系统默认配置是:cat/proc/sys/net/ipv4/ip_local_port_range:3276860999这意味着我们只有28,231个可用端口(60999减去32768),or它是您可以建立到指定IP地址的最大TCP连接数。您可以在服务器端和客户端扩大此范围:echo400065000>/proc/sys/net/ipv4/ip_local_port_range这样我们可以建立61,000个连接,接近一个IP可用的最大端口数(65535)。这里的重点是,如果我们要达到10w个连接,就需要给MySQL服务器分配更多的IP地址,所以我给MySQL服务器分配了两个IP地址。解决了端口数问题后,我们遇到了一个新问题:sysbench0.5:多线程系统评估基准测试使用以下选项运行测试:线程数:50000FATAL:线程#32352的pthread_create()失败。errno=12(Cannotallocatememory)这个问题是sysbench的内存分配问题导致的。sysbench只能分配的内存只能创建32,351个连接。此问题在1.0.x版本中更为严重。Sysbench1.0.x限制Sysbench1.0.x版本使用不同的Lua编译器,这使得我们不可能创建超过4000个连接。所以看起来Sysbench比PerconaServer更早达到极限,所以我们需要使用更多的客户端。如果每个客户端最多有32351个连接,那么我们至少需要使用4个客户端才能达到10万个连接的目标。为了达到5w个连接,我们用了两台机器作为客户端,每台机器开了25000个线程。结果如下:[29s]threads:25000,tps:0.00,reads:16794.09,writes:0.00,responsetime:1799.63ms(95%),errors:0.00,reconnects:0.00[30s]threads:0,0,0.0tpsreads:16491.03,writes:0.00,responsetime:1800.70ms(95%),errors:0.00,reconnects:0.00吞吐量与上一步类似(总tps为16794*2=33588),但是性能降低,有95%的响应时间加倍。这是意料之中的,因为与上一步相比,我们将连接数增加了一倍。第四步,75000个连接这一步我们再增加一个服务器作为客户端,每个客户端也运行25000个线程。结果如下:[157s]threads:25000,tps:0.00,reads:11633.87,writes:0.00,responsetime:2651.76ms(95%),errors:0.00,reconnects:0.00[158s]threads:25000,0tpsreads:10783.09,writes:0.00,responsetime:2601.44ms(95%),errors:0.00,reconnects:0.00第五步,100000个连接终于到了,这一步也不难,只需要再打开一个客户端,同样运行25,000个线程。结果如下:[101s]threads:25000,tps:0.00,reads:8033.83,writes:0.00,responsetime:3320.21ms(95%),errors:0.00,reconnects:0.00[102s]threads:25000.0,tps:reads:8065.02,writes:0.00,responsetime:3405.77ms(95%),errors:0.00,reconnects:0.00throughput保持在32260(8065*4)的水平,95%的响应时间为3405ms。这里有一个很重要的事情,想必大家已经发现了,有线程的10w个连接的响应速度甚至比没有线程池的1w个连接的响应速度还要好。线程池使PerconaServer能够更有效地管理资源并提供更好的响应速度。结论10万连接数是可以实现的,还可以实现更多。实现这个目标有三个重要组成部分:PerconaServer的线程池正确的网络设置为MySQL服务器配置多个IP地址(每个IP限制65535个连接)附录最后粘贴完整的my.cnf文件[mysqld]datadir{{mysqldir}}ssl=0skip-log-binlog-error=error.log#建议禁用符号链接以防止各种安全风险200000table_open_cache_instances=64back_log=3500max_connections=110000#?filesinnodb_file_per_tableinnodb_log_file_size=15Ginnodb_log_files_in_group=2innodb_open_files=4000#?buffersinnodb_buffer_pool_size=?40Ginnodb_buffer_pool_instances=8innodb_log_buffer_size=64M#?tuneinnodb_doublewrite=?1innodb_thread_concurrency=0innodb_flush_log_at_trx_commit=?0innodb_flush_method=O_DIRECT_NO_FSYNCinnodb_max_dirty_pages_pct=90innodb_max_dirty_pages_pct_lwm=10innodb_lru_scan_depth=2048innodb_page_cleaners=4join_buffer_size=256Ksort_buffer_size=256Kinnodb_use_native_aio=1innodb_stats_persistent?=?1#innodb_spin_wait_delay=96innodb_adaptive_flushing?=?1innodb_flush_neighbors?=?0innodb_read_io_threads?=?16innodb_write_io_threads?=?16innodb_io_capacity=1500innodb_io_capacity_max=2500innodb_purge_threads=4innodb_adaptive_hash_index=0max_prepared_stmt_count=1000000innodb_monitor_enable?=?'%'performance_schema?=?ON点关注,不迷路好了各位,以上就是这篇文章本文的全部内容在这里。能在这里看到的,都是有才华的人。前面说过,PHP的技术点很多,就是因为太多了,所以我在这里整理成PDF和文档。需要的可以点击进入秘码:想了解更多可以访问【比大厂】优质PHP架构师教程目录,只要能看懂保证工资又上了一个台阶(持续更新中)。以上内容希望对大家有所帮助。很多PHPer在前进的过程中总会遇到一些问题和瓶颈。他们写了太多的业务代码,没有方向感。我不知道从哪里开始改进。是的这里我整理了一些资料,包括但不限于:分布式架构、高扩展性、高性能、高并发、服务器性能调优、TP6、laravel、YII2、Redis、Swoole、Swoft、Kafka、Mysql优化、shell脚本、需要进阶干货的可以免费分享Docker、微服务、Nginx等知识点给大家。有需要的可以加我的PHP技术交流群953224940