V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
haiyan
V2EX  ›  程序员

PHP 网站内存占用很高,一做活动就挂了,大佬们帮忙看看

  •  
  •   haiyan · 2019-07-16 09:03:49 +08:00 · 7400 次点击
    这是一个创建于 1708 天前的主题,其中的信息可能已经有所发展或是发生改变。
    服务器就一个小说网站,服务器阿里云的 2 核 4G 配置,mysql 数据库 1.5G ,日活 2000 这样,平时网站内存就占到了 80%多了,mysql 占了 20%。如果发个促销网址,人同时一上来就挂,实际那两分钟来的人也还不多 1000,必须重启 php-fpm 才行。同配置的.net 版系统就毫无压力,索引设置了,日志也看了,现在不知道是配置低了,还是程序性能太差了。
    请大家帮忙提点见解,谢谢了!
    74 条回复    2019-11-20 12:33:51 +08:00
    abccccabc
        1
    abccccabc  
       2019-07-16 09:09:32 +08:00   ❤️ 1
    你这是在 win 系统跑 PHP 吗??试下加缓存之类的。
    AngryPanda
        2
    AngryPanda  
       2019-07-16 09:11:31 +08:00 via Android   ❤️ 2
    我知道了,你是来黑 PHP 的
    AngryPanda
        3
    AngryPanda  
       2019-07-16 09:12:47 +08:00 via Android
    看一下 phpfpm 的 log
    chuhemiao
        4
    chuhemiao  
       2019-07-16 09:13:42 +08:00   ❤️ 1
    加个 cdn 和 rdb
    Dogergo
        5
    Dogergo  
       2019-07-16 09:14:00 +08:00   ❤️ 1
    代码有问题,大变量释放之类的
    hbolive
        6
    hbolive  
       2019-07-16 09:14:54 +08:00   ❤️ 1
    你这是单台服务器,所以重点检查下数据库,程序。
    所以可以检查下是哪些页面导致数据库负载太高,SHOW full PROCESSLIST,做好库表优化工作。。。
    程序的优化只能一点点排查了,也跟写程序的人有关系。。
    加入缓存系统。。
    lmaster
        7
    lmaster  
       2019-07-16 09:16:55 +08:00   ❤️ 1
    有篇博文介绍了 nginx+php ( http://zyan.cc/nginx_php_v4/),你看看是不是 nginx 进程太多导致,试试将 worker_processes 降低,然后你的服务器外网带宽是多少?
    kiwier
        8
    kiwier  
       2019-07-16 09:17:51 +08:00   ❤️ 1
    fpm 再不济,这一两千并发还是可以承受得住的
    tanszhe
        9
    tanszhe  
       2019-07-16 09:19:12 +08:00   ❤️ 1
    用的 laravel 吧
    Woood
        10
    Woood  
       2019-07-16 09:20:00 +08:00   ❤️ 1
    试下 swoole
    Woood
        11
    Woood  
       2019-07-16 09:21:17 +08:00
    2 分钟 1000,都扛不住,是有的参数没有设置吧,比如 app_debug 之类的
    haiyan
        12
    haiyan  
    OP
       2019-07-16 09:23:11 +08:00
    root 2696 0.0 0.2 39816 7816 ? Ss Jul15 0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
    www 2698 0.0 0.8 70536 33328 ? S Jul15 0:25 nginx: worker process
    www 2699 0.0 0.9 91016 35620 ? S Jul15 0:35 nginx: worker process
    mysql 4024 1.6 13.1 2156936 508640 ? Sl Jul15 17:17 /usr/local/mysql/bin/mysqld
    root 5569 0.0 0.3 551672 14788 ? Ss Jul15 0:01 php-fpm: master process
    www 5579 0.0 0.5 633356 21584 ? S Jul15 0:12 php-fpm: pool www
    php-fpm X 32 个
    haiyan
        13
    haiyan  
    OP
       2019-07-16 09:24:51 +08:00
    centos7 跑的,thinkphp 3 的框架,没用什么缓存,感觉没用也没什么影响,系统其实算起来很简单的了
    haiyan
        14
    haiyan  
    OP
       2019-07-16 09:29:45 +08:00
    挂了看 php 日志就是 connect() to unix:/dev/shm/php-cgi.sock failed (2: No such file or directory) while connecting to upstream 这个,max_children 设置到 100 了
    jsjscool
        15
    jsjscool  
       2019-07-16 09:30:41 +08:00   ❤️ 1
    装个 xhgui-branch 看看慢在哪
    justrand
        16
    justrand  
       2019-07-16 09:33:47 +08:00   ❤️ 1
    慢日志发上来看看。一般一个 fpm 进程 40M-60M
    haiyan
        17
    haiyan  
    OP
       2019-07-16 09:35:20 +08:00
    @hbolive
    @jsjscool 看了数据库日志,把慢的查询都优化了,还是那样
    haiyan
        18
    haiyan  
    OP
       2019-07-16 09:37:51 +08:00
    这个还不好测试并发,因为都要网站依赖微信登录,没有登录都调到了登录页面了
    components
        19
    components  
       2019-07-16 09:52:51 +08:00   ❤️ 1
    就一小说阅读站,为什么要用 MySQL,sqllite 足以!
    其实,你用 MySQL,就已经吃掉很大一半内存了
    lifeintools
        20
    lifeintools  
       2019-07-16 09:54:34 +08:00   ❤️ 1
    @haiyan 目测是需要参数调优。
    flashrick
        21
    flashrick  
       2019-07-16 10:05:55 +08:00   ❤️ 1
    @components 小说用 nosql 存吧,用 redis 都好,
    haiyan
        22
    haiyan  
    OP
       2019-07-16 10:12:40 +08:00
    @components
    @flashrick 心塞啊,.net 版的还是 win+iis+mssql 应该更占内存啊
    haiyan
        23
    haiyan  
    OP
       2019-07-16 10:12:59 +08:00
    @lifeintools 能否指点一下,哪里的参数
    jsjscool
        24
    jsjscool  
       2019-07-16 10:14:29 +08:00   ❤️ 1
    @haiyan 这明显不是数据库的问题,初步怀疑是哪个资源文件锁了。编程最好不要靠猜,https://github.com/laynefyc/xhgui-branch 装一下,分分钟解决问题。
    dafengchui
        25
    dafengchui  
       2019-07-16 10:14:51 +08:00   ❤️ 1
    其实我觉得估计用了 mysql 的默认配置, 优化下 mysql
    mumbler
        26
    mumbler  
       2019-07-16 10:22:23 +08:00 via Android   ❤️ 1
    遇到过同样问题,最后发现是 nginx 配置问题,并发设置太低
    haiyan
        27
    haiyan  
    OP
       2019-07-16 10:23:22 +08:00
    @jsjscool 学习一下,谢谢你
    HiCode
        28
    HiCode  
       2019-07-16 10:47:55 +08:00   ❤️ 1
    “服务器阿里云的 2 核 4G 配置,mysql 数据库 1.5G ,日活 2000 这样,平时网站内存就占到了 80%多了,mysql 占了 20%”


    我感觉代码问题挺大吧,“平时网站内存就占到了 80%多”,2000 日活,什么情况下会让 php 把内存都占了?

    楼主表述不正确,还是其他?
    haiyan
        29
    haiyan  
    OP
       2019-07-16 11:07:06 +08:00
    @HiCode
    看错了,对 linux 的不了解,实际是这样的
    物理内存:共 3.702 G , 已用 3.082 G , 空闲 0.62 G , 使用率 83.25%

    Cache 化内存为 2.058 G , 使用率 55.59 % | Buffers 缓冲为 0.15 G

    真实内存使用 0.874 G , 真实内存空闲 2.828 G , 使用率 23.6 %
    dongya
        30
    dongya  
       2019-07-16 11:09:00 +08:00   ❤️ 1
    @AngryPanda 哈哈, 你说对了
    kiwier
        31
    kiwier  
       2019-07-16 11:09:39 +08:00   ❤️ 1
    哥哥 tp3 该换了,漏洞太多,并且性能不行
    yc8332
        32
    yc8332  
       2019-07-16 11:10:09 +08:00   ❤️ 1
    就是你的 php 程序速度太慢了。。。并发大了就只能排队了。。。加更多 php 进程没用,数据库连接数是一个问题,还有就是 cpu 也忙不过来。。。还是要优化你的 php 程序。。
    Mazexal
        33
    Mazexal  
       2019-07-16 11:10:52 +08:00   ❤️ 2
    .net core 天下第一
    sggggy
        34
    sggggy  
       2019-07-16 11:11:25 +08:00   ❤️ 1
    初学 linux 的话建议安装 htop,用 htop 去看,不会因为不理解 top 的命令而心惊肉跳的。之前我也遇到老是有程序员问运维,为啥内存消耗这么高,要不要重启一下啥的…… windows 带来的理念。
    vincenttone
        35
    vincenttone  
       2019-07-16 11:14:16 +08:00   ❤️ 1
    看当时的连接时长和数量,关键部分添加日志(比如请求和响应时长、数据库连接时长、timewait 的情况),添加内存和 cpu 负载的监控。这样你才知道具体问题出在哪里,猜测没用。
    haiyan
        36
    haiyan  
    OP
       2019-07-16 11:17:26 +08:00
    @dongya
    @Mazexal 给 php 招黑了 🙈

    @kiwier 接手的项目,不是我开发的,换就是重新搞,搞不起啊
    HiCode
        37
    HiCode  
       2019-07-16 11:21:54 +08:00   ❤️ 1
    @haiyan

    这个内存使用率也偏高了,日活 2000,不是每分钟 2000,我建议是从内存占用入手。
    goodspb
        38
    goodspb  
       2019-07-16 12:53:30 +08:00   ❤️ 1
    和内存无关系。主要是 fpm 被耗尽了,先查一下 fpm 慢日志,看看是哪里导致的慢。临时的解决方案应该是调整一下 PM 的配置
    avenger
        39
    avenger  
       2019-07-16 12:56:42 +08:00 via iPhone   ❤️ 1
    phpfpm 配置贴一下
    azh7138m
        40
    azh7138m  
       2019-07-16 12:59:48 +08:00   ❤️ 1
    你可以考虑换 fpm 走 http 和 nginx 交互,代价是虽然能用户侧不会出现 50x,但是响应速度会变慢,实际 qps 可能会降低。
    还是要做好 profiling,看下是慢在哪里了。
    不过,2 分钟 单机 1k UV 其实很高了,一个 UV 毕竟对应了不少业务。
    Snail233
        41
    Snail233  
       2019-07-16 13:11:31 +08:00   ❤️ 1
    @Woood 哈哈哈哈,用的 laravel 吧,哈哈哈哈哈哈哈
    Snail233
        42
    Snail233  
       2019-07-16 13:11:46 +08:00
    @tanszhe 哈哈哈哈,用的 laravel 吧,哈哈哈哈哈哈哈
    opengps
        43
    opengps  
       2019-07-16 13:52:18 +08:00   ❤️ 1
    2 分钟 1000,这是很高的并发了,居然还用单机承载,而且是云服务器的硬盘
    haiyan
        44
    haiyan  
    OP
       2019-07-16 13:57:14 +08:00
    @avenger
    pm = dynamic
    pm.max_children = 100
    pm.start_servers = 30
    pm.min_spare_servers = 20
    pm.max_spare_servers = 70
    pm.max_requests = 2048
    pm.process_idle_timeout = 10s
    request_terminate_timeout = 120
    request_slowlog_timeout = 0
    ragnaroks
        45
    ragnaroks  
       2019-07-16 14:44:13 +08:00   ❤️ 1
    那就别用 php 了啊...你都用上.net 了,直接升级成.net core 呗,2c4g 抗 1w 并发不是轻轻松松?
    haiyan
        46
    haiyan  
    OP
       2019-07-16 15:16:01 +08:00
    @ragnaroks 系统在用着
    haiyan
        47
    haiyan  
    OP
       2019-07-16 15:16:26 +08:00
    @jsjscool 装了半天了还是没有装成功
    jswh
        48
    jswh  
       2019-07-16 15:18:39 +08:00   ❤️ 1
    看错了,对 linux 的不了解,实际是这样的
    物理内存:共 3.702 G , 已用 3.082 G , 空闲 0.62 G , 使用率 83.25%

    Cache 化内存为 2.058 G , 使用率 55.59 % | Buffers 缓冲为 0.15 G

    真实内存使用 0.874 G , 真实内存空闲 2.828 G , 使用率 23.6 %
    ============================
    另外你 2 核心 4G 服务器,这个 php-fpm 设置得有点高了,可以稍微小一点,毕竟 mysql 也是内存大户。


    Linux 要看实际使用内存,不要把 buffer/cache 算上。和 Windows 策略不一样
    jswh
        49
    jswh  
       2019-07-16 15:19:36 +08:00
    @jswh 补充一下,如果还在用 php5.*建议尽快升级到 7.*
    caryqy
        50
    caryqy  
       2019-07-16 15:21:54 +08:00   ❤️ 1
    暂时解决不了的话就加硬件配置
    avenger
        51
    avenger  
       2019-07-16 16:03:18 +08:00   ❤️ 1
    @haiyan 我贴一个我们产品服务器的配置,服务器也是 2 核 4G,高峰的时候,并发 1000,服务器都没啥压力,用的是 Laravel php7.2,开了 opcache,你参考一下,不过我们数据库是分开的,用的单独的阿里云 RDS

    ```
    pm = static
    pm.max_children = 300
    pm.start_servers = 20
    pm.min_spare_servers = 5
    pm.max_spare_servers = 50
    ;pm.process_idle_timeout = 10s
    pm.max_requests = 5000
    ```

    另外,建议服务器有压力的时候开启一下 php-fpm status 看一下具体的情况,这是一个成长的机会。
    avenger
        52
    avenger  
       2019-07-16 16:12:11 +08:00
    @haiyan 又去看了下,我们的服务器是 2 核 8g 内存,ssd 硬盘
    jsjscool
        53
    jsjscool  
       2019-07-16 16:22:59 +08:00   ❤️ 1
    @haiyan 报啥错?走到哪一步了?
    qsbaq
        54
    qsbaq  
       2019-07-16 16:26:51 +08:00   ❤️ 1
    @haiyan 配置成 static,然后上个 opcache。
    lifeintools
        55
    lifeintools  
       2019-07-16 17:11:19 +08:00   ❤️ 1
    @jsjscool 他的 PHP 水平 你让他安装个插件 太难为他了。不然 就 nginx 和 fpm 参数调优。
    haiyan
        56
    haiyan  
    OP
       2019-07-16 17:42:33 +08:00
    @jsjscool git clone https://github.com/laynefyc/xhgui-branch.git
    cd xhgui-branch
    php install.php 这一步中途提示:github 连接超时
    qinxi
        57
    qinxi  
       2019-07-16 18:07:41 +08:00   ❤️ 1
    建议用 Java ,同时招聘 https://www.v2ex.com/t/583148 这个同学
    wangzz223
        58
    wangzz223  
       2019-07-16 18:17:16 +08:00   ❤️ 1
    搞点缓存挡挡...都打到 mysql 上,服务并发不会很好..
    能异步化处理的异步化处理.
    yufeng0681
        59
    yufeng0681  
       2019-07-16 18:25:05 +08:00   ❤️ 1
    打日志,分段跟踪:
    1、压力测试,数据库是否有问题
    2、压力测试,web 响应是否有问题
    3、压力中,将某一段逻辑拿掉测试性能( 1、拿掉数据库代码直接返回; 2、拿掉业务处理代码直接回 html )

    小说业务有热门数据概念,最好上缓存,提高响应速度,减少数据库压力。虽然不知道你的小说是图片还是文字类的
    codespots
        60
    codespots  
       2019-07-16 18:34:31 +08:00   ❤️ 1
    @ragnaroks 你是在黑 PHP 还是在黑 .net core
    yumenoks
        61
    yumenoks  
       2019-07-16 18:36:51 +08:00   ❤️ 1
    上服务器吧,一个月 300 左右的,
    然后把数据库分离出来,丢到阿里云啥的,
    服务器可以弄 2 台,或者 1 台多 IP,然后开 1 台 linux 跑 web,一台 window 跑关关采集.
    看你自己的预算了.
    1981
        62
    1981  
       2019-07-16 19:00:17 +08:00   ❤️ 1
    个人建议把数据库分开来,我 10m 的数据库都卡卡卡卡卡卡卡
    encro
        63
    encro  
       2019-07-16 20:47:30 +08:00   ❤️ 1
    可以帮你解决,服务费 2000 元。
    也可以自己看我这篇日志吧:
    https://c4ys.com/archives/1609

    PHP 是进程模式的,1000 个并发,那么需要的 cpu 和内存你这配置确实不够。(没有用 swoole 之类的话)
    1000*10M 大约,大约需要 10G 内存。
    通常都没有 1000 个并发,估计数据库先挂了,挂的原因可能是慢 SQL,导致进程卡住一直上涨,连接不释放内存爆掉,或者连接数超过上线,套路云默认 5000。

    提示:
    nginx 开启 request_time;
    php-fpm 慢日志
    mysql 慢日志
    php-fpm 错误日志
    nginx 错误日志
    php 进程数
    mysql 连接数
    nginx 连接数

    以上文字价值 5000
    encro
        64
    encro  
       2019-07-16 20:57:02 +08:00   ❤️ 1
    request_terminate_timeout = 120
    request_slowlog_timeout = 0

    request_terminate_timeout 和 nginx 的 timeout 配置冲突,导致 nginx 主动断开,php 不回收,然后就会 not such file。

    google 下这个错误,就会发现答案的。
    如果百度的话,我可以保证没有一个是对的。
    ginjedoad
        65
    ginjedoad  
       2019-07-16 21:02:35 +08:00   ❤️ 1
    golang 重构一下,4 台一样的配置的机器,百万并发支持。
    encro
        66
    encro  
       2019-07-16 21:11:45 +08:00   ❤️ 1
    通常我用 Yii 框架,一个请求大约是 10-50ms,100 个进程( static 模式),1 分钟理论上支持的请求数是 1000*100/50=2000。
    caoyouming
        67
    caoyouming  
       2019-07-16 21:43:17 +08:00 via Android   ❤️ 1
    我在学校做的那个选课系统,单次选课人数最多可达到 5000 左右,并没有感到有压力呀。我用的也是单服务器,apache+mysql+php,对,服务器也是 winserver,我记得我开始做这个项目时候有一次也遇到类似的问题,改了 apache 的配置文件,包括连接数等等之后就没有这样的问题了。你可以看看你的服务器配置文件,找个懂配置文件的看看就行了。
    jhdxr
        68
    jhdxr  
       2019-07-16 21:48:21 +08:00   ❤️ 2
    @Snail233 laravel 也没那么不堪。。。

    小说网站能卡成这样多半是程序没写好。说不定在循环里写个 sql 查询之类的。。。

    另外拿别的语言比较的多半没用意义。换语言本身就是一个重构过程,你换的过程中又不会一句一句去翻译,肯定会解决原来的一些不合理之处。
    akira
        69
    akira  
       2019-07-17 00:59:10 +08:00   ❤️ 1
    方案 1. 每个月多花几百块 升级下服务器
    方案 2. 付费找人帮忙优化服务器
    方案 3. 自学服务器优化相关技能并完成优化工作
    ragnaroks
        70
    ragnaroks  
       2019-07-17 08:38:46 +08:00   ❤️ 1
    haiyan
        71
    haiyan  
    OP
       2019-07-17 09:01:03 +08:00
    一早来这么多回复,很感谢大家,指了很多方向,够我去了解的了。
    这个网站不着急马上解决,只要不发促销就行了😺。
    我看了代码,基本上压力在这几个:
    1,推送,每 5 分钟查询前 5 分钟未付款的订单,订单表 3 万多数据,查出来后循环发送;
    2,十几个推广在用着后台,生成二维码推广海报,时不时刷下各种统计;
    3,前台小说章节目录,是个大变量,两千多章节全部都是显示;
    4,登录和状态检查,通过子域名区分是谁的客户,用户表 40 多万,这个操作繁琐。
    我准备先去加缓存,推送换成队列,后续把优化结果发出来。
    flashrick
        72
    flashrick  
       2019-07-17 10:16:28 +08:00
    @haiyan 这 4 条都可以用 redis 解决 手动狗头
    haiyan
        73
    haiyan  
    OP
       2019-07-22 09:32:53 +08:00
    回来更新下,上周改完之后,终于可以顶住了。
    基本就是把上面的,1,4 两点改成用 redis 缓存实现,网站首页很少变化的也放缓存,微信获取 access_token 也放缓存,查询数据库量大大减少了,看来是 mysql 堵塞了。
    再次感谢各位帮助,学到了很多。
    CODEWEA
        74
    CODEWEA  
       2019-11-20 12:33:51 +08:00
    for 循环 mysql ?,果然是来黑 php 的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5362 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 03:46 · PVG 11:46 · LAX 20:46 · JFK 23:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.