1.基础知识.md

页大小

linux page size is 4096 bytes

TCP报文的最大负载和报文的最小长度

MTU:最大传输单元,以太网的MTU为1500Bytes
MSS:最大分解大小,为每次TCP数据包每次传输的最大数据的分段大小,由发送端通知接收端,发送大于MTU就会被分片。
MSS默认最小为536B,最小的MTU576B,MSS = MTU - IP头(20B)- TCP头(20B)

MSL,即Maximum Segment Lifetime,一个数据分片(报文)在网络中能够生存的最长时间
TTL是 time to live的缩写,中文可以译为“生存时间”,这个生存时间是由源主机设置初始值但不是存的具体时间
RTT是客户到服务器往返所花时间(round-trip time,简称RTT),TCP含有动态估算RTT的算法

查看默认的MSL值(60s):

cat /proc/sys/net/ipv4/tcp_fin_timeout

如何解决黏包拆包

1 什么是粘包现象

  TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。

2 为什么出现粘包现象

  • (1)发送方原因
      我们知道,TCP默认会使用Nagle算法。而Nagle算法主要做两件事:1)只有上一个分组得到确认,才会发送下一个分组;2)收集多个小分组,在一个确认到来时一起发送。
      所以,正是Nagle算法造成了发送方有可能造成粘包现象。

  • (2)接收方原因
      TCP接收到分组时,并不会立刻送至应用层处理,或者说,应用层并不一定会立即处理;实际上,TCP将收到的分组保存至接收缓存里,然后应用程序主动从缓存里读收到的分组。这样一来,如果TCP接收分组的速度大于应用程序读分组的速度,多个包就会被存至缓存,应用程序读时,就会读到多个首尾相接粘到一起的包。

3 什么时候需要处理粘包现象

  (1)如果发送方发送的多个分组本来就是同一个数据的不同部分,比如一个很大的文件被分成多个分组发送,这时,当然不需要处理粘包的现象;
  (2)但如果多个分组本毫不相干,甚至是并列的关系,我们就一定要处理粘包问题了。比如,我当时要接收的每个分组都是一个有固定格式的商品信息,如果不处理粘包问题,每个读进来的分组我只会处理最前边的那个商品,后边的就会被丢弃。这显然不是我要的结果。

4 如何处理粘包现象

  • (1)发送方
      对于发送方造成的粘包现象,我们可以通过关闭Nagle算法来解决,使用TCP_NODELAY选项来关闭Nagle算法。

  • (2)接收方
      遗憾的是TCP并没有处理接收方粘包现象的机制,我们只能在应用层进行处理。

  • (3)应用层处理
      应用层的处理简单易行!并且不仅可以解决接收方造成的粘包问题,还能解决发送方造成的粘包问题。
      解决方法就是循环处理:应用程序在处理从缓存读来的分组时,读完一条数据时,就应该循环读下一条数据,直到所有的数据都被处理;但是如何判断每条数据的长度呢?

    主要有三种策略,其利弊也有简单说明:

    (1)发送固定长度的消息
    我们首先假设总长度 1000,如果我发送一个”hi”,长度不足 1000, 其他地方补全即可。但是会浪费资源,同时不能传输长度超过 1000 的报文。

    (2)使用特殊标记来区分消息间隔
    回车换行符就是一种特殊的结束分隔符
    这种方法虽然解决了长度固定的问题,但是有分隔符被使用了怎么办的问题。当然了你的系统如果不存在"#@!"三个字符转化为字节的这样的顺序,那么你就可以使用这些字节作为分隔符。但是像微信就不可以用这种方式,因为用户可能什么都会发,万一发送了个跟"#@!"字节一样的消息,就会发生混乱。

    (3)把消息的尺寸与消息一块发送

    这个就是最常规和正常的方式。dubbo 等协议都是基于这些的,因为 dubbo 也是基于 netty 来实现底层通讯的,所以速度可能会比 spring 等速度好点。
    举个简单的实现例子,我们把报文的前 4 个字节永远固定,就是一个长整数,用来声明这条报文的总长度,后面的字节当成 body。每次一方接收到报文,取出前 4 个字节进行解码,得知总长度,然后进行这个包的处理就可以了。
    如果把前面的 4 个字节,扩展到 16 字节,那就是 dubbo 协议的长度了。

    Netty 中的解决方案:
    netty 中的 decode 和 encode 已经有了很多接口,想个性化自己实现可以,也可以直接采用他们提供的。

    FixedLengthFrameDecoder。主要对应上一节中的策略 1,使用很简单。
    DelimiterBasedFrameDecoder。主要对应上一节中的策略 2,可以自定义输入自己的分隔符。
    编写自己的协议的话,主要就是约定好报头就好啦。可以参考 dubbo 的协议。

PageCache、BufferCache

简单说来,page cache用来缓存文件数据,buffer cache用来缓存磁盘数据。在有文件系统的情况下,对文件操作,那么数据会缓存到page cache,如果直接采用dd等工具对磁盘进行读写,那么数据会缓存到buffer cache。

开源实现:cachingbe

参考资料

Page cache和Buffer cache
io实践
linux tools


2.linux常用命令.md

命令大全

常用操作 https://linuxtools-rst.readthedocs.io/zh_CN/latest/index.html
命令手册 https://wangchujiang.com/linux-command/c/sed.html

操作系统查看版本

cat /etc/centos-release

uname -a
cat /proc/version
lsb_release -a
hostnamectl

cpu配置命令

查看每个物理 CPU 中 core 的个数(就是核数)

cat /proc/cpuinfo| grep "cpu cores"| uniq

查看逻辑 CPU 的个数

cat /proc/cpuinfo| grep "processor"| wc -l

查看http耗时

time curl -v "http://uat-apollometa:10080" -o /dev/null

rpm

“rpm -ql 包名”来查看具体的安装路径

vi 命令

Ctrl+f:向文件尾翻一屏
Ctrl+b;向文件首翻一屏
b或B :光标左移一个字至字首
e或E :光标右移一个字至字尾

:s/p1/p2/g:将当前行中所有p1均用p2替代

:set number
:set nonumber

grep命令

grep -rn redis -9
# -r 递归
# -n 显示行号
# -9 显示查找下面9行

more命令

more +3223947 tcp.log
/ - 使用一个模式进行搜索,并定位到下一个匹配的文本

less命令

/ - 使用一个模式进行搜索,并定位到下一个匹配的文本

n - 向前查找下一个匹配的文本

N - 向后查找前一个匹配的文本

软连接管理

unlink 软连接
ln -sfn dev_20190522131339 latest
rm latest

查看目录磁盘

du -ah --max-depth=1

上传文件

rz -bye,并且去掉弹出的对话框中“Upload files as ASCII”前的勾选。

修改dns

/etc/resolv.conf

ab test

ab -n 100 -c 10 http://test.com/
ab -n 100 -H “Cookie: Key1=Value1; Key2=Value2” http://test.com/

VI

移到行道有两个,0 和 ^ (shift+6),在行首第一个字符是空白字符时有点区别。
移到行尾是 $ (shift+4)
到结尾是G
到开头是gg
复制yy

常用软件安装

yum install java-1.8.0-openjdk-devel.x86_64

yum install locate
updatedb

二进制文件检索

grep -a

less -f -r

strings file|grep 'abc'

解压缩

解压到指定目录

tar -xvf a.gz -C ./dir

命令行操作

Ctrl + 左右键:在单词之间跳转

Ctrl + A:跳到本行的行首

Ctrl + E:跳到页尾

Ctrl + U:删除当前光标前面的所有文字(还有剪切功能)

Ctrl + K:删除当前光标后面的所有文字(还有剪切功能)

Ctrl + L:进行清屏操作

Ctrl + Y:粘贴Ctrl + U或Ctrl + K剪切的内容

Ctrl + W和Alt + D:对于当前的单词进行删除操作,W删除光标前面的单词的字符,D则删除后面的字符 

Alt + Backsapce:删除当前光标后面的单词

GLIB_C升级

[root@localhost ~]# strings /lib64/libc.so.6 |grep GLIBC_ 
[root@localhost ~]# rpm -qa |grep glibc
如下升级glibc版本到2.17做法
# wget http://ftp.gnu.org/gnu/glibc/glibc-2.17.tar.gz
# tar -xvf glibc-2.17.tar.gz
# cd glibc-2.17
# mkdir build; cd build
# ../configure --prefix=/usr --disable-profile --enable-add-ons --with-headers=/usr/include --with-binutils=/usr/bin
# make -j 8
# make install
 
查看版本,发现已升级到2.17版本
# ldd --version
# strings /lib64/libc.so.6 |grep GLIBC_

3.linux常用命令-GFW.md

服务端配置

 supervisorctl stop ssserver
 
 ssserver -c /etc/shadowsocks.json -d start
 
 supervisorctl restart kcptun
 
 ./shell-scripts/kcptun/kcptun.sh log
 

客户端kcptun 启动:

/Users/jonny/Downloads/kcptun-darwin-amd64-20190109/client_darwin_amd64 -c config.json

免费的

鲸鱼加速器
SetupVpn
谷歌访问助手


4.linux常用命令-网络.md

检查端口

* tcp检查
    nc -z -w2 10.244.0.8 31389

* udp检查
    nc -u 127.0.0.1 7777
    nc -ul -p 7777
    
查看端口:
netstat –apn
lsof -i:port

连接状态列表:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

杀进程:
kill -9 processId

pidstat -u -p 7249
pidstat -r -p 7249 1 
pidstat -d -p 7249 1 2

检查连接

- curl --connect-timeout 2  -i http://install.ren

- wget http://install.ren

查杀端口

netstat -nltp
netstat -tunpl | grep 端口号
netstat –anp | grep 8080 或者 名称
lsof -i tcp:port 

网络情况

netstat -nat | grep -iw "8989" | wc -l
netstat -anp | grep ESTABLISHED | wc -l

当服务器维持30000个socket连接时,使用netstat和ss命令统计连接数的耗时情况如下:
[root@wang ~]# netstat -at | wc -l     //耗时15.60秒 
[root@wang ~]# ss -atr | wc -l          //耗时5.40秒(未利用tcp_diag) 

ss -a 查看机器的socket连接数
ss -l 查看机器的端口情况
ss -s 查看机器的网络连接数

抓包,防止包截断:

tcpdump -s0
tcpdump -i eth0 dst host 172.20.49.153 -A -s0
tcpdump -i eth0 dst host 10.69.10.27 and port 10080 and 'ip[2:2] > 10240' -A 

更多:https://www.cnblogs.com/ggjucheng/archive/2012/01/14/2322659.html

文件描述符

  • 查看系统当前打开的文件描述符数量

sudo cat /proc/sys/fs/file-nr

  • 查看某个进程打开的文件描述符数量

lsof -p 20262 |wc -l

  • 查看描述符排行
[root@master1] ~$ lsof -n |awk '{print $10}'|sort |uniq -c |sort -nr|head -10

更多:https://blog.csdn.net/fanren224/article/details/79971359


5.系统配置调优.md

cpu

可以用下面的命令将 cpu 占用率高的线程找出来:
ps H -eo user,pid,ppid,tid,time,%cpu,cmd --sort=%cpu

cat /proc/cpuinfo

物理CPU个数: cat /proc/cpuinfo |grep "physical id"|sort |uniq|wc -l
每个CPU物理核数: cat /proc/cpuinfo |grep "cpu cores"|uniq
每个CPU逻辑核数: cat /proc/cpuinfo |grep "siblings"|uniq
总CPU逻辑核数: cat /proc/cpuinfo |grep -c "processor"
我的服务器是两个芯片组,每个芯片组是10核,支持超线程,所以逻辑CPU是40。
超线程指物理内核+逻辑内核,芯片上只存在一个物理内核,但是这个物理内核可以模拟出一个逻辑内核,于是系统信息就显示了两个内核,一真一假。

内存

free -h

PID

pidstat -u -p 7249
pidstat -r -p 7249 1
pidstat -d -p 7249 1 2

使用pidstat进行问题定位时,以下命令常被用到:

pidstat -u 1
pidstat -r 1
pidstat -d 1
以上命令以1秒为信息采集周期,分别获取cpu、内存和磁盘IO的统计信息。

内存清除

sync
To free pagecache:
echo 1 > /proc/sys/vm/drop_caches

To free dentries and inodes:
echo 2 > /proc/sys/vm/drop_caches

To free pagecache, dentries and inodes:
echo 3 > /proc/sys/vm/drop_caches

资料

vmstat - 内存,进程和分页等的简要信息。
iostat - CPU统计信息,设备和分区的输入/输出统计信息。

单位-S m
https://linux.cn/article-4024-1.html


6.Linux故障诊断.md

strace

strace -o output.txt -T -tt -e trace=all -p 28979
上面的含义是 跟踪28979进程的所有系统调用(-e trace=all),并统计系统调用的花费时间,以及开始时间(并以可视化的时分秒格式显示),最后将记录结果存在output.txt文件里面。

/var/log/messages

dmesg | grep java


7.linux 性能调优.md

iostat

iostat属于sysstat软件包。可以直接安装。

yum install sysstat

https://www.cnblogs.com/ftl1012/p/iostat.html

iperf

yum install epel-release
yum update
yum install iperf

1.在需要测试的电脑上,以服务器模式启动iperf

iperf -s

2.在第二台电脑上,以客户端模式启动iperf连接到第一台电脑,替换198.51.100.5为地台电脑的ip地址

iperf -c 198.51.100.5

3.这时可以在第一步中的服务端终端看到连接和结果,类似下图


Server listening on TCP port 5001
TCP window size: 85.3 KByte (default)
------------------------------------------------------------
[ 4] local 198.51.100.5 port 5001 connected with 198.51.100.6 port 50616
[ ID] Interval Transfer Bandwidth
[ 4] 0.0-10.1 sec 1.27 GBytes 1.08 Gbits/sec

TIME_WAIT调优

TIME_WAIT状态是怎么产生的

HTTP协议头里面加上connection:keep-alive当然能解决这个问题。

还有的方法就是系统参数调优:

sysctl net.ipv4.tcp_tw_reuse=1
sysctl net.ipv4.tcp_tw_recycle=1
sysctl net.ipv4.tcp_timestamps=1

tcp_tw_reuse
这个参数作用是当新的连接进来的时候,可以复用处于TIME_WAIT的socket。默认值是0。

tcp_tw_recycle和tcp_timestamps
默认TIME_WAIT的超时时间是2倍的MSL,但是MSL一般会设置的非常长。如果tcp_timestamps是关闭的,开启tcp_tw_recycle是没用的。但是一般情况下tcp_timestamps是默认开启的,所以直接开启就有用了。


8.linux设计和架构.md

定时器

时间轮: https://www.pianshen.com/article/4402681742/

cpu分配

进程调度-时间片轮转算法


9.shell代码.md

循环

for i in {1..1000}
do
curl --location --request GET 'http://fat-bff-admin.d.cn/general/bffApiDebug' --data-raw '{"platformCode":"Android"}'
done

Copyright © 2018 INSTALL.REN