11月 26

php服务器CPU负载过高故障解决

  今天接到问题,服务器跑一段时间总是cpu使用量突然增大,然后就不能连接了。突然增大情况无规律。通过查看平时服务器运行正常,CPU、内存和IO用量都不高,日志报警大致信息如下:
[WARNING] fpm_stdio_child_said(), line 167: child 30951 (pool default) said into stderr:….. [ERROR] fpm_unix_init_child(), line 168:

setrlimit(RLIMIT_NOFILE) failed: Invalid argument (22)”

  通过安装和初步处理人员沟通了解到。现在已经按照日志在网上搜索,按照网上的解决方案进行处理。处理如下

1、提升服务器的文件句柄打开打开
/etc/security/limits.conf : (增加)
* soft nofile 51200
* hard nofile 51200
# vi /etc/security/limits.conf 加上
* soft nofile 51200
* hard nofile 51200
2、提升nginx的进程文件打开数
nginx.conf : worker_rlimit_nofile 51200;
3、修改php-fpm.conf文件,主要需要修改2处。
命令 ulimit -n 查看限制的打开文件数,php-fpm.conf 中的选项rlimit_files 确保和此数值一致。
10240
51200
4、
# vi /etc/sysctl.conf
底部添加
fs.file-max=51200

  “max_requests”为什么是10240,不知道所以然。

  因为其他资源已经占满,或者存在内存泄露等问题,再大量请求时,系统单个任务压力过大导致服务器不稳定。所以经将配置改为“1024”减少最大值重启数量。

  优化并不是单纯的将参数调大,如果这样能解决,那发布版本时直接都改为最大就好了。也不能按照网上的解决方案照搬方法。所以在解决过程中,要参考学习,也要搞清原理,按照当前环境适当调整。通过调整,服务器已经稳定运行3个月,没有再次出现问题。

11月 22

python 获取阿里OSS存储图片,在内存中处理图片

  申请了阿里的云存储OSS来存储图片。需要的时候直根据图片名,到阿里OSS中获得图片,然后切割成需要尺寸,最后返回给客户。获取后的切割操为内存操作,这样就不用占硬盘的IO了。
  Image使用的是PIL。阿里的SDK。SDK在python2.6调试报错。SDK比较古老,如报MD5的错误可以将oss_util.py开始的“import md5”修改为“from hashlib import md5”
  部分代码如下:

#!/bin/env python
# -*- coding:utf-8 -*-
# ---------------------------------------------
# Filename:    test.py
# Revision:    
# Date:        2012-11-19
# Author:      simonzhang
# Email:       simon-zzm@163.com
# Web:         www.simonzhang.net
# ---------------------------------------------
from oss import oss_api
import Image
from StringIO import StringIO

#### 阿里云OSS的基础信息 
HOST="oss.aliyuncs.com"  
ACCESS_ID = "xxxxxxxxx" 
SECRET_ACCESS_KEY = "xxxxxxxxxxxxx="
bucketName = "_photo"


#### 从阿里云存储获取图片
def get_image(_image_name):
    my_store = oss_api.OssAPI(HOST, ACCESS_ID, SECRET_ACCESS_KEY)
    res = my_store.get_object(bucketName, _image_name).read()
    #### 开始切图
    _cut_image = cut_image(res)
    return _cut_image

#### 切图部分
def cut_image(_image_data):
    _get_image = Image.open(_image_data)
    #### 切成300X300的尺寸
    tmp_image = _get_data.resize((300,300),Image.ANTIALIAS)
    #### 在内存中转换图片为string
    _tmp_file = StringIO("")
    tmp_image.save(_tmp_file, 'JPEG', quality=75)
    _tmp_file.seek(0)
    _tmp_image = _tmp_file.read()
    return _tmp_image

  测试效果还可以,一个一核的CPU,512M内存,1M带宽跑满CPU使用率10%。买台最便宜的阿里主机,直接从OSS里获取就不用再收费了。框架用的是tornado。

11月 18

tornado 使用配置文件的问题测试

  使用tornado做个能承担高负载的接口,配置部分是否要使用配置文件(ConfigParser)。现在有两个问题需要测试。第一、配置文件是否一次性加载,我可不希望,每次调用都会加载配置文件。第二、修改配置文件是否可以自动加载。在tornado中py文件可以自动加载,这样服务就不需要重启,服务也不会间断。
  首先是做一个tornado的测试页。在目录opt下建立testconfig文件夹,在testconf下编写代码。共有4个文件。

  主文件 main.py 代码如下:

#!/bin/env python
# -*- coding:utf-8 -*-
# -------------------------------------------------------------------------------
# Filename:    main.py
# Revision:    1.0
# Date:        2012-11-18
# Author:      simonzhang
# Email:       simon-zzm@163.com
# Web:         www.simonzhang.net
# -----------------------------------------------------------------------------
import tornado.ioloop
import tornado.web
from index import *
 
application = tornado.web.Application([
    (r"/", MainHandler),
])
 
if __name__ == "__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

  主文件要调用的部分 index.py 代码如下:

#!/bin/env python
# -*- coding:utf-8 -*-
# -------------------------------------------------------------------------------
# Filename:    main.py
# Revision:    1.0
# Date:        2012-11-18
# Author:      simonzhang
# Email:       simon-zzm@163.com
# Web:         www.simonzhang.net
# -----------------------------------------------------------------------------
import tornado.ioloop
import tornado.web
import ConfigParser

# 配置进行全局加载,如果是放到类中肯定每次都有IO。
cf = ConfigParser.ConfigParser()
cf.read("config.properties")
get_index_file_path = cf.get(cf.sections()[0], "path")
 
class MainHandler(tornado.web.RequestHandler):
    def get(self):
        read_file = open(get_index_file_path, "rb").read()
        self.write("%s" % read_file)

  配置文件名为config.properties内容如下:

[context_path]
path = index.txt

  创建一个index.txt文件,在里面写点要显示的文件。

  开始编写监控配置文件IO的脚本。监控文件变化的部分详见:http://www.simonzhang.net/?p=429。还不知道watchdog能不能做到这个。
  脚本名为 watchfile.py 代码如下:

#!/bin/env python
# -*- coding:utf-8 -*-
# -------------------------------------------------------------------------------
# Filename:    watchfile.py
# Revision:    1.0
# Date:        2012-11-17
# Author:      simonzhang
# Email:       simon-zzm@163.com
# Web:         www.simonzhang.net
# -----------------------------------------------------------------------------
import re
import pyinotify

wm = pyinotify.WatchManager()
mask = pyinotify.IN_OPEN

class EventHandler(pyinotify.ProcessEvent):
    def process_IN_OPEN(self, event):
        self.rebuild(event)
    def rebuild(self, event):
        if (event.dir == False) and (event.name == 'config.properties') :
            print "open config file"

def main():
    handler = EventHandler()
    notifier = pyinotify.Notifier(wm, handler)
    wdd = wm.add_watch('/opt/testconfig',mask, rec=True,auto_add=True )
    notifier.loop()

if __name__ == "__main__":
    main()

  最终测试结果。第一、配置文件是在服务启动时一次加载。第二、配置文件不能自动加载,修改完配置文件必须要重启服务。
  使用ConfigParser来做配置文件,自然非常方便,tornado重启速度很快,但是我还是希望能自动加载,因为在几百台服务的情况下,能自动加载自然比需要重启更方便。所以当前就是把配置直接写到代码中,然后找个文件记录配置位置。之后再研究一下能不能热重启。如果大家有好的办法也烦请请告诉我一声。