庸人妄语

大道三千,吾修顺心意


  • 首页

  • 标签

  • 分类

  • 归档

mysql 36条军规

发表于 2018-01-02 | 分类于 mysql

36条军规

核心军规

  • 不在数据库做运算,尽可能简单应用mysql,复杂运算移到程序段

举例:

1
2
md5();
Order by Rand();
  • 控制单表数据量
1
2
3
1. int型不超过1000w,含char则不超过500w
2. 合理分表不超载,常用分表策略:UserID、DATE、AREA...
3. 限制单库表数量在300以内;
  • 控制列数量
1
表字段数少而精:io高效、全表遍历、表修复快、提高并发、alter table快
  • 拒绝3B:拒绝大SQL,复杂事务,大批量任务
  • 平衡范式与冗余

字段类军规

  • 用好数值字段类型

tinyint(1Byte)、smallint(2Byte)、mediumint(3Byte)、int(4Byte)、bigint(8Byte)

1
2
3
4
5
6
7
8
9
举例:bad case
int(1)/int(11),填充的是0的个数

举例:时间格式中timestamp、datetime、int的选择
1. int: 4字节、索引快、between、范围广,适合需要进行大量时间范围查询的数据表
2. datetime: 8字节、时区无关、索引最慢,范围较Timestamp广
3. timestamp:4字节、时区相关[UTC存储],范围到2037年,索引较datetime快,可自动更新,跨国应用不合适
```
+ 字符转化为数字

举例: 用无符号INT存储IP,而非CHAR(15):数字型VS字符串,更高效、查询更快、占用空间更小

1
2
3
4
5
6
+ 避免使用NULL字段,特别是索引列

首先,我们要搞清楚“空值” 和 “NULL” 的概念:
1、空值是不占用空间的
2、MySQL中的NULL其实是占用空间的
> 所谓的NULL就是什么都没有,连\0都没有,\0在字符串中是结束符,但是在物理内存是占空间的,等于一个字节,而NULL就是连这一个字节都没有。在数据库里是严格区分的,任何数跟NULL进行运算都是NULL, 判断值是否等于NULL,不能简单用=,而要用IS NULL关键字。

  1. null字段很难进行查询优化: where子句中使用is null或is not null的语句优化器是不允许使用索引的
  2. Null 列需要更多的存储空间:需要一个额外字节作为判断是否为 NULL 的标志位
  3. Null字段的复合索引无效,索引不会包含有NULL值的列 只要列中包含有NULL值都将不会被包含在索引中,结果集中也不会包含这些记录
  4. NOT IN子查询在有NULL值的情况下返回永远为空结果,查询容易出错

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    + 少用并拆分TEXT/BLOB,尽量不使用TEXT/BLOB,若必须则尽可能拆分到单独的表中

    ```
    1. TEXT类型处理性能远低于VARCHAR(各自处理过程)
    2. 强制生成硬盘临时表
    3. 浪费更多空间 VARCHAR(65535) == 64K (UFT8)
    ```
    + 不在数据库中存图片

    ## 索引类军规
    + 谨慎合理的添加索引:改善查询,减慢更新
    1. 结合核心sql优先考虑覆盖索引
    2. 字段区分度要大,综合评估数据密度和数据分布
    3. 最好不超过字段数20%
    4. 索引并不是越多越好,能不加的索引尽量不加
      1
      + 自增列或者全局id做INNODB主键
  5. 主键建立聚簇索引;

  6. 主键不应该被修改,按自增顺序插入值,二级索引存储主键值
  7. 字符串不应该做主键
  8. 如果不指定主键,innodb会使用唯一且非空值索引代替;

    1
    2
    3
    4
    5
    + 尽量不使用外键,可“到达”其他表,意味着锁表高并发容易死锁,由程序保证约束
    + 不在索引列进行数据运算 和函数运算:会无法使用索引导致全表扫描

    ## 约定类军规:
    + 隔离线上线下:
  9. 构建数据库的生态环境,开发无线上库操作权限

  10. 原则:线上连线上,线下连线下
  11. 实时数据用real库,测试用qa库,模拟环境用sim库,开发用dev

    1
    + 禁止未经DBA确认的子查询

    mysql子查询:

    1. 大部分情况优化较差,特别是 where中使用 in id的子查询
    2. 一般可用join改写,mysql对子查询会处理为临时表,所以一般join效率比做子查询高
      1
      + 永远不再程序端显示加锁
  12. 外部锁对数据库不可控

  13. 高并发时是灾难
  14. 极难调试和排查
    1
    2
    3
    4
    5
    6
    7
    8
    + 字符集,统一字符集:utf8;校对规则:utf8_general_ci
    + 注意避免用保留字命名,eg. type
    + 统一命名规范:表名、字段释义、表注释  
    + mysql大批量操作最好改变为手动提交
    + 批量操作,避开高峰区,挪至凌晨
    ## sql类军规

    + sql语句尽可能简单

大sql缺点:

  1. 可能一条大sql就把整个库hang死
  2. 一条sql只能在一个cpu运算
  3. 5000+qps的高并发中,1s大sql意味着服务要挂

做法:

  1. 拒绝大sql,拆解成多条简单sql
  2. 用上多cpu
  3. 简单sql缓存命中率更高
  4. 减少锁表时间
  5. 拆分也要适量

    1
    + 保持事务连接短小
  6. 事务/连接使用原则:即开即用,用完即关

  7. 与事务无关的操作放在事务外面,减少锁资源占用
  8. 在不破坏一致性前提下,使用多个短事务代替长事务

    1
    + 尽可能避免使用SP/TRIG/FUNC
    1. 尽可能少用存储过程
    2. 尽量减少使用触发器
    3. 减少使用MYSQL函数对结果进行处理,由客户端程序负责
      1
      + 尽量不要select *,只取需要的列
  9. 更少的io

  10. 可能利用覆盖索引取值
  11. 更多消耗cpu、内存、io、网络带宽

    1
    + OR改写为IN()
    1. or效率 o(n),in效率 o(log n),当n很大时,or会很慢
    2. 注意控制in的个数,建议小于200个。 eg: 大客户系统的慢sql
      1
      + OR改写为UNION
  12. OR也可以使用到联合索引

  13. 但mysql对于or很多时候并不会优化为两次索引或者合并索引,所以or最好写做两条sql 做union all

瞎举个例子,看下union写法,其实也走合并索引:
select id from t1 where name = ‘婷宝’ or ucid = ‘131’;
=>
select id from t1 where name = ‘婷宝’
union
select id from t1 where ucid = ‘131’;

1
2
3
4
5
6

+ 避免负向查询和%前缀模糊查询:使用不了索引,导致全表扫描

> not, !=, <>, !> , !<, "not exists", "not in", "not like"

+ 慎用count(*)

举例:
count(col) = count(1) = count(0) = count(100) != count(col)

1
+ limit高效分页,limit越大,效率越低

  1. 偏移量越大则越慢
  2. 当是id时,降偏移量移到 where条件中

eg.
select id from t limit 10000, 10;
=>
select id from t where id > 10000 limit 10;

1
+ 少用连接join

  1. 减少硬盘临时表生成,特别是有TEXT/BLOB时
  2. mysql在join中对“order by”, “group by”优化较弱 join中的排序分组几乎都会使用fille sort 和临时表

    1
    2
    3
    4
    + 若无需对结果去重,用union all,而非union,union有去重开销
    + group by无排序要求时使用自动排序
    + 同数据类型的列值比较
    + 使用load data导数据
    1. 批量数据块导入,load data比insert快约20倍
    2. 成批装载比单行装载更快,不需要每次刷新缓存
    3. 无索引时装载比索引装载更快
    4. insert values,values,values 减少索引刷新
    5. 尽量不用insert … select, 会延迟、同步出错
      1
      + 打散批量更新
  3. 大批量更新凌晨操作,避开高峰

  4. 凌晨不限制,白天上限默认为100条/秒

    1
    2
    3
    4
    5
    6
    7
    8
    9
    + know every sql

    # 优化建议
    ## 1.批量插入代替循环单条插入
    ## 2.当只要一行数据时使用 LIMIT 1
    当你查询表的有些时候,你已经知道结果只会有一条结果,在这种情况下,加上 LIMIT 1 ,MySQL数据库引擎会在找到一条数据后停止搜索,而不是继续往后查下一条符合记录的数据。

    ## 3.在Join表的时候使用相当类型的例,并将其索引
    如果你的应用程序有很多 JOIN 查询,你应该确认两个表中Join的字段是被建过索引的。这样,MySQL内部会启动为你优化Join的SQL语句的机制。而且,这些被用来Join的字段,应该是相同的类型的。
  5. DECIMAL和INT字段Join在一起,MySQL就无法使用它们的索引

  6. 对于那些STRING类型,还需要有相同的字符集才行。
    1
    2
    3
    4
    5
    6
    7
    8
    ## 4.千万不要 ORDER BY RAND()
    MySQL会不得不去执行RAND()函数(很耗CPU时间),而且这是为了每一行记录去记行,然后再对其排序。就算是用了Limit 1也无济于事(因为要排序)

    ## 5.Prepared Statements
    > Prepared Statements 可以检查一些你绑定好的变量,这样可以保护你的程序不会受到“SQL注入式”攻击。

    ## 6.垂直分割
    > “垂直分割”是一种把数据库中的表按列变成几张表的方法,这样可以降低表的复杂度和字段的数目,从而达到优化的目的

eg.大客户系统的客户属性拆解:主属性+附加属性

1
2
3
## 7.拆分大的 DELETE 或 INSERT 语句

首先,我们的服务器并不会有太多的子进程,线程和数据库链接,因为这是极大的占服务器资源的事情,尤其是内存;其次,DELETE 或 INSERT是会锁表的,表一锁住了,别的操作都进不了;结果,如果表锁上一段时间,比如30秒钟,那么对于一个有很高访问量的站点来说,这30秒所积累的访问进程/线程,数据库链接,打开的文件数,可能不仅仅会让WEB服务Crash,还可能会让整台服务器马上挂掉;所以,需要对一个大的处理,进行拆分,

eg. 使用limit + sleep

while (1) {
//每次只做1000条
mysql_query(“DELETE FROM logs WHERE log_date <= ‘2017-11-01’ LIMIT 1000”);
if (mysql_affected_rows() == 0) {
break;
}
// 每次都要休息一会儿
usleep(50000);
}
```

8. 越小的列会越快

对于大多数的数据库引擎来说,硬盘操作可能是最重大的瓶颈。所以,把你的数据变得紧凑会对这种情况非常有帮助,因为这减少了对硬盘的访问。

9.小心“永久链接”

“永久链接”的目的是用来减少重新创建MySQL链接的次数,在理论上来说,这听起来非常的不错。但是从个人经验(也是大多数人的)上来说,这个功能制造出来的麻烦事更多。因为,你只有有限的链接数,内存问题,文件句柄数等等。

git拉取远程分支到本地

发表于 2017-11-28 | 分类于 版本管理
  • 新建本地分支
1
git checkout -b localName

pull远程代码

1
git pull origin remoteName
  • fetch
1
git fetch origin branchname:branchname
  • 获取远程分支remoteName 到本地新分支localName,并跳到localName分支
1
git checkout origin/remoteName -b localName

nginx 403 Forbidden

发表于 2017-11-27 | 分类于 问题排查

nginx 403 Forbidden

lnmp访问速度变慢排查方法

发表于 2017-11-27 | 分类于 问题排查

lnmp访问速度变慢排查方法

nginx日志

发表于 2017-11-27 | 分类于 Nginx

nginx 日志主要有两条指令:

  1. log_format:用来设置日志格式;
  2. access_log:用来指定日志文件的存放路径、格式(把定义的log_format 跟在后面)和缓存大小;如果不想启用日志则access_log off ;

log_format 日志格式

语法格式:

该指令用来设置日志记录的格式。

1
2
log_format name format [format ...]
name : 给定义的格式起的名称,应该是全局唯一的

默认日志格式

默认情况下,nginx的默认日志格式如下(不同版本可能略有不同):

1
2
3
log_format combined '$remote_addr - $remote_user [$time_local]  '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';

日志格式举例:

1
192.168.161.1 - - [25/Oct/2016:05:39:45 +0800] "GET /favicon.ico HTTP/1.1" 404 571 "http://192.168.161.126/" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36"

常见内置变量

nginx中log日志变量

日志分类

access_log

该指令用来指定访问日志的路径及格式等信息。

语法格式

1
access_log path [log_format_name [buffer=buffer_size | off]]

示例:

1
2
3
4
log_format reverseRealIpFormat1 '$remote_addr - $remote_user [$time_local]  '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log /var/log/nginx/my-access.log reverseRealIpFormat1 buffer=8k;

在access_log中可以使用变量,但是不能与buffer同时启用,否则buffer不能启用

1
2
1. access_log /var/log/nginx/$server_name.log reverseRealIpFormat1;
2. access_log /var/log/nginx/$server_name.log reverseRealIpFormat1 buffer=8k;

error_log

error_log是设置记录错误日志的指令。

该指令在 http, stream, server 和 location 段都可以被指定,可以覆盖更外面的段的设置。

1
error_log /var/log/nginx/error.log warn;

open_log_file_cache

每次记录日志都是将日志文件打开->写入->关闭,太消耗IO.

open_log_file_cache 可以设置路径中含有变量的日志配置中日志文件的文件描述符缓存。

1
2
3
4
5
6
7
8
open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time] | off;

参数注释如下:

max:设置缓存中的最大文件描述符数量,如果缓存被占满,采用LRU算法将描述符关闭。
inactive:设置存活时间,默认是10s
min_uses:设置在inactive时间段内,日志文件最少使用多少次后,该日志文件描述符记入缓存中,默认是1次
valid:设置检查频率,默认60s

例如:

1
open_log_file_cache max=655350 inactive=20s;

设置刷盘策略

buffer 满 32k 才刷盘;假如 buffer 不满 5s 钟强制刷盘

1
access_log /data/logs/nginx-access.log buffer=32k flush=5s;

使用举例

一般log_format在全局设置,可以设置多个。access_log 可以在全局设置,但往往是定义在虚拟主机(server)中的location中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'"$status" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'"$gzip_ratio" $request_time $bytes_sent $request_length';

log_format srcache_log '$remote_addr - $remote_user [$time_local] "$request" '
'"$status" $body_bytes_sent $request_time $bytes_sent $request_length '
'[$upstream_response_time] [$srcache_fetch_status] [$srcache_store_status] [$srcache_expire]';

open_log_file_cache max=1000 inactive=60s;

server {
server_name ~^(www\.)?(.+)$;
access_log logs/$2-access.log main;
error_log logs/$2-error.log;
location /srcache {
access_log logs/access-srcache.log srcache_log;
}
}
}

日志分析:

通过对日志格式的定义,就可以使用常见的 Linux 命令行工具进行分析了:

查找访问频率最高的 URL 和次数:

1
cat access.log | awk -F ‘^A’ ‘{print $10}’ | sort | uniq -c

查找当前日志文件 500 错误的访问:

1
cat access.log | awk -F ‘^A’ ‘{if($5 == 500) print $0}’

查找当前日志文件 500 错误的数量:

1
cat access.log | awk -F ‘^A’ ‘{if($5 == 500) print $0}’ | wc -l

查找某一分钟内 500 错误访问的数量:

1
cat access.log | awk -F ‘^A’ ‘{if($5 == 500) print $0}’ | grep ’09:00’ | wc-l

查找耗时超过 1s 的慢请求:

1
tail -f access.log | awk -F ‘^A’ ‘{if($6>1) print $0}’

假如只想查看某些位:

1
tail -f access.log | awk -F ‘^A’ ‘{if($6>1) print $3″|”$4}’

查找 502 错误最多的 URL:

1
cat access.log | awk -F ‘^A’ ‘{if($5==502) print $11}’ | sort | uniq -c

查找 200 空白页

1
cat access.log | awk -F ‘^A’ ‘{if($5==200 && $8 < 100) print $3″|”$4″|”$11″|”$6}’

切割日志

Nginx 的日志都是写在一个文件当中的,不会自动地进行切割,如果访问量很大的话,将导致日志文件容量非常大,不便于管理和造成Nginx 日志写入效率低下等问题。所以,往往需要要对access_log、error_log日志进行切割。

切割日志一般利用USR1信号让nginx产生新的日志。实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash

logdir="/data/logs/nginx"
pid=`cat $logdir/nginx.pid`
DATE=`date -d "1 hours ago" +%Y%m%d%H`
DATE_OLD=`date -d "7 days ago" +%Y%m%d`
for i in `ls $logdir/*access.log`; do
mv $i $i.$DATE
done
for i in `ls $logdir/*error.log`; do
mv $i $i.$DATE
done
kill -s USR1 $pid
rm -v $logdir"/access.log."$DATE_OLD*

rm -v $logdir"/error.log."$DATE_OLD*

1、分析:

将上面的脚本放到crontab中,每小时执行一次(0 ),这样每小时会把当前日志重命名成一个新文件;然后发送USR1这个信号让Nginx 重新生成一个新的日志。(相当于备份日志)
将前7天的日志删除;
2、说明:
在没有执行kill -USR1 $pid之前,即便已经对文件执行了mv命令而改变了文件名称,nginx还是会向新命名的文件”*access.log.2016032623”照常写入日志数据的。原因在于:linux系统中,内核是根据文件描述符来找文件的。

3、logrotates:
使用系统自带的logrotates,也可以实现nginx的日志分割,查看其bash源码,发现也是发送USR1这个信号。

使用日志排查问题举例

磁盘满

问题描述

某周日晚8点多,收到报警短信,我们一个pv统计服务的打点统计结果突然大幅减少。赶紧登VPN上内网,发现pv统计曲线,在故障发生后,对比上周日下降到1/3左右。

解决步骤

  1. 检查了统计计算程序,未发现异常。
  2. 检查了一下机器列表
    发现有一台电信的机器(ds1)挂了,lvs上已经自动下线;另一台电信机器(ds2)CPU空闲率从81%下降到42%

  3. 先将这些程序 kill掉,并在 联通机房的 ls2 机器上启动起来
    操作完毕后,ds2的CPU空闲率回升到70%多,但pv统计结果依然维持在1/3左右

  4. 查看ds2上的打点日志(nginx的access log),发现竟然没有新日志写入。再查看nginx的错误日志,有如下字样:
1
[alert] 19963#0: *17264042335 write() to "/usr/local/nginx/logs/xxx.log" failed (28: No space left on device) while logging request

再用df -lh命令查看,发现磁盘已满

1
2
3
Filesystem            Size  Used Avail Use% Mounted on
/dev/xvde1 493G 493G 0G 100% /
tmpfs 2.0G 0 2.0G 0% /dev/shm

清理一部分无用日志,重启nginx,再观察,统计结果终于回升了。

问题原因

原来电信机房的ds1机器挂了之后,所有电信的流量都到ds2这一台机器上了,导致打点日志增长过快,加上之前有部分无用日志未及时清理,导致硬盘满了,所有电信网络打点请求的日志都没有记录下来。我们电信的请求量大约是联通的两倍,因此反映到统计结果上是下降到1/3。

结论

这次问题的出现到解决,实际上经历了较长的时间。回过头来思考,其实问题是可以很快定位解决的。观察到日志下降到1/3的现象,就可以怀疑是整个电信的日志没有收集到,查一下电信机器上的打点日志 和 error log,很快可以看到问题。另外,出现程序执行不对劲,日志写入不了等等奇怪问题,都可以看看是否磁盘满了。


参考博客:

  1. http://www.jianshu.com/p/4fcaac8f2996
  2. https://lanjingling.github.io/2016/03/14/nginx-access-log/
  3. http://tabalt.net/blog/a-nginx-log-problem-investigation-record/

Nginx 504错误总结

发表于 2017-11-27

很多人都都可能遇到过 504 Gateway Time-out。有时候会让人一头雾水。
解决方法:
1.通过百度可以很多人的说法,调整 nginx配置或者PHP-fpm配置,配置大家都可以百度,在这边就不多说。但是很多都尝试了没有什么软用。
2.尝试过上面的方法还是回到本质上是不是整站都是504.如果不是,我建议你打开php-fpm 慢日志来查看对应的页面请求与响应慢是由哪个方法或者操作造成的。
php-fpm 慢日志的配置如下:
request_slowlog_timeout = 5 //5秒以上的 当一个请求该设置的超时时间后,就会将对应的PHP调用堆栈信息完整写入到慢日志中 设置为 ‘0’ 表示 ‘Off’
slowlog = /var/log/php-fpm.slow.log //日志目录

再打开日志方法查看是哪个方法或者操作导致的。直接修改代码。
php-fpm 慢日志 不建议在生产环境下使用


  1. https://my.oschina.net/u/3503791/blog/908623

Nginx 500错误总结

发表于 2017-11-27

500(服务器内部错误) 服务器遇到错误,无法完成请求。
501(尚未实施) 服务器不具备完成请求的功能。例如,当服务器无法识别请求方法时,服务器可能会返回此代码。
502(错误网关) 服务器作为网关或代理,从上游服务器收到了无效的响应。
503(服务不可用) 目前无法使用服务器(由于超载或进行停机维护)。通常,这只是一种暂时的状态。
504(网关超时) 服务器作为网关或代理,未及时从上游服务器接收请求。
505(HTTP 版本不受支持) 服务器不支持请求中所使用的 HTTP 协议版本。

Nginx 500错误(Internal Server Error 内部服务器错误):500错误指的是服务器内部错误,也就是服务器遇到意外情况,而无法履行请求。

500错误一般有几种情况:

  1. web脚本错误,如php语法错误,lua语法错误等。

  2. 访问量大的时候,由于系统资源限制,而不能打开过多的文件

一般分析思路:

(1)查看nginx error log ,查看php error log

(2)如果是too many open files,修改nginx的worker_rlimit_nofile参数,使用ulimit查看系统打开文件限制,修改/etc/security/limits.conf

(3)如果是脚本的问题,则需要修复脚本错误,并优化代码

(4)各种优化都做好,还是出现too many open files,那就要考虑做负载均衡,把流量分散到不同服务器上去了。

错误原因总结:

1、硬盘空间满了

使用 df -k 查看硬盘空间是否满了。清理硬盘空间就可以解决500错误。nginx如果开启了access log,在不需要的情况下,最好关闭access log。access log会占用大量硬盘空间。

2、nginx配置文件错误

这里不是指语法错误,nginx如果配置文件有语法错误,启动的时候就会提示。当配置rewrite的时候,有些规则处理不当会出现500错误,请仔细检查自己的rewrite规则。如果配置文件里有些变量设置不当,也会出现500错误,比如引用了一个没有值的变量。

3、如果上面的问题都不存在可能是模拟的并发数太多了,需要调整一下nginx.conf的并发设置数

解决方法是:

1 打开/etc/security/limits.conf文件,加上两句

复制代码代码如下:

  • soft nofile 65535
  • hard nofile 65535

2 打开/etc/nginx/nginx.conf
在worker_processes的下面增加一行

复制代码代码如下:
worker_rlimit_nofile 65535;

3 重新启动nginx,重新载入设置

复制代码代码如下:
kill -9 ps -ef | grep php | grep -v grep | awk '{print $2}'
/usr/bin/spawn-fcgi -a 127.0.0.1 -p 9000 -C 100 -u www-data -f /usr/bin/php-cgi
killall -HUP nginx
重启后再看nginx的错误日志,也没有发现500报错的情况了。

4、有可能是数据库问题我的在nginx日志php日志都没有发现什么问题, 最后发现数据库访问不了,修正后问题解决。


参考:

  1. http://www.cnblogs.com/huqiang/p/5333975.html

PHP慢日志slow_log

发表于 2017-11-27

    php-fpm慢日志slowl_og设置可以让开发者很好的查找哪些php进程速度过慢而导致的网站问题,让开发者方便的找到问题的所在。该方法同样适用于排查nginx的500、502问题根源,当nginx收到如上错误码时,可以确定后端php-fpm解析php出了某种问题,比如,执行错误,执行超时等。

参数设置

php-fpm.conf的配置文件中有一个参数request_slowlog_timeout是这样描述的:

; The timeout for serving a single request after which a PHP backtrace will be dumped to the ‘slowlog’ file. A value of ‘0s’ means ‘off’.
; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
; Default Value: 0
; request_slowlog_timeout = 0

1
2
1. 当request_slowlog_timeout设为一个具体秒时,比如request_slowlog_timeout =5,表示如果哪个脚本执行时间大于5秒,会记录这个脚本到慢日志文件中。
2. request_slowlog_timeout =0表示关闭慢日志输出

日志位置设置

慢日志文件位置默认在php的安装目录下的log文件夹中,可以通过修改slowlog = log/$pool.log.slow参数来指定,如下,慢日志会记录下进程号,脚本名称,具体哪个文件哪行代码的哪个函数执行时间过长:

1
2
3
4
[21-Nov-2013 14:30:38] [pool www] pid 11877
script_filename = /usr/local/nginx/html/www.quancha.cn/www/fyzb.php
[0xb70fb88c] file_get_contents() /usr/local/nginx/html/www.quancha.cn/www/fyzb.php:2
[21-Nov-2013 14:15:23] ERROR: [pool www] 'slowlog' must be specified for use with 'request_slowlog_timeout'
  1. request_slowlog_timeout 和 slowlog 需要同时设置
  2. 需要手动创建slowlog文件夹

日志说明

开启后,如果有脚本执行超过指定的时间,就会在指定的日志文件中写入类似如下的信息:

1
2
3
4
[19-Dec-2013 16:54:49] [pool www] pid 18575
script_filename = /home/web/htdocs/sandbox_canglong/test/tt.php
[0x0000000003a00dc8] curl_exec() /home/web/htdocs/sandbox_canglong/test/tt.php:2
[0x0000000003a00cd0] exfilter_curl_get() /home/web/htdocs/sandbox_canglong/test/tt.php:6

日志说明:

  1. script_filename 是入口文件
  2. curl_exec() : 说明是执行这个方法的时候超过执行时间的。
  3. exfilter_curl_get() :说明调用curl_exec()的方法
  4. exfilter_curl_get() 。
  5. 每行冒号后面的数字是行号

开启后,在错误日志文件中也有相关记录。如下

1
2
3
4
[19-Dec-2013 15:55:37] WARNING: [pool www] child 18575, script '/home/web/htdocs/sandbox_canglong/test/tt.php' (request: "GET /test/tt.php") executing too slow (1.006222 sec), logging
[19-Dec-2013 15:55:37] NOTICE: child 18575 stopped for tracing
[19-Dec-2013 15:55:37] NOTICE: about to trace 18575
[19-Dec-2013 15:55:37] NOTICE: finished trace of 18575

使用举例

问题一描述:

在一次nginx应用更新的灰度过程中,我们选取一台nginx上线,观察接下来的半小时内,nginx占用内存不断增大,直到耗尽系统资源。

问题一排查步骤:

  1. 排查error_log中并没有错误信息;
  2. 监控发现新上线的nginx流量大增;
  3. 分析access_log发现新上线的nginx的QPS是原机器的6~8倍。
  4. 证实是Keepalived导致流量负载不均衡。LVS作为负载均衡时,后端的nignx配置的keepalive_timeout时间有差异导致。

LVS的负载均衡是TCP层的,只能做连接的均衡,如果Keepalive时间设置的超长,会导致路由到这个连接的请求越多

问题二描述:

nginx做反向代理,有时发现某些接口较慢,通常都在3s左右。

问题二排查步骤:

  1. 配置nginx的access log记录upstream_response_time
  2. 分析发现响应大约3s多。
  3. 分析后端的access_log,处理时间都在毫秒级别。这说明问题是由于nginx跟后端connect较慢导致

参考博客:

  1. http://blog.csdn.net/leonpengweicn/article/details/42494813
  2. http://www.bo56.com/%E5%96%84%E7%94%A8php-fpm%E7%9A%84%E6%85%A2%E6%89%A7%E8%A1%8C%E6%97%A5%E5%BF%97slow-log%EF%BC%8C%E5%88%86%E6%9E%90php%E6%80%A7%E8%83%BD%E9%97%AE%E9%A2%98/

2018研发校招面经

发表于 2017-11-22 | 分类于 面试

工欲善其事必先利其器

阿里、腾讯
阿里面试题总结
百度、京东、蘑菇街、腾讯
阿里、华为、滴滴、百度、携程、爱奇艺、美团
百度、京东、滴滴、新浪
百度、腾讯、网易、360、去哪网
百度、头条、滴滴、阿里、搜狐
腾讯、滴滴、阿里、网易、小米、京东、美团、百度
美团、蚂蚁金服、阿里
蚂蚁金服、携程、美团、58
美团、腾讯、百度
阿里、美团、同花顺
阿里、小米、搜狗、美团、百度、腾讯、便利蜂
蚂蚁金服、链家
阿里
腾讯
小米
华为
头条、网易、美团、google、京东
腾讯、阿里
百度、阿里
蚂蚁金服、京东
知识点总结
知识点总结
知识点总结
书籍
面试书籍
高级算法
校招心路总结
校招历程
校招历程
校招历程
大数据面经,阿里,百度,头条,滴滴,美团,京东,携程
链家、58、美团、滴滴、头条、百度、腾讯
知识点

重启远程linux主机

发表于 2017-11-21 | 分类于 linux

在终端上利用ssh,不登录远程主机,直接发送重启命令

1
ssh root@192.168.8.128 'reboot'
12
MandyDragon

MandyDragon

17 日志
10 分类
12 标签
RSS
© 2018 MandyDragon
访问量 次