windows 服务器下的 apache 出现 MemoryError (django wsgi )

用django开发的一个老项目,开发时版本是0.9 , 后期服务器迁移多次,现在django版本用的1.2,用的apache 配合 wsgi模块搭建,原来服务器是linux,目前移到了 windows server 2012 配置是 2 cpu, 8g mem

昨天客户说服务器出问题了,访问时出现 500错误,internal server error

登录到服务器,打开apache的日志,发现和以前的不一样,并没有指出程序什么地方出错,截取一段如下

[Fri Sep 22 09:38:02 2029] [error] [client xxx.xxx.xxx.xxx]     args[0] = force_unicode(args[0]), referer: http://xx.xxx.xx.xx/xxxx/xxxx/index/
[Fri Sep 22 09:38:02 2029] [error] [client xxx.xxx.xxx.xxx]   File "D:\\Python27\\lib\\site-packages\\django\\utils\\encoding.py", line 85, in force_unicode, referer: http://xx.xxx.xx.xx/xxxx/index/
[Fri Sep 22 09:38:02 2029] [error] [client xxx.xxx.xxx.xxx]     s = s.decode(encoding, errors), referer: http://xx.xxx.xx.xx/xxxx/xxxx/index/
[Fri Sep 22 09:38:02 2029] [error] [client xxx.xxx.xxx.xxx]   File "D:\\Python27\\Lib\\encodings\\utf_8.py", line 16, in decode, referer: http://xx.xxx.xx.xx/xxxx/xxxx/index/
[Fri Sep 22 09:38:02 2029] [error] [client xxx.xxx.xxx.xxx]     return codecs.utf_8_decode(input, errors, True), referer: http://xx.xxx.xx.xx/xxxx/xxxx/index/
[Fri Sep 22 09:38:02 2029] [error] [client xxx.xxx.xxx.xxx] TemplateSyntaxError: Caught MemoryError while rendering: , referer: http://xx.xxx.xx.xx/xxxx/xxxx/index/
[Fri Sep 22 09:38:04 2029] [error] [client xxx.xxx.xxx.xxx] mod_wsgi (pid=4308): Exception occurred processing WSGI script 'D:/mytest/wsgi/mytest.wsgi'., referer: http://xx.xxx.xx.xx/xxxx/xxxx/index/
[Fri Sep 22 09:38:04 2029] [error] [client xxx.xxx.xxx.xxx] Traceback (most recent call last):, referer: http://xx.xxx.xx.xx/xxxx/xxxx/index/
[Fri Sep 22 09:38:04 2029] [error] [client xxx.xxx.xxx.xxx]   File "D:\\Python27\\lib\\site-packages\\django\\http\\__init__.py", line 431, in next, referer: http://xx.xxx.xx.xx/xxxx/xxxx/index/
[Fri Sep 22 09:38:04 2029] [error] [client xxx.xxx.xxx.xxx]     chunk = chunk.encode(self._charset), referer: http://xx.xxx.xx.xx/xxxx/xxxx/index/
[Fri Sep 22 09:38:04 2029] [error] [client xxx.xxx.xxx.xxx]   File "D:\\Python27\\lib\\site-packages\\django\\utils\\functional.py", line 55, in _curried, referer: http://xx.xxx.xx.xx/xxxx/xxxx/index/
[Fri Sep 22 09:38:04 2029] [error] [client xxx.xxx.xxx.xxx]     return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs)), referer: http://xx.xxx.xx.xx/xxxx/xxxx/index/
[Fri Sep 22 09:38:04 2029] [error] [client xxx.xxx.xxx.xxx]   File "D:\\Python27\\lib\\site-packages\\django\\utils\\safestring.py", line 81, in _proxy_method, referer: http://xx.xxx.xx.xx/xxxx/xxxx/index/
[Fri Sep 22 09:38:04 2029] [error] [client xxx.xxx.xxx.xxx]     data = method(self, *args, **kwargs), referer: http://xx.xxx.xx.xx/xxxx/xxxx/index/
[Fri Sep 22 09:38:04 2029] [error] [client xxx.xxx.xxx.xxx] MemoryError, referer: http://xx.xxx.xx.xx/xxxx/xxxx/index/

MemoryError ? 这是说内存错误?

查看任务管理器后发现内存使用近4G, 离8G的内存还远着,再看apache使用了近2G, 尝试将 apache 服务重新启动了一下,发现apache内存使用将到了 25M。而原来出现错误的页面都已经正常。

联想到新增加了视频上传功能,猜测可能是用户最近上传视频之后,导致了apache的内存泄漏。

联想到前段时间一台云服务器1cpu, 1g mem 出现的内存不足问题,先对apache进行配置调节。

五.启用MPM模块配置文件
1.MPM模块是专门针对Windows操作系统而优化设计的,在Apace安装目录下的conf下的httpd.conf文件中启用该配置文件
找到
# Server-pool management (MPM specific)

Include conf/extra/httpd-mpm.conf (去掉前面的注释符号"#")
2.在Apace安装目录下的conf下extra目录中的配置文件httpd-mpm.conf中更改MPM模块的相关配置
找到mpm_winnt_module,由于mpm_winnt模块只会创建1个子进程,因此这里对单个子进程的参数设置就相当于对整个Apache的参数设置。
<IfModule mpm_winnt_module>

ThreadsPerChild 1500

MaxRequestsPerChild 0

</IfModule>
ThreadsPerChild: 线程数量,线程数量越大,越能够更好的处理更多并发连接。默认值是150,推荐设置:小型网站=1000 中型网站=1000~2000 大型网站=2000~3500
MaxConnectionsPerChild:累计最多处理到多少个请求,超过该值会自动重启Apache,设置为0,则没有限制,但可能会照成内存泄漏。小型网站=10000 中型或大型网站=20000~100000,若设置为大于0时,最好为ThreadsPerChild的100倍

MaxConnectionsPerChild:累计最多处理到多少个请求,超过该值会自动重启Apache,设置为0,则没有限制,但可能会照成内存泄漏。小型网站=10000 中型或大型网站=20000~100000,若设置为大于0时,最好为ThreadsPerChild的100倍

考虑到内部系统,将参数调小一点,观察一下将来是否正常。
#ThreadsPerChild 150
#MaxRequestsPerChild 0

ThreadsPerChild 100
MaxRequestsPerChild 5000

参考: https://blog.csdn.net/xyy1028/article/details/89440858

云服务器居然内存不足(只有apache,mysql)

一台小服务器,前几天出现持续地连接不上数据库的情况。

于是进到服务器,重启mysql, 过一会发现,依然连不上,mysql又崩了,查看mysql日志

[Note] InnoDB: PUNCH HOLE support available
[Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
[Note] InnoDB: Uses event mutexes
[Note] InnoDB: GCC builtin __atomic_thread_fence() is used for memory barrier
[Note] InnoDB: Compressed tables use zlib 1.2.11
[Note] InnoDB: Using Linux native AIO
[Note] InnoDB: Number of pools: 1
[Note] InnoDB: Using CPU crc32 instructions
[Note] InnoDB: Initializing buffer pool, total size = 128M, instances = 1, chunk size = 128M
[ERROR] InnoDB: mmap(137428992 bytes) failed; errno 12
[ERROR] InnoDB: Cannot allocate memory for the buffer pool
[ERROR] InnoDB: Plugin initialization aborted with error Generic error
[ERROR] Plugin ‘InnoDB’ init function returned error.
[ERROR] Plugin ‘InnoDB’ registration as a STORAGE ENGINE failed.
[ERROR] Failed to initialize builtin plugins.
[ERROR] Aborting

[Note] Binlog end
[Note] Shutting down plugin ‘CSV’
[Note] /usr/sbin/mysqld: Shutdown complete

有问题找度娘,结果人家说是 mysql 没有使用swap

$ free
total used free shared buff/cache available
Mem: 1009152 243408 561672 24052 204072 599100
Swap: 0 0 0

好像还真是

于是给系统加上swap

$ sudo fallocate -l 1G /swapfile
$ ls -lh /swapfile
-rw-r–r– 1 root root 1.0G Aug 6 00:34 /swapfile
$ sudo chmod 600 /swapfile
$ ls -lh /swapfile
-rw——- 1 root root 1.0G Aug 6 00:34 /swapfile
$ sudo mkswap /swapfile
Setting up swapspace version 1, size = 1024 MiB (1073737728 bytes)
no label, UUID=acf7347a-7a96-443b-ae73-cf6ea2d6e7f2
$ sudo swapon /swapfile
$ sudo swapon –show
NAME TYPE SIZE USED PRIO
/swapfile file 1024M 0B -2
$ free -h
total used free shared buff/cache available
Mem: 985M 240M 541M 23M 203M 582M
Swap: 1.0G 0B 1.0G

重启mysql,貌似有点作用,不过发现还是好慢好慢,访问在等待十几分钟后可以显示出网页,

top – 02:09:49 up 1:11, 2 users, load average: 0.23, 0.10, 0.02
Tasks: 117 total, 2 running, 80 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 1.0 sy, 0.0 ni, 98.7 id, 0.0 wa, 0.0 hi, 0.3 si, 0.0 st
KiB Mem : 1009280 total, 301684 free, 399268 used, 308328 buff/cache
KiB Swap: 2097148 total, 1963260 free, 133888 used. 447072 avail Mem

$ free
total used free shared buff/cache available
Mem: 1009280 399296 301480 19832 308504 447044
Swap: 2097148 133888 1963260

看看 apache的配置,稍微调整一下,还是不起作用

<IfModule mpm_prefork_module>
        StartServers                    3
        MinSpareServers          2
        MaxSpareServers         5
        #MaxRequestWorkers        150
        MaxRequestWorkers        20
        #MaxConnectionsPerChild   5000
        MaxConnectionsPerChild   30
</IfModule>

应该是apache吃了太多的内存,导致mysql吃不到,然后mysql直接掀桌子不玩。

短时间内没辙了,还是云服务器加内存吧

原来服务器是活动时买的,1cpu 1G,想要升到2G内存,因为不加钱,居然不给升,发企鹅工单后,才知道只有产生了费用的才给升,于是升到4G。

升好内存后,发现世界原来如此美好,一切又美出天了

这世界归根结底还是人民币玩家厉害。

空下来研究一下apache的内存调优,或者切换到nginx上

参考:

ubuntu 18.04 设置swap 交换分区文件:https://blog.csdn.net/lhs960124/article/details/80446433