Rootop 服务器运维与web架构

2019-03-29
发表者 Venus
什么是2MSL已关闭评论

什么是2MSL

原文:https://blog.csdn.net/xiaofei0859/article/details/6044694

MSL是Maximum Segment Lifetime英文的缩写,中文可以译为“报文最大生存时间”。
他是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。
因为tcp报文(segment)是ip数据报(datagram)的数据部分,具体称谓请参见《数据在网络各层中的称呼》一文,而ip头中有一个TTL域,TTL是time to live的缩写,中文可以译为“生存时间”,这个生存时间是由源主机设置初始值但不是存的具体时间,而是存储了一个ip数据报可以经过的最大路由数,每经过一个处理他的路由器此值就减1,当此值为0则数据报将被丢弃,同时发送ICMP报文通知源主机。RFC 793中规定MSL为2分钟,实际应用中常用的是30秒,1分钟和2分钟等。

2MSL即两倍的MSL,TCP的TIME_WAIT状态也称为2MSL等待状态,当TCP的一端发起主动关闭,在发出最后一个ACK包后,即第3次握手完成后发送了第四次握手的ACK包后就进入了TIME_WAIT状态,必须在此状态上停留两倍的MSL时间,等待2MSL时间主要目的是怕最后一个ACK包对方没收到,那么对方在超时后将重发第三次握手的FIN包,主动关闭端接到重发的FIN包后可以再发一个ACK应答包。在TIME_WAIT状态时两端的端口不能使用,要等到2MSL时间结束才可继续使用。当连接处于2MSL等待阶段时任何迟到的报文段都将被丢弃。不过在实际应用中可以通过设置SO_REUSEADDR选项达到不必等待2MSL时间结束再使用此端口。

TTL与MSL是有关系的但不是简单的相等的关系,MSL要大于等于TTL。

centos7下默认是60秒

[root@localhost ~]# cat /proc/sys/net/ipv4/tcp_fin_timeout
60

另外可以参考知乎的回答:https://www.zhihu.com/question/67013338

2019-03-19
发表者 Venus
awk的几个常用用法已关闭评论

awk的几个常用用法

以passwd文件中的2行测试:
[root@rootop ~]# cat passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin

# 默认awk以空格或制表符做为分隔符,通过-F可以指定分隔符
格式:
awk -F '分隔符' # 单引号、双引号都可以

[root@rootop ~]# cat passwd  | awk -F ":" '{print $1}' # 通过stdin标准输入做为要处理的数据
root
bin

[root@rootop ~]# awk -F ":" '{print $1}' passwd # 通过指定文件做为要处理的数据
root
bin

$1为打印分隔后的第几列

# 通过打印 NF 变量可以看到有几列
[root@rootop ~]# awk -F ":" '{print NF}' passwd 
7
7

# 通过打印 NF 列可以打印最后一列
[root@rootop ~]# awk -F ":" '{print $NF}' passwd 
/bin/bash
/sbin/nologin

# 打印倒数第二列
[root@rootop ~]# awk -F ":" '{print $(NF-1)}' passwd 
/root
/bin

# 打印第一列并打印倒数第二列组成一行
[root@rootop ~]# awk -F ":" '{print $1$(NF-1)}' passwd 
root/root
bin/bin

# 如果中间想加个字符串可能会想到这么做
[root@rootop ~]# awk -F ":" '{print $1 "string" $(NF-1)}' passwd 
rootstring/root
binstring/bin

可以看到是连接在一起,没有分隔(第一列、字符串、第二列之间没有空格)

# 正确方法用逗号隔开,逗号表示添加空格
[root@rootop ~]# awk -F ":" '{print $1,"string",$(NF-1)}' passwd 
root string /root
bin string /bin

# 计算长度
[root@rootop ~]# awk -F ":" '{print length($1)}' passwd 
4
3

# 过滤结果 通过{}花括号外的 /条件/ 实现过滤
[root@rootop ~]# awk -F ":" '/ro/ {print $1}' passwd 
root

类似于用grep过滤结果
[root@rootop ~]# awk -F ":" '{print $1}' passwd | grep ro
root

2019-03-15
发表者 Venus
nginx压力测试碰到的问题已关闭评论

nginx压力测试碰到的问题

服务器端的问题:
1、/var/log/messages中报错:

Mar 15 15:46:13 localhost kernel: TCP: request_sock_TCP: Possible SYN flooding on port 80. Dropping request.  Check SNMP counters.

这是内核检测到可能受到syn攻击,丢弃了接下来的请求。
通过net.ipv4.tcp_syncookies = 0可以关闭内核检测syn洪水攻击。

把/etc/sysctl.conf内核参数优化成如下:

net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_max_syn_backlog = 20000
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1

上面参数可以从:https://www.rootop.org/pages/2529.html 找到解释

客户端的问题:
1、apache自带的ab压力测试工具并发高了会提示:socket: Too many open files (24)
这是本地系统文件最大打开数的问题,压力测试工具会模拟大量客户端发起请求,只要发起请求就得创建socket连接-socket句柄等于文件句柄,本地会打开一个端口与服务器连接。
通过修改/etc/security/limits.conf中软、硬限制加大最大打开数。但是会受到系统资源限制。

# 内核限制级别文件句柄,这个值查资料说是由系统根据硬件配置自动计算出来限制整个系统。
# 不过也可以由 sysctl.conf 中 fs.file-max = 2000000改变

[root@localhost ~]# cat /proc/sys/fs/file-max
1609786

# 单个进程限制级别文件句柄 默认1024*1024

[root@localhost ~]# cat /proc/sys/fs/nr_open
1048576

# 如果用ulimit或者 /etc/security/limits.conf 设置最大打开数,不能超过 nr_open 值,否则会报错。
[code type="shell"]
[root@localhost ~]# ulimit -n 1048577 
-bash: ulimit: open files: cannot modify limit: Operation not permitted

如果通过 limits.conf 修改超过nr_open,重启后就会无法登陆系统。

# 如果想增大ulimit -n,则需要先修改nr_open最大值。

[root@localhost ~]# vi /etc/sysctl.conf 
fs.nr_open = 2000000
[root@localhost ~]# sysctl -p

[root@localhost ~]# cat /proc/sys/fs/nr_open 
2000000
[root@localhost ~]# ulimit -n 2000000
[root@localhost ~]#  # 没有报错

上面2个配置参数同样对服务端有效。
2、apache自带的ab工具测试并发高了会提示:apr_socket_recv: Connection reset by peer (104)
此原因就是服务器端内核认为是受到了syn洪水攻击而发送了RST重置标识位。(具体去看TCP/IP协议)

3、fork failed.: Resource temporarily unavailable
此错误为用户运行的进程数量达到系统限制

通过ulimit可以查看当前用户可以运行多少个进程(max user processes字段)
[root@localhost html]# ulimit -u
7244

临时加大:
[root@localhost html]# ulimit -u 20000

永久配置:

[root@localhost ~]# cat /etc/security/limits.conf
* soft nofile 2000000
* hard nofile 2000000
* soft nproc 20000
* hard nproc 20000

2019-03-13
发表者 Venus
mysql事务隔离级别已关闭评论

mysql事务隔离级别

断断续续研究mysql数据库的隔离级别,理解起来比较抽象,来回看了很多次才整理了如下总结。

先解释3个名词。

脏读:
如果事务1修改了数据,事务2读取了数据,但是由于某种原因回滚了事务1,事务2读到的数据就变为脏数据。
(简单理解为只要发生回滚动作的情况下产生的数据变化)

幻读:
比如事务1根据sql语句中的where条件获取了N条数据,事务1还未结束,事务2新增了符合where条件的X条数据,事务1再次执行sql就发现多出来一些数据。
(简单理解为符合条件索引多出来的数据变化)

不可重复读:
比如事务1获取了一条数据,事务2修改了这条数据,事务1再获取这条数据,发现变了。
(简单理解为没有发生回滚的情况下产生的数据变化)

PS:在不同的隔离级别下,出现上面的情况也不一样。

1、read uncommitted 读取未提交的数据
解释:两个事务,事务1写入了一条数据但是还未提交,事务2就可以读取到这条数据。
存在的问题:脏读、幻读、不可重复读

2、read committed 读取已提交的数据 (Oracle数据库的默认隔离级别)
解释:事务1未提交,事务2提交了新数据,事务1可以获取事务2提交的数据。可以解决脏读问题。
存在的问题:幻读、不可重复读

3、repeatable read 可重复读数据 (mysql的默认隔离级别)
解释:事务1在启动时给数据库”创建一个快照”,随后事务1在未提交之前所读取的数据都从这个快照中获取。即使其他事务修改了数据也不受影响。
不存在脏读、幻读、不可重复读(通过MVCC多版本并发控制解决不可重复读问题)

4、serializable 串行化:可以解决 脏读 不可重复读 和 虚读 -相当于锁表
没研究,不解释~

2019-03-13
发表者 Venus
mysql死锁 Deadlock found when trying to get lock; try restarting transaction已关闭评论

mysql死锁 Deadlock found when trying to get lock; try restarting transaction

研究了一下mysql的死锁,记录如下。
比如有2个事务,执行的sql分别如下:
这里用 #N 标识sql语句的执行顺序,下面开启两个mysql客户端连接,其中表的id为主键。

事务1
START TRANSACTION; #1
UPDATE username SET `name` = 't1' WHERE id = 1; #3
UPDATE username SET `name` = 't1' WHERE id = 2; #5
COMMIT;
事务2
START TRANSACTION; #2
UPDATE username SET `name` = 't2' WHERE id = 1; #6
UPDATE username SET `name` = 't2' WHERE id = 2; #4
COMMIT;

死锁:当出现2个(以上)事务互相等待对方释放锁的时候就会出现死锁。
PS:不管两个事务执行什么sql语句,只要出现互相等待对方释放就发生了死锁问题。

1、当执行#1 #2时两条事务开始
2、当执行#3 时,事务1将id=1的这条数据加锁(当sql语句执行时才加锁,事务开始时不会加)
3、当执行#4 时,事务2将id=2的这条数据加锁
4、当执行#5 时,事务1等待事务2释放锁(锁是在事务提交以后才释放)
此时,通过information_schema库INNODB_TRX事务表中查看正在运行的事务,注意2个事务中trx_weight的最小值,后续死锁时mysql可以确定需要回滚哪个事务。


5、当执行#6 时,事务2与事务1发生死锁。

mysql会报一个错误:Deadlock found when trying to get lock; try restarting transaction
通过mysql命令行执行:mysql> show engine innodb status\G; 查看mysql记录的信息(可以看到最后一次死锁)
------------------------
LATEST DETECTED DEADLOCK   # mysql检测到的最后一次死锁
------------------------
2019-03-13 11:52:13 0x7fd873618700
*** (1) TRANSACTION:  # 事务1
TRANSACTION 188912126, ACTIVE 32 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 1979385, OS thread handle 140567861790464, query id 328763106 192.168.1.1 root updating
UPDATE username SET `name` = 't1' WHERE id = 2 # 执行的sql
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 21691 page no 3 n bits 80 index PRIMARY of table `test_cjx`.`username` trx id 188912126 lock_mode X locks rec but not gap waiting
Record lock, heap no 9 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 4; hex 80000002; asc     ;;
 1: len 6; hex 00000b4291ff; asc    B  ;;
 2: len 7; hex 2b0000015101e7; asc +   Q  ;;
 3: len 2; hex 7432; asc t2;;
 4: len 4; hex 80000000; asc     ;;

*** (2) TRANSACTION:  # 事务2
TRANSACTION 188912127, ACTIVE 31 sec starting index read
mysql tables in use 1, locked 1
3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 1980464, OS thread handle 140567625434880, query id 328764925 192.168.1.1 root updating
UPDATE username SET `name` = 't2' WHERE id = 1 # 执行的sql
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 21691 page no 3 n bits 80 index PRIMARY of table `test_cjx`.`username` trx id 188912127 lock_mode X locks rec but not gap
Record lock, heap no 9 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 4; hex 80000002; asc     ;;
 1: len 6; hex 00000b4291ff; asc    B  ;;
 2: len 7; hex 2b0000015101e7; asc +   Q  ;;
 3: len 2; hex 7432; asc t2;;
 4: len 4; hex 80000000; asc     ;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 21691 page no 3 n bits 80 index PRIMARY of table `test_cjx`.`username` trx id 188912127 lock_mode X locks rec but not gap waiting
Record lock, heap no 8 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 6; hex 00000b4291fe; asc    B  ;;
 2: len 7; hex 2a00000150025c; asc *   P \;;
 3: len 2; hex 7431; asc t1;;
 4: len 4; hex 80000000; asc     ;;

*** WE ROLL BACK TRANSACTION (2)  # mysql回滚了哪个事务
------------
TRANSACTIONS
------------

可以看到mysql回滚了事务2,此事务id为 188912127,此时事务1可以提交了,最终name的值应为t1。因为事务2的trx_weight权重最小(上面图显示了权重为3),所以回滚了(释放锁)。