终于发现hu60.cn内存不足的真相了:无论是否使用,宝塔安装的php都会占内存

@Ta 07-22 21:43发布,07-22 21:47修改 29827点击
  1. 在宝塔里安装的PHP版本,无论是否有网站使用都会保持运行。
  2. 宝塔给PHP的默认最大进程数是150。
  3. 我之前安装了PHP 8.3,只部署在了 dev.hu60.cn 上(仅我可访问),然后发现它与 hu60 程序不兼容,就放着没管了。
  4. 后来我发现php 8.3启动了很多进程导致内存不足,于是把 dev.hu60.cn 换回8.1了。我以为问题已经解决了。
  5. 结果不知道为什么,php 8.3在完全没有被使用的情况下,进程数不断缓慢增长直到150个,这个增长周期长达一天,所以每次都是早上重启系统,然后第二天早上内存不足卡顿。
  6. 把最大进程数调为10应该可以解决问题。不过我已经不想用8.3了,已经把它彻底卸载了,明天应该不会再卡顿了。
  7. 为什么以前没出问题?以前我确实也有一个闲置的php 8.0版本,但我把它的最大进程调成了10,所以没占用太多内存。不过今天发现无论是否使用它都会占内存之后,已经把它卸载了。
  8. 看起来内存不足问题与数据库完全无关,因为我之前减小mysql的最大内存限制也完全没有缓解问题。现在我已经把mysql的内存限制还原了,有更多内存缓存可以让搜索速度更快。
回复列表(19|隐藏机器人聊天)
  • @Ta / 07-22 21:53 / /

    沙发

  • @Ta / 07-22 22:00 / /

    vps内存是多少?
    一加ace2Pro(灰|24+1024)

  • @Ta / 07-22 22:11 / /

    @老虎会游泳,PHP 是每个进程,同时处理一个请求吗?

    然后认为,大多数时候,都在处理 IO(数据库/网络/文件……),

    所以开了十几倍 CPU 核心数量的进程,以提高 QPS/TPS?(老虎有测过,网站 QPS/TPS 吗?)

  • @Ta / 07-22 22:19 / /
    1:  可以加大内存
    2: 每次不能访问了都要微信找你,把你都搞烦了
  • @Ta / 07-22 23:53 / /
  • @Ta / 07-22 23:53 / /

    @无名啊,嗯,每个进程处理一个请求,进程数就是并发连接数

  • @Ta / 07-23 01:38 / /
    欢迎老虎用Go重写葫芦林 
  • @Ta / 07-23 02:30 / /
    所以现在虎绿林的php版本是?
    主要是,我要紧跟虎绿林的php版本走,
  • @Ta / 07-23 08:09 / /
    真相大白了
  • @Ta / 07-23 09:27 / /
  • @Ta / 07-23 16:40 / /

    @大药瓶子,Go 的 ORM 好用吗?

  • @Ta / 08-05 01:53 / /
    PHP 8.3 惹的祸?
  • @Ta / 08-06 09:28 / /

    @大尨,对,但主要还是宝塔的默认进程数给的太高了。

  • @Ta / 08-25 22:46 / /
    以前还在上学的时候还尝试着弄过,现在真干程序员了却没啥折腾的欲望了。
  • @Ta / 08-30 22:38 / /

    @老虎会游泳,我写了一些脚本,利用去年隔壁 v2 论坛千万帖子数据,在机械硬盘上,测试了 SQLite 并发能力:

    更新

    • [08-30 22:38]:全文索引加上主帖内容,写请求从 800 RPS 掉到 700 了。。

    结果

    (读写请求,用两个 wrk 同时进行。末尾附上运行过程)

    • 700 写请求/秒:新增用户信息/帖子数据/回帖数据 + 全文索引 (新增帖子/回帖时。效果 + 计算该帖总回复数(新增帖子/回帖时)

      1. 测试时,按创建用户/帖子/回复的时间顺序,并发请求。
    • 4000 读请求/秒:读取某个帖子及其所有回帖的所有数据,以 json 形式响应。

      1. 仅请求已完结的帖子。(所有回复已添加进服务端数据库)
      2. 以帖子点击数,作为概率,加权随机不放回地抽取,服务端数据库里,已完结的帖子。(一般点击数越高,回帖数量也越多)

    环境

    • CPU:i7-4790(看 gb6 跑分,论单核,和 i5-8250u 差不多。是 i3-12100 的 57%)
    • 内存:16 GB,DDR3,1600 MHz
    • 系统:Ubuntu 24.04
    • 服务端:Python 3.12,FastAPI,双进程(2 workers),运行时总共 100 MB 内存左右
    • 测试时服务端数据库
      • 大小:5.0 GB
      • 用户数:32.8 W
      • 帖子数:79.7 W
      • 回帖数:1062.3 W
    • 硬盘
      image.webp(21.93 KB)

    缺点

    • 断电可能丢失少量数据

      操作系统崩溃/断电时,可能会损失少量数据。但可以维持原子性、一致性。

    • 落盘几千个事务时,会卡 0.5 秒

      几千个事务后,会在一个事务强制将预写日志,刷新回数据库。(否则日志无限增长,读取速度下降)

      但该事务需要等待:

      1. 在此事务前的所有读事务完成。(否则隔离性有问题,会不可重复读)
      2. 将以往几千个事务脏页数据,大量随机写回数据库。(测试时需要 0.5 秒左右)

      因此:

      1. 不能持续开着一个数据库连接,惰性获取数据进行响应。(如全文搜索后,按用户下拉速度,流式响应游标结果)
      2. 回写数据库时,后续写请求会被阻塞。

      改进方向:

      1. SQLite 官方有个开发了 7 年的 WAL2 分支,可在写满一个 WAL 后,立即转向第二个。
        只要第一个 WAL 所有读事务完毕,就可立即全部写回数据库(大大延长了读事务持续时间,但还是不能无限),且此时不会阻塞后续写事务。
        但该分支一直未被合并回主分支,可能有不稳定的风险。
    • 写事务串行,需最快速度完成

      本质上,SQLite 的并行写事务数仍是 1,因此每个写请求都需要尽可能快处理,否则后续写请求都会被拖慢,降低 RPS。

      改进方向:

      1. SQLite 官方有个开发了 9 年的 begin-concurrent 分支,允许多个事务,同时写入不同的页面。
        若提交时,读取/写入过的页号被其他事务修改过,回滚重来。(类似 redis 的事务)
        同上,该分支一直未被合并回主分支,可能有不稳定的风险。
    • FastAPI 服务端,需要读写请求分离

      一个 worker 专心处理写请求,其他 workers 处理读请求。

      原因:

      1. SQLite 只支持 1 个并行写事务,且自带的阻塞重试机制效率低下,需要外部互斥锁保证,任何时刻只有一个写请求在进行。
      2. Python 的 GIL 很慢,不能使用多线程。
      3. 多进程方案,可以使用 redis 锁来实现。但需要使用异步,等待获得写请求锁期间,去处理读请求。(否则绝大部分 workers 都阻塞在等写锁时)
      4. 然而,Python 的事件循环,是公平调度。在等 redis 锁时,会先去完成本次调度的其他几十个读请求。下一轮循环,才拿到锁。
        但实际上,可能处理第二个读请求时,redis 就上锁成功。导致其他 workers 的写请求,也要被迫额外等待几十个读请求完成。。
      5. 我还没完美实现,基于优先级的事件循环调度。。(为啥就没个包干这种事啊。。nodejs、PHP 好像也不支持。。)

    测试过程

    1. 写请求

      $ wrk -s test.lua --latency -t1 -d30 -c100 http://127.0.0.1:8081 -- write
      [22:24:42]  INFO  启动写入脚本
      Running 30s test @ http://127.0.0.1:8081
        1 threads and 100 connections
        Thread Stats   Avg      Stdev     Max   +/- Stdev
          Latency   221.29ms  237.46ms   1.98s    79.97%
          Req/Sec     1.25k   684.68     2.37k    51.41%
        Latency Distribution
           50%   66.50ms
           75%  382.95ms
           90%  622.55ms
           99%  806.51ms
        20453 requests in 30.06s, 4.90MB read
        Socket errors: connect 0, read 0, write 0, timeout 5
      Requests/sec:    680.47
      Transfer/sec:    167.06KB
      
    2. 读请求

      $ wrk -s test.lua --latency -t1 -d30 -c100 http://127.0.0.1:8080
      [22:24:43]  INFO  启动读取脚本
      Running 30s test @ http://127.0.0.1:8080
        1 threads and 100 connections
        Thread Stats   Avg      Stdev     Max   +/- Stdev
          Latency    22.74ms   12.94ms 369.21ms   98.69%
          Req/Sec     4.24k   429.51     4.64k    90.88%
        Latency Distribution
           50%   21.47ms
           75%   22.67ms
           90%   24.43ms
           99%   70.82ms
        126055 requests in 30.03s, 193.80MB read
      Requests/sec:   4197.77
      Transfer/sec:      6.45MB
      
  • @Ta / 08-31 01:21 / /

    @老虎会游泳,你知道 Armbian 怎么挂载 Android 的文件系统吗?

    我有个几十块的 CM311-1A 电视盒子,想用它测测 15 楼的并发能力。

    (这货芯片性能应该和 J1900 差不多?四核 Nginx 默认页,压测有 4W QPS)

  • @Ta / 08-31 11:00 / /
    1panel试试?
  • @Ta / 08-31 11:01 / /
    @穴儿,肛
  • @Ta / 09-02 00:56 / /

    @老虎会游泳,我又用 CM311-1A 电视盒子,测试了千万数据论坛在 SQLite 上的并发能力:

    更新

    • [09-02 00:51]
      1. 区分轻中程度,写请求并发能力。
      2. 补充个和 6 年前千元机性能对比。

    结果

    (用两个 wrk同时进行读写请求。即,➀➁ 或 ➀➂)

    • 1100 获取整帖/秒/三进程:包括回帖人所有信息等。返回 json。
    • 300 注册用户/秒/进程:代表普通数据写并发数量。
    • 200 发帖回帖/秒/进程:包括全文索引 效果 + 该帖回复数。

    环境

    • CPU:晶晨 S905L3A

      • 压测单核 Nginx 默认页,1.0W QPS。可能和 J1900 差不多?
      • 压测单核 Nginx 默认页,2.2W QPS,高通 636。
    • 内存:2 GB

    • 功耗:2 ~ 3 W

    • 系统:Armbian 24.8.0 noble 6.1.100

    • 服务端:Python 3.12,FastAPI,四进程(4 workers),压测时 200 MB 内存

    • 测试时服务端数据库

      • 大小:4.7 GB
      • 用户数:34.5 W
      • 帖子数:75.4 W
      • 回帖数:1001.6 W
    • 存储

      image.webp(22.19 KB)

    测试过程

    1. 获取整帖请求

      $ wrk -s test.lua --latency -t1 -d30 -c100 http://192.168.1.8:8080
      [00:03:43]  INFO  启动读取整帖脚本
      Running 30s test @ http://192.168.1.8:8080
        1 threads and 100 connections
        Thread Stats   Avg      Stdev     Max   +/- Stdev
          Latency    85.74ms   32.75ms 874.56ms   98.14%
          Req/Sec     1.13k   141.22     1.52k    77.66%
        Latency Distribution
           50%   82.90ms
           75%   92.17ms
           90%   97.29ms
           99%  116.91ms
        33742 requests in 30.01s, 81.59MB read
      Requests/sec:   1124.43
      Transfer/sec:      2.72MB
      
    2. 注册用户请求

      $ wrk -s test.lua --latency -t1 -d30 -c100 http://192.168.1.8:8081 -- user
      [00:03:42]  INFO  启动注册用户脚本
      Running 30s test @ http://192.168.1.8:8081
        1 threads and 100 connections
        Thread Stats   Avg      Stdev     Max   +/- Stdev
          Latency   309.43ms  124.90ms   1.94s    84.28%
          Req/Sec   309.40    100.59   524.00     71.36%
        Latency Distribution
           50%  311.17ms
           75%  330.83ms
           90%  354.10ms
           99%  839.12ms
        8531 requests in 30.04s, 1.61MB read
        Socket errors: connect 0, read 0, write 0, timeout 50
      Requests/sec:    284.03
      Transfer/sec:     55.00KB
      
    3. 发帖回帖请求

      $ wrk -s test.lua --latency -t1 -d30 -c100 http://192.168.1.8:8081 -- post
      [00:22:44]  INFO  启动发帖回帖脚本
      Running 30s test @ http://192.168.1.8:8081
        1 threads and 100 connections
        Thread Stats   Avg      Stdev     Max   +/- Stdev
          Latency   411.50ms  194.28ms   1.94s    81.43%
          Req/Sec   228.08     73.82   490.00     77.99%
        Latency Distribution
           50%  400.31ms
           75%  433.54ms
           90%  540.13ms
           99%    1.03s 
        6127 requests in 30.01s, 1.47MB read
        Socket errors: connect 0, read 0, write 0, timeout 60
      Requests/sec:    204.16
      Transfer/sec:     50.15KB
      
添加新回复
回复需要登录