Lnmp技术手册

 

 

 

                        

 

 

 

 

 

 

 

 

 

 

 

 Php篇

 

配置

1) Php.ini

display_errors=(boolen) 错误信息是否显示到屏幕 生产环境必须关闭

output_buffering = On  设一个输出处理器自动地打开输出缓冲

register_globals=off 开启全局变量(安全问题 做关闭操作)

max_execution_time 每个脚本运行的最长时间

memory_limit  脚本运行最大消耗的内存

magic_quotes_gpc 字符串的转义 一般防止出错 不建议开启 建议程序自己处理

 

如果有上传文件的需要考虑:

一般考虑时间超长和默认资源限制

 upload_max_filesize 10M    //所上传的文件的最大大小
 post_max_size 10M   //设定 POST 数据所允许的最大大小 若果超过内存限制 memory_limit 也会影响上传 通常memory_limit 应该比 post_max_size 要大
max_input_time 300   //脚本等待输入数据的时间
max_execution_time 300 //设置PHP 脚本的最大执行时间(进程的CPU时间)  {php-cgi(php-fpm) 中,该参数不会起效需要配置 php-fpm.conf中request_terminate_timeout 替代此函数}

 

另外也要考虑webserver 的资源限制

 

2) php-fpm

 

pm = static|dynamic(如果是大内存服务器的话 建议开启静态 每个干净的php进程一般6M左右)

pm.max_children 子进程的数量 根据应用场景 如果次数太小 会出现502

 

pm.max_requests 设置每个子进程重生之前服务的请求数. 对于可能存在内存泄漏的第三方模块来说是非常有用的

request_terminate_timeout 设置单个请求的超时中止时间. 该选项可能会对php.ini设置中的'max_execution_time'因为某些特殊原因没有中止运行的脚本有用

 

pm.max_requestsrequest_terminate_timeout的设置 对于一些异常进程非常重要 咱们多个系统出现过此类问题

 

Php调试

 

1) 内置api基本调试

Echo、 print _r 、var_dump(var_export)、debug_zval_dump 。

 

2) 错误控制和日志记录

display_errors  error_reporting  log_errors log_errors

 

 

 

 

详见:http://cn2.php.net/manual/zh/errorfunc.configuration.php#ini.display-errors

 

3) 错误抛出和处理

Try  catch截取异常  throw抛出异常

 错误抛出和处理主要是说我们在程序中,能够自己触发错误,或者是自己截获处理错误,类似于面向对 象编程里的异常处理 throw 抛出异常,catch  截获异常一个思路。

trigger_error 、set_error_handler、set_exception_handler  这三个api 主要就是处理错误抛出和处理内置函数。

 

使用 trgger_error 可以触发一个错误,触发级别跟上文的 error_reporting      的设定级别一致,主要是能够触 发的是 E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE  三种级别的错误,如果不做处理,那么 在程序执行就会报错,错误提示跟上文描述差不多,会出现 Fatal Error 、Warning 、Notice三种错误显示。

trigger_error 是一个抛出错误的函数,可以抛出任何用户级别错误,在非面向对象时代的编里,可以作 为一个提示错误的一种方式。

详见:http://www.php.net/manual/zh/language.exceptions.php

4) 第三方工具

Xdebug、、firebug、firephp、 xhprof apd(Advanced PHP debugge)等

1)Xdebug

重点说一下Xdebug

实例:

团购抓取增加了很多功能 抓取速度骤然变慢 要确定是什么拉慢了系统

安装xdebug

[root@localhost zhangminsong]# wget http://xdebug.org/files/xdebug-2.2.1.tgz

[root@localhost zhangminsong]# tar xvf xdebug-2.2.1.tgz

[root@localhost zhangminsong]# cd xdebug-2.2.1

[root@localhost xdebug-2.2.1]# /usr/local/php/bin/phpize

Configuring for:

PHP Api Version:         20090626

Zend Module Api No:      20090626

Zend Extension Api No:   220090626

[root@localhost xdebug-2.2.1]# ./configure --with-php-config=/usr/local/php/bin/php-config

[root@localhost xdebug-2.2.1]# make

[root@localhost xdebug-2.2.1]# make install

Installing shared extensions:     /usr/local/php/lib/php/extensions/no-debug-non-zts-20090626/

 

修改 php.ini 增加

 

[Xdebug]

zend_extension="/usr/local/php/lib/php/extensions/no-debug-non-zts-20090626/xdebug.so"

xdebug.auto_trace = on

xdebug.auto_profile = on

xdebug.collect_params = on

xdebug.collect_return = on

xdebug.profiler_enable = on

xdebug.trace_output_dir="/tmp/xdebug"

xdebug.profiler_output_dir="/tmp/xdebug"

xdebug.profiler_output_name="script"

 

Mkdir /tmp/xdebug

重启php 查看phpinfo

 

跑一下抓取脚本 会在/tmp/xdebug中产生如下文件

[root@localhost xdebug-2.2.1]# ll /tmp/xdebug/

总用量 904

-rw-r--r-- 1 www www 234232 2月   1 23:46 script

-rw-r--r-- 1 www www 686293 2月   1 23:46 trace.619174344.xt

 

Sz /tmp/xdebug/script 到本地分析这个文件 分析这个文件需要下载一个工具

WinCacheGrind(http://sourceforge.net/projects/wincachegrind/ )

 

 

一目了然 

 

 

跑到这个函数 浪费了这么时间(1600个商品)居然调用了17w次的redis 平均一次0.2

Ms,问题找到了  然后修改了代码逻辑 ok 速度变快了.

详情:http://xdebug.org/

 

2)APD(Advanced PHP Debugger)

 

高级 PHP  调试器。是用来给 PHP  代码提供规划与纠错的能力, 以及提供了显示整个堆栈追踪的能力。支持交互式纠错,但默认是将数据写入跟踪文件。它还提供了 基于事件的日志,因此不同级别的信息(包括函数调用,参数传递,计时等)可以对个别的脚本打开或关闭。

详情:http://cn2.php.net/manual/zh/intro.apd.php

3)Xhprof

 

它是个轻量级的性能监测工具,安装部署简单,占用系统资源更少, Xhprof 不是通过配置来启用监测,是否启用你直接在代码里启用,你需要监测哪个文件就在该文件启 用监测,这样不会像Xdebug 一样每个执行的文件都会记录下性能情况,Xhprof 自带Web 断的结果查看页面,不需要像Xdebug 另外安装 。

详情:http://cn2.php.net/manual/zh/intro.xhprof.php

5)php单元测试

  Phpuint

 PHPUnit  是一个轻量级的PHP  测试框架。它是在PHP5  下面对JUnit3  系列版本的完整移植,是xUnit 测试框架家族的一员(它们都基于模式先锋Kent Beck 的设计) 。

单元测试是几个现代敏捷开发方法的基础,使得PHPUnit 成为许多大型PHP 项目的关键工具。这个工 具也可以被 Xdebug  扩展用来生成代码覆盖率报告 ,并且可以与phing  集成来自动测试,最后它还可以和 Selenium 整合来完成大型的自动化集成测试。 

 

详见:http://pear.phpunit.de/

 

Php加速优化工具(主要是优化php opcode)

APC xcache 、eacceleratorZend Optimize

建议做个必须条件安装到线上

 

php扩展安装

 

1)安装php扩展

进行PHP的扩展开发有两种方式 ,第一种是从PHP源码进行,第二种是从PHP提供的独立的工具进行 第一种少了灵活性 所以我们一般选择第二种方式。

PHP的核心(core)有两部分组成最底层的Zend引擎和他上面的phpcode,所以扩展类型又有两种:

extension意为基于php(core)的扩展

zend_extension意为基于zend引擎的扩展

我们常用第二种方式进行扩展即外部加载

php的扩展包 大部分在/php源码/ext 下  如果没有可以单独下载

 

步骤

 /usr/local/php/bin/phpize

 

  ./configure --help

  ./configure --with-php-config=/usr/local/php/bin/php-config

  make

  make test #就算这里提示出错,不要理它!

  make install

 

注:phpize 是属于 php-devel 中的东西,主要是设定 php 外挂模块的一些设定(一般存在于php-devel

 

make install会生成xxx.so  然后在php.ini中手动加载进去。

 

2)编写php扩展

 

1 获取php源码包解压

wget http://

tar

2 进入php源码包ext 目录

cd php-5.2.14/ext

3 生成扩展框架

./ext_skel --extname=zhang

实例:

--------------

[root@domain09 ext]# ./ext_skel --extname=zhang

Creating directory zhang

Creating basic files: config.m4 config.w32 .cvsignore zhang.c php_zhang.h CREDITS EXPERIMENTAL tests/001.phpt zhang.php [done].

 

To use your new extension, you will have to execute the following steps:

 

1.  $ cd ..

2.  $ vi ext/zhang/config.m4

3.  $ ./buildconf

4.  $ ./configure --[with|enable]-zhang

5.  $ make

6.  $ ./php -f ext/zhang/zhang.php

7.  $ vi ext/zhang/zhang.c

8.  $ make

 

Repeat steps 3-6 until you are satisfied with ext/zhang/config.m4 and

step 6 confirms that your module is compiled into PHP. Then, start writing

code and repeat the last two steps as often as necessary.

------------------------------------------------------------------

 

这个命令会在php-5.2.14/ext目录里面生成 zhang目录 并在该目录生成一些文件 其中用到的 是3个文件  一个是config.m4 一个是php_zhang.h  一个是 zhang.c

 

实例:

------------------------------------------------------

[root@domain09 zhang]# ll

total 64

-rw-r--r-- 1 root root 1975 Jan 20 09:59 config.m4

-rw-r--r-- 1 root root  282 Jan 20 09:59 config.w32

-rw-r--r-- 1 root root    4 Jan 20 09:59 CREDITS

-rw-r--r-- 1 root root    0 Jan 20 09:59 EXPERIMENTAL

-rw-r--r-- 1 root root 2666 Jan 20 09:59 php_zhang.h

drwxr-xr-x 2 root root 4096 Jan 20 09:59 tests

-rw-r--r-- 1 root root 5133 Jan 20 09:59 zhang.c

-rw-r--r-- 1 root root  496 Jan 20 09:59 zhang.php

------------------------------------------------------------

 

 

 

编辑 这三个文件

vi config.m4

把下面这两句前面的的dnl去掉,保存

dnl PHP_ARG_ENABLE(zhang, whether to enable zhang support,

dnl [  --enable-zhang           Enable zhang support])

 

 

 

 vi php_zhang.h

 

找到PHP_FUNCTION(confirm_zhang_compiled);    /* For testing, remove later. */

,新增一行:

PHP_FUNCTION(zhang_test);

 

保存

vi zhang.c

代码后面加上你的c代码

比如

PHP_FUNCTION(zhang){

 

RETURN_STRING("hello world! zhangminsong",1);

 

}

 

然后开始编译

[root@domain09 zhang]# phpize

[root@domain09 zhang]# ./configure --with-php-config=/usr/local/ku6/php/bin/php-config

[root@domain09 zhang]# make

 

 

然后 zhang/modules/下会生成一个zhang.so

 

cp 到php的extensions目录  然后 vi php.ini 加上

 

extension = zhang.so

 

重启php

 

<?php

 

phpinfo();

 

echo zhang();

 

?>

 

php程序安全

1 是命令注入攻击 主要通过system eval passthru等这些函数 执行外部提交过来的命令

2 客户端脚本注入攻击(注意过滤提交数据)

3 跨站脚本攻击(注意过滤提交数据)

4 sql 注入攻击(注意过滤特殊字符)

5 跨站伪造请求攻击 (检查页面来源)

6 session 劫持攻击(注意session id 的安全 如封装 更改名称等)

7 session固定攻击(不要get post获取 重新生成新的seesion id 检查来源等)

8 HTTP响应拆分攻击(使用最新版的php 就行了 或者检查http头或者sessionid)

9 文件上传攻击(限制上传条件)

10 目录穿越攻击(检查目录字符)

11 远程文件引入攻击(检查目录字符)

12 变量指定攻击 (注意检查变量)


基本就这些了 括号里面我粗略的注释了防范的方法 总的来说就要不要信任站外提交一切数据 必须按照规则检查过滤

 

 附录 php一些常见错误

1 语法构造错误 

This is a syntax error

2 头出输出错误 

Warning: Cannot add header information - headers already sent by

Warning: Cannot send session cache limiter - headers already sent in somefile.php on line

3 mySql 资源错误

Warning: Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in…

SQL查询语句错误(但错误没有被抛出)

 

4 Sessions 不能被创建或者被修改维护

Sessions are not being created or maintained

 

5文件流错误

Warning: failed to open stream…

 

6文件没有权限被读取

 Warning: fopen(…): failed to open stream: Permission denied in…

 

7 空白页面

 

8 乱码

 

9 最大执行时间错误

Max Execution Time Error

 

10 打开基目录错误

warning: Unknown(): open_basedir restriction in effect.

 

 

 

 

 

 

 

 

 

 

Mysql 篇

 

1)mysql安全

 

1 mysql目录文件的权限设置

MySQL所在的主机的安全性是最首要的问题,如果主机不安全,被攻击者控制,那么MySQL的安全性也无从谈起。其次就是数据目录和数据文件的安全性,也就是权限设置问题

mysql的运行建立mysql用户和mysql用户组:

/usr/sbin/groupadd mysql

/usr/sbin/useradd -g mysql mysql

chmod +w /usr/local/ku6/mysql/

chown -R mysql:mysql /usr/local/ku6/mysql/

chown -R mysql:mysql mysql/

 

mysql用户帐号的身份建立数据表:

/usr/local/ku6/mysql/bin/mysql_install_db --

basedir=/usr/local/ku6/mysql --datadir=/mysql/3306/data --user=mysql

 

 

2 修改root用户口令,删除空口令

mysql> use mysql;

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Database changed

mysql> delete from user where user='';

Query OK, 0 rows affected (0.00 sec)

mysql> update user set password=password('testpasswd') where

 

user='root';

Query OK, 2 rows affected (0.00 sec)

Rows matched: 2  Changed: 2  Warnings: 0

 

mysql> flush privileges;

Query OK, 0 rows affected (0.00 sec)

 

3 mysql的访问问题

避免外部连接

启动时Skip-networking

my.cnf bind-address=内网ip

限定连接IP

mysql> grant ALL PRIVILEGES on *.* to ktvtest@'%' to

ktv_user@'x.x.x.x/x.x.x.x' identified by 'passwd';

4 危险的函数

LOAD DATA INFILE(只能读全局可读文件)

SELECT …INTO  OUTFILE(不能覆盖文件)

 

举例:

mysql>create table a (cmd text);

mysql>insert into a values ("<?php" );

mysql>insert into a values ("phpinfo()" );

mysql>insert into a values ("<php?>" );

mysql>select * from a into outfile “/usr/local/ku6/ktv/shell.php";

5 mysql 启动安全问题

绝对不要作为使用root用户运行MySQL服务器。应该用普通非特权用户运行mysql

my.cnf    user=mysql

6 命令历史记录保护

# rm .bash_history .mysql_history

# ln –s /dev/null .bash_history

# ln –s /dev/null .mysql_history

 

 7 构建choot 环境

MySQL运行在一个独立的环境下,将其和主系统隔离

 

2)mysql监控与调优

 

1 检查系统的状态

主要察看 CPU问题 内存问题 磁盘IO问题 网络问题

命令 top 、vmstat 、sar、iostat等

 

1) 用vmstat察看关于内核进程,虚拟内存,磁盘,cpu的的活动状态

[root@ks01 ~]# vmstat

procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------

 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st

 0  0    208 811596 326016 2485004    0    0     0     1    0    0  0  0 100  0  0

 

 

其中:

kthr--内核进程的状态

--r 运行队列中的进程数,在一个稳定的工作量下,应该少于5

--b 等待队列中的进程数(等待I/O),通常情况下是接近0的.

memory--虚拟和真实内存的使用信息

--avm 活动虚拟页面,在进程运行中分配到工作段的页面空间数.

--fre 空闲列表的数量.一般不少于120,当fre少于120时,系统开始自动的kill进程去释放

      free list

page--页面活动的信息

--re 页面i/o的列表

--pi 从页面输入的页(一般不大于5)

--po 输出到页面的页

--fr 空闲的页面数(可替换的页面数)

--sr 通过页面置换算法搜索到的页面数

--cy 页面置换算法的时钟频率

faults--在取样间隔中的陷阱及中断数

--in 设备中断

--sy 系统调用中断

--cs 内核进程前后交换中断

cpu--cpu的使用率

--us 用户进程的时间

--sy 系统进程的时间

--id cpu空闲的时间

--wa 等待i/o的时间

一般us+sy 在单用户系统中不大于90,在多用

 

2 )sar来检查操作系统是否存在IO问题

 

sar可以显示CPU、运行队列、磁盘I/O、分页(交换区)、内存、CPU中断、网络等性能数据

 

[root@ks01 ~]# sar

Linux 2.6.18-194.el5 (ks01.oss.com)     05/03/2011

 

12:00:01 AM       CPU     %user     %nice   %system   %iowait    %steal     %idle

12:10:01 AM       all      0.00      0.00      0.00      0.03      0.00     99.96

12:20:01 AM       all      0.00      0.00      0.00      0.01      0.00     99.98

...

其中:

-CPU

 CPU编号

--%user

 在用户模式中运行进程所花的时间的百分比

 

--%nice

 运行正常进程所花的时间的百分比

--%system

 在内核模式(系统)中运行进程所花的时间的百分比

--%iowait

 没有进程在该CPU上执行时,处理器等待I/O完成的时间的百分比   --这个值过高,表示硬盘存在I/O瓶颈

--%idle

 CPU空闲时间百分比 ---如果这个值很高 但是系统响应慢 这时候应该加大内存 如果这个值持续太低 说明系统缺少cpu资源

 

附:sar 命令行的常用格式:

sar -u 是sar的缺省输出 (CPU 使用情况)

 

 

sar [options] [-A] [-o file] t [n]

 

在命令行中,n 和t 两个参数组合起来定义采样间隔和次数,t为采样间隔,是必须有

的参数,n为采样次数,是可选的,默认值是1,-o file表示将命令结果以二进制格式

存放在文件中,file 在此处不是关键字,是文件名。options 为命令行选项,sar命令

的选项很多,下面只列出常用选项:

 

   -A:所有报告的总和。

   -u:CPU利用率

   -v:进程、I节点、文件和锁表状态。

   -d:硬盘使用报告。

   -r:没有使用的内存页面和硬盘块。

   -g:串口I/O的情况。

      -b:缓冲区使用情况。

      -a:文件读写情况。

      -c:系统调用情况。

      -R:进程的活动情况。

      -y:终端设备活动情况。

      -w:系统交换活动。

 

比如

[root@ks01 ~]# sar -u 2 5  每2秒采集一下信息 收集5次

Linux 2.6.18-194.el5 (ks01.oss.com)     05/03/2011

 

03:33:47 PM       CPU     %user     %nice   %system   %iowait    %steal     %idle

03:33:49 PM       all      0.00      0.00      0.00      0.00      0.00    100.00

03:33:51 PM       all      0.00      0.00      0.00      0.00      0.00    100.00

03:33:53 PM       all      0.00      0.00      0.00      0.03      0.00     99.97

03:33:55 PM       all      0.00      0.00      0.00      0.00      0.00    100.00

03:33:57 PM       all      0.00      0.00      0.00      0.00      0.00    100.00

Average:          all      0.00      0.00      0.00      0.01      0.00     99.99

 

2 检查mysql状态

 

几个命令:

 

show status        显示系统状态

show variables     显示系统变量

show processlist   显示进程状态

show profiles;     收集执行查询资源信息 默认是关闭的 开启 set profiling=1;

 

------------------------------------

常用的衍生命令:

 

 连接失败情况

show status like'%aborted%'

 

Aborted_clients  客户端非法中断连接次数 如果随时间而增大 看看mysql的链接是否正常 或者检查一下网络 或者检查一下max_allowed_packet  超过此设置的查询会被中断( show variables like'%max%')

Aborted_connects 连接mysql失败次数  如果指过高 那就该检查一下网络 错误链接失败会在此记录

 

mysql> show status like'%aborted%';

+------------------+-------+

| Variable_name    | Value |

+------------------+-------+

| Aborted_clients  | 46    |

| Aborted_connects | 1     |

+------------------+-------+

2 rows in set (0.00 sec)

 

 

 

慢查询:

 

show variables like '%slow%'

show status like '%slow%';

默认是关闭的 开启 set global log_slow_queries=ON ;

Slow_launch_threads 值较大 说明有些东西正在延迟链接的新线程

 

mysql> show variables like '%slow%' ;

+---------------------+--------------------------------------+

| Variable_name       | Value                                |

+---------------------+--------------------------------------+

| log_slow_queries    | ON                                   |

| slow_launch_time    | 1                                    |

| slow_query_log      | ON                                   |

| slow_query_log_file | /data0/mysql/3306/data/ks01-slow.log |

+---------------------+--------------------------------------+

4 rows in set (0.00 sec)

mysql> show status like '%slow%';

+---------------------+-------+

| Variable_name       | Value |

+---------------------+-------+

| Slow_launch_threads | 0     |

| Slow_queries        | 0     |

+---------------------+-------+

2 rows in set (0.00 sec)

 

 

 

连接数

 

show variables like 'max_connections' 最大连接数

show  status like 'max_used_connections'响应的连接数

max_used_connections / max_connections * 100% (理想值 ≈ 85%)

如果max_used_connections跟max_connections相同 那么就是max_connections设置过低或者超过服务器负载上限了

 

mysql> show variables like 'max_connections' ;

+-----------------+-------+

| Variable_name   | Value |

+-----------------+-------+

| max_connections | 5000  |

+-----------------+-------+

1 row in set (0.00 sec)

 

 

缓存簇

show status like 'key_blocks_u%';使用和未使用缓存簇(blocks)数

show  variables like '%Key_cache%';

show  variables like '%Key_buffer_size%';

如果Key_blocks_used * key_cache_block_size  远小于key_buffer_size 那么就意味着内存呗浪费了 应该调大key_buffer_size值

 

mysql> show status like 'key_blocks_u%';

+-------------------+--------+

| Variable_name     | Value  |

+-------------------+--------+

| Key_blocks_unused | 213839 |

| Key_blocks_used   | 503    |

+-------------------+--------+

2 rows in set (0.00 sec)

mysql> show  variables like '%Key_cache%';

+--------------------------+-------+

| Variable_name            | Value |

+--------------------------+-------+

| key_cache_age_threshold  | 300   |

| key_cache_block_size     | 1024  |

| key_cache_division_limit | 100   |

+--------------------------+-------+

3 rows in set (0.00 sec)

mysql> show  variables like '%Key_buffer_size%';

+-----------------+-----------+

| Variable_name   | Value     |

+-----------------+-----------+

| key_buffer_size | 268435456 |

+-----------------+-----------+

1 row in set (0.00 sec)

 

 

 

线程使用情况

show status like 'Thread%';如果发现Threads_created值过大的话,可以适当增加配置文件中thread_cache_size值

Threads_cached用来缓存线程

mysql> show status like 'Thread%';

+-------------------+-------+

| Variable_name     | Value |

+-------------------+-------+

| Threads_cached    | 4     |

| Threads_connected | 1     |

| Threads_created   | 5     |

| Threads_running   | 1     |

+-------------------+-------+

4 rows in set (0.00 sec)

 

 

打开的文件数

show  status like '%open_file%';

show  variables like '%open_file%';

如果Open_files和open_files_limit接近 就应该增加open_files_limit的大小

不过mysql打开的文件描述符限制都是OS的文件描述符限制,和配置文件中open_files_limit的设置没有关系

 

mysql> show  status like '%open_file%';

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| Open_files    | 178   |

+---------------+-------+

1 row in set (0.00 sec)

mysql> show  variables like '%open_file%';

+-------------------+-------+

| Variable_name     | Value |

+-------------------+-------+

| innodb_open_files | 300   |

| open_files_limit  | 25000 |

+-------------------+-------+

2 rows in set (0.00 sec)

 

全联接

show  status like '%select_full__%';

全链接是无索引链接 最好避免

如果Select_full_range_join过高 说明系统运行了很多范围查询联接表

 

mysql> show  status like '%select_full__%';

+------------------------+-------+

| Variable_name          | Value |

+------------------------+-------+

| Select_full_join       | 0     |

| Select_full_range_join | 0     |

+------------------------+-------+

2 rows in set (0.00 sec)

 

 

打开表情况

show tatus like 'open%tables%';

如果open_tables接近table_cache的时候,并且Opened_tables这个值在逐步增加,说明table_cache不够用 表缓存没有完全用上 那就要考虑增加table_cache的大小了。还有就是Table_locks_waited比较高的时候,也需要增加table_cache

 

 

mysql> show status like 'open%tables%';

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| Open_tables   | 95    |

| Opened_tables | 0     |

+---------------+-------+

2 rows in set (0.00 sec)

 

 

查询缓存

show status like 'qcache%';

show variables like 'query_cache%';察看query_cache的配置

query_cache_limit:超过此大小的查询将不缓存

query_cache_min_res_unit:缓存块的最小大小

query_cache_size:查询缓存大小

query_cache_type:缓存类型,决定缓存什么样的查询,示例中表示不缓存 select sql_no_cache 查询

query_cache_wlock_invalidate:当有其他客户端正在对MyISAM表进行写操作时,如果查询在query cache中,是否返回cache结果还是等写操作完成再读表获取结果

 

mysql> show status like 'qcache%';

+-------------------------+-----------+

| Variable_name           | Value     |

+-------------------------+-----------+

| Qcache_free_blocks      | 3         |

| Qcache_free_memory      | 536800368 |

| Qcache_hits             | 224134    |

| Qcache_inserts          | 382       |

| Qcache_lowmem_prunes    | 0         |

| Qcache_not_cached       | 404       |

| Qcache_queries_in_cache | 40        |

| Qcache_total_blocks     | 95        |

+-------------------------+-----------+

8 rows in set (0.00 sec)

mysql> show variables like 'query_cache%';

 

+------------------------------+-----------+

| Variable_name                | Value     |

+------------------------------+-----------+

| query_cache_limit            | 2097152   |

| query_cache_min_res_unit     | 2048      |

| query_cache_size             | 536870912 |

| query_cache_type             | ON        |

| query_cache_wlock_invalidate | OFF       |

+------------------------------+-----------+

5 rows in set (0.00 sec)

 

 

排序情况

show  status like 'sort%';

Sort_merge_passes过大 就要增加Sort_buffer_size  但是盲目的增加 Sort_buffer_size 并不一定能提高速度

 

mysql> show  status like 'sort%';

+-------------------+-------+

| Variable_name     | Value |

+-------------------+-------+

| Sort_merge_passes | 0     |

| Sort_range        | 0     |

| Sort_rows         | 0     |

| Sort_scan         | 0     |

+-------------------+-------+

4 rows in set (0.00 sec)

 

 

高速缓存

show variables like 'key_buffer_size';MyISAM 存储引擎键高速缓存 对MyISAM表性能影响很大大

show  status like 'key_read%';磁盘读取索引的请求次数

索引未命中缓存的概率=Key_reads / Key_read_requests * 100%

不能以Key_read_requests / Key_reads原则来设置key_buffer_size

Key_reads 将这个值和系统的i/o做对比

 

mysql> show variables like 'key_buffer_size';

+-----------------+-----------+

| Variable_name   | Value     |

+-----------------+-----------+

| key_buffer_size | 268435456 |

+-----------------+-----------+

1 row in set (0.00 sec)

mysql> show  status like 'key_read%';

+-------------------+--------+

| Variable_name     | Value  |

+-------------------+--------+

| Key_read_requests | 115144 |

| Key_reads         | 1311   |

+-------------------+--------+

2 rows in set (0.00 sec)

 

mysql>

 

 

表锁情况

show  status like 'table_locks%';

Table_locks_waited显示了多少表呗锁住并导致了mysql的锁等待 可以开启慢查询看一下

 

mysql> show  status like 'table_locks%';

+-----------------------+-------+

| Variable_name         | Value |

+-----------------------+-------+

| Table_locks_immediate | 20370 |

| Table_locks_waited    | 0     |

+-----------------------+-------+

2 rows in set (0.00 sec)

 

 

表扫描情况

show status like 'handler_read%';

show status like 'com_select';

如果Handler_read_rnd_next /Handler_read_rnd 的值过大 那么就应该优化索引、查询

 

 mysql> show status like 'handler_read%';

+-----------------------+-------+

| Variable_name         | Value |

+-----------------------+-------+

| Handler_read_first    | 0     |

| Handler_read_key      | 0     |

| Handler_read_next     | 0     |

| Handler_read_prev     | 0     |

| Handler_read_rnd      | 0     |

| Handler_read_rnd_next | 20    |

+-----------------------+-------+

6 rows in set (0.00 sec)

 

mysql> show status like 'com_select';

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| Com_select    | 0     |

+---------------+-------+

1 row in set (0.00 sec)

 

 

 

临时表情况

 

show  status like 'created_tmp%';

show  variables like 'tmp_table%';

show  variables like 'max_heap%';

如果Created_tmp_disk_tables值较高 则有可能是因为:tmp_table_size或者max_heap_table_size太小

或者是选择blob、text属性的时候创建了临时表

Created_tmp_tables 过高的话 那么就有话查询吧

 

mysql>  show  status like 'created_tmp%';

+-------------------------+-------+

| Variable_name           | Value |

+-------------------------+-------+

| Created_tmp_disk_tables | 0     |

| Created_tmp_files       | 5     |

| Created_tmp_tables      | 0     |

+-------------------------+-------+

3 rows in set (0.00 sec)

mysql> show  variables like 'tmp_table%';

+----------------+-----------+

| Variable_name  | Value     |

+----------------+-----------+

| tmp_table_size | 257949696 |

+----------------+-----------+

1 row in set (0.00 sec)

mysql> show  variables like 'max_heap%';

+---------------------+-----------+

| Variable_name       | Value     |

+---------------------+-----------+

| max_heap_table_size | 257949696 |

+---------------------+-----------+

1 row in set (0.00 sec)

 

 

二进制日志缓存

 

show status like'%binlog%';

 show variables like'%binlog%';

如果Binlog_cache_disk_use 和 Binlog_cache_use 比例很大 那么就应该增加binlog_cache_size的值

 

mysql> show status like'%binlog%';

+------------------------+-------+

| Variable_name          | Value |

+------------------------+-------+

| Binlog_cache_disk_use  | 0     |

| Binlog_cache_use       | 69166 |

| Com_binlog             | 0     |

| Com_show_binlog_events | 0     |

| Com_show_binlogs       | 0     |

+------------------------+-------+

5 rows in set (0.00 sec)

mysql> show variables like'%binlog%';

+-----------------------------------------+------------+

| Variable_name                           | Value      |

+-----------------------------------------+------------+

| binlog_cache_size                       | 4194304    |

| binlog_direct_non_transactional_updates | OFF        |

| binlog_format                           | MIXED      |

| innodb_locks_unsafe_for_binlog          | OFF        |

| max_binlog_cache_size                   | 8388608    |

| max_binlog_size                         | 1073741824 |

| sync_binlog                             | 0          |

+-----------------------------------------+------------+

7 rows in set (0.00 sec)

 

 

附录 mysql 故障

 

1 应用获取不到连接池

2 数据库响应慢

3 SQL慢

4 服务器load高

5 SWAP

6 表不见了

7 MySQL crash

 

Nginx篇

 

1)配置

 

 

worker_processes 8
nginx要开启的进程数 一般等于cpu的总核数 其实一般情况下开4个或8个就可 以了 多了没有太多用
每个nginx进程消耗的内存10兆的模样

worker_cpu_affinity
仅适用于linux,使用该选项可以绑定worker进程和CPU(2.4内核的机器用不

了)
假如是8 cpu 分配如下:
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000

00100000 01000000 10000000

nginx可以使用多个worker进程,原因如下:

to use SMP
to decrease latency when workers blockend on disk I/O
to limit number of connections per process when select()/poll() is

used
The worker_processes and worker_connections from the event sections

allows you to calculate maxclients value: k

max_clients = worker_processes * worker_connections

 

worker_rlimit_nofile 102400;

每个nginx进程打开文件描述符最大数目 配置要和系统的单进程打开文件数一

,linux 2.6内核下开启文件打开数为65535,worker_rlimit_nofile就相应

应该填写65535
nginx调度时分配请求到进程并不是那么的均衡,假如超过会返回502错误。我

这里写的大一点

use epoll

Nginx使用了最新的epoll(Linux 2.6内核)和kqueue(freebsd)网络I/O模

型,而Apache则使用的是传统的select模型。
处理大量的连接的读写,Apache所采用的select网络I/O模型非常低效。
在高并发服务器中,轮询I/O是最耗时间的操作 目前Linux下能够承受高并发

访问的Squid、Memcached都采用的是epoll网络I/O模型。

worker_connections 65535;
每个工作进程允许最大的同时连接数  Maxclient = work_processes * worker_connections)

keepalive_timeout 75

keepalive超时时间

这里需要注意官方的一句话:
The parameters can differ from each other. Line Keep-Alive:

timeout=time understands Mozilla and Konqueror. MSIE itself shuts

keep-alive connection approximately after 60 seconds.

client_header_buffer_size 16k
large_client_header_buffers 4 32k
客户请求头缓冲大小
nginx默认会用client_header_buffer_size这个buffer来读取header值,如果

header过大,它会使用large_client_header_buffers来读取
如果设置过小HTTP头/Cookie过大 会报400 错误 nginx 400 bad request
求行如果超过buffer,就会报HTTP 414错误(URI Too Long)
nginx接受最长的HTTP头部大小必须比其中一个buffer大,否则就会报400的

HTTP错误(Bad Request)。

open_file_cache max 102400

使用字段:http, server, location 这个指令指定缓存是否启用,如果启用,将记录文件以下信息: ·打开的文件描述符,大小信息和修改时间. ·存在的目录信息. ·在搜索文件过程中的错误信息 -- 没有这个文件,无法正确读取,参考open_file_cache_errors 指令选项:
·max - 指定缓存的最大数目,如果缓存溢出,最长使用过的文件(LRU)将被移除
: open_file_cache max=1000 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; open_file_cache_errors on;

open_file_cache_errors
语法:open_file_cache_errors on | off 默认值:open_file_cache_errors off 使用字段:http, server, location 这个指令指定是否在搜索一个文件是记录cache错误.

open_file_cache_min_uses

语法:open_file_cache_min_uses number 默认值:open_file_cache_min_uses 1 使用字段:http, server, location 这个指令指定了在open_file_cache指令无效的参数中一定的时间范围内可以使用的最小文件数,如 果使用更大的值,文件描述符在cache中总是打开状态.
open_file_cache_valid

语法:open_file_cache_valid time 默认值:open_file_cache_valid 60 使用字段:http, server, location 这个指令指定了何时需要检查open_file_cache中缓存项目的有效信息.


开启gzip
gzip on;
  gzip_min_length  1k;
  gzip_buffers     4 16k;
  gzip_http_version 1.0;
  gzip_comp_level 2;
  gzip_types       text/plain application/x-javascript text/css

application/xml;
  gzip_vary on;

缓存静态文件:

  location ~* ^.+\.(swf|gif|png|jpg|js|css)$ {
                root   /usr/local/ku6/ktv/show.ku6.com/;
                expires 1m;
        }

 

 

附录:一些错误排查

 

 

502 504错误

 php-cgi进程数不够用、php执行时间长(链接mysql等后端服务慢、异常等)、或者是php-cgi 进程死掉

,都会出现502错误

一般来说Nginx 502 Bad Gateway和php-fpm.conf的设置有关,而Nginx 504 Gateway Time-out则是与nginx.conf(fastcgi_*)的设置有关

 

  1、查看当前的PHP FastCGI进程数是否够用:

      netstat -anpo | grep "php-cgi" | wc -l

  如果实际使用的“FastCGI进程数”接近预设的“FastCGI进程数”,那么

,说明“FastCGI进程数”不够用,需要增大。

  2、部分PHP程序的执行时间超过了Nginx的等待时间,可以适当增加

nginx.conf配置文件中FastCGI的timeout时间,例如:

 

http

{

......

fastcgi_connect_timeout 300;

fastcgi_send_timeout 300;

fastcgi_read_timeout 300;

......

}

 

 

413 Request Entity Too Large

增大client_max_body_size

client_max_body_size:指令指定允许客户端连接的最大请求实体大小,它出现在请求头部的Content-Length字段. 如果请求大于指定的值,客户端将收到一个"Request Entity Too Large" (413)错误. 记住,浏览器并不知道怎样显示这个错误.

 

php.ini中增大

post_max_size 和upload_max_filesize

 

 附录 nginx一些错误

误信息

错误说明

"upstream prematurely(过早的) closed connection"

请求uri的时候出现的异常,是由于upstream还未返回应答给用户时用户断掉

连接造成的,对系统没有影响,可以忽略

"recv() failed (104: Connection reset by peer)"

(1)服务器的并发连接数超过了其承载量,服务器会将其中一些连接Down掉;

(2)客户关掉了浏览器,而服务器还在给客户端发送数据;

(3)浏览器端按了Stop

"(111: Connection refused) while connecting to upstream"

用户在连接时,若遇到后端upstream挂掉或者不通,会收到该错误

"(111: Connection refused) while reading response header from upstream"

用户在连接成功后读取数据时,若遇到后端upstream挂掉或者不通,

会收到该错误

"(111: Connection refused) while sending request to upstream"

Nginx和upstream连接成功后发送数据时,若遇到后端upstream挂掉或者不通,

会收到该错误

"(110: Connection timed out) while connecting to upstream"

nginx连接后面的upstream时超时

"(110: Connection timed out) while reading upstream"

nginx读取来自upstream的响应时超时

 

"(110: Connection timed out) while reading response header from upstream"

nginx读取来自upstream的响应头时超时

"(110: Connection timed out) while reading upstream"

nginx读取来自upstream的响应时超时

"(104: Connection reset by peer) while connecting to upstream"

upstream发送了RST,将连接重置

"upstream sent invalid header while reading response header from upstream"

upstream发送的响应头无效

"upstream sent no valid HTTP/1.0 header while reading response header from upstream"

upstream发送的响应头无效

"client intended to send too large body"

用于设置允许接受的客户端请求内容的最大值,默认值是1M,

client发送的body超过了设置值

"reopening logs"

用户发送kill  -USR1命令

"gracefully shutting down",

用户发送kill  -WINCH命令

"no servers are inside upstream"

upstream下未配置server

"no live upstreams while connecting to upstream"

upstream下的server全都挂了

"SSL_do_handshake() failed"

SSL握手失败

"SSL_write() failed (SSL:) while sending to client"

 

"(13: Permission denied) while reading upstream"

 

"(98: Address already in use) while connecting to upstream"

 

"(99: Cannot assign requested address) while connecting to upstream"

 

"ngx_slab_alloc() failed: no memory in SSL session shared cache"

ssl_session_cache大小不够等原因造成

"could not add new SSL session to the session cache while SSL handshaking"

ssl_session_cache大小不够等原因造成

"send() failed (111: Connection refused)"

 

 

优化Linux内核参数

vi /etc/sysctl.conf

 

这个希望运维给的权威一些

  

# Add
net.ipv4.tcp_max_syn_backlog = 65536
net.core.netdev_max_backlog =  32768
net.core.somaxconn = 32768

net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216

net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2

net.ipv4.tcp_tw_recycle = 1
#net.ipv4.tcp_tw_len = 1
net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_mem = 94500000 915000000 927000000
net.ipv4.tcp_max_orphans = 3276800

#net.ipv4.tcp_fin_timeout = 30
#net.ipv4.tcp_keepalive_time = 120
net.ipv4.ip_local_port_range = 1024  65535
 

 

前端篇

 

1  组件切分到多个域(垂直切割):

 

比如动静分开 图片服务域 (公司图片hash)js服务域 css服务域 静态html服务域等

作用:分散流量 浏览器的并发 (域名要注意cookies的作用域  不然http头会带上cookies)

 

2  减少HTTP请求:

 

合并js、css

CSS Sprites

Image Map

Data URI编码图片

 

 

3  浏览器缓存 :

这个我要重点说一下

浏览器会在用户的系统创建一个目录 用来存放缓存的内容 并会给他们一些标识 用来区分是否过期

不同的浏览器采用不同的方式来缓存内容 比如火狐可以用 about:cache?device=disk或者about:cache?device=memory 来看到底放那里了

 

注意的几个参数:

1) Last-Modified 与If-Modified-Since 告诉里浏览器最后修改的时间和这个时间之后是否更新

我这里是用nginx来自动生成的

location ~* ^.+\.(swf|gif|png|jpg|js|css)$ {

  root   /usr/local/ku6/ktv/xiu.ku6.com/;

  expires 时间;

 }

2) etag 打死我都不会用的 用不好 太耗费流量了

 

 

附上http头信息:

 

响应头信息:

Date Mon, 02 May 2011 14:55:07 GMT

Content-Type text/html; charset=utf-8

Last-Modified Mon, 25 Apr 2011 07:39:09 GMT

Vary Accept-Encoding

Content-Encoding gzip

X-Cache HIT from cache.fastweb.com.cn

请求头信息:

Host xiu.ku6.com

User-Agent Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13 QQDownload/1.7

Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language zh-cn,zh;q=0.5

Accept-Encoding gzip,deflate

Accept-Charset GB2312,utf-8;q=0.7,*;q=0.7

Keep-Alive 115

Connection keep-alive

If-Modified-Since Mon, 25 Apr 2011 07:39:09 GMT

Cache-Control max-age=0

 

4  图片优化:

 

控制图片大小

使用png8代替256色的jpg

Jpeg使用渐变渲染模式 提高载入速度

使用CSS代替图片

拼合css sprites图片

避免img标签缩图 防止内存泄漏

 

另:

压缩inline——css、js  减少加载时间(服务器nginx也开启了gizp 这个后面另说)

减少嵌套层级 要符合标准

避免使用iframe标签 Iframe标签相当于新开一个浏览器窗口

html 去掉注释及空白符

删除非必要的html属性 防止浏览器回流页面

内联脚本、外链脚本优化 防止阻塞

 

 

压力测试工具

Ab、Webbenchloadrunner

 

Webbench -c 【】 -t 【】  “url”

 

 

 

 

 

常见一些线上问题

1 系统重启 nginx php等服务没有随机启动 解决:/etc/rc.d/rc.local

2  502等问题 比如php进程100 mysql连接数50 解决:增大mysql连接数

3  504 413 错误 解决:详见nginx篇

4  权限问题 比如www用户目录跟root用户执行与写的问题

5  nginx 110: Connection timed out 防火墙ip_conntrack哈希表满拒绝连接问题 解决:关闭防火墙 或者修改参数

6  sql 过大 mysql报错  解决:max_allowed_packet 增大

7  MySQL server has gone away 解决:wait_timeout interactive_timeout 增大值 

8 端口无法访问 解决:检查防火墙设置

9 sql 执行效率问题  解决 :explain sql和慢查询日志

10 CLOSE_WAIT和TIME_WAIT过多  解决:修改系统参数

11 mysql引擎的选择 (根据应用)

12 php版本升级 与程序兼容的问题 解决:php版本日志找出差异

13 告警与容灾处理机制

14  程序安全(sql注入、test.php与test.php_bak svn文件)

15 数据库count 过慢 检查引擎是否为myisam

16 乱码问题 解决:字符集的设定

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2013-04-26 17:28  jason&li  阅读(365)  评论(0编辑  收藏  举报