【问题小解决】PID耗尽的危害

如何判断 PID 耗尽

首先要确认当前的 PID 限制,检查全局 PID 最大限制:

1
cat /proc/sys/kernel/pid_max

也检查下线程数限制:

1
cat /proc/sys/kernel/threads-max

再检查下当前用户是否还有ulimit限制最大进程数。

确认当前实际 PID 数量,检查当前用户的 PID 数量:

1
ps -eLf | wc -l

如果发现实际 PID 数量接近最大限制说明 PID 就可能会爆满导致经常有进程无法启动, 低版本内核可能报错:Cannot allocate memory,这个报错信息不准确, 在内核 4.1 以后改进了: https://github.com/torvalds/linux/commit/35f71bc0a09a45924bed268d8ccd0d3407bc476f

Read more...

【问题小解决】MySQL高可用集群之双主多从

通常MySQL主从复制主要用来解决读写分离,分担服务器压力。MySQL互为主备实现服务的高可用;这里同时基于高可用和负载均衡。

mysql-ha

环境准备

主机名/角色VIPIP地址操作系统MySQL版本
Node0/master1172.16.10.100172.16.10.10CentOS8.1.19118.0.17
Node1/master2172.16.10.11CentOS8.1.19118.0.17
Node2/slave1172.16.10.12CentOS8.1.19118.0.17

安装MySQL

在所有节点上执行dnf -y install mysql mysql-server,并在master节点上配置server-id并开启bin-log

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
vi /etc/my.cnf.d/mysql-server.cnf
[mysqld]
# 主数据库端ID号,全局唯一,通常用IP地址最后一位
server_id = 10
# 开启二进制日志
log-bin = mysql-bin
# 需要复制的数据库名,如果复制多个数据库,重复设置这个选项即可
binlog-do-db = test
# 将从服务器从主服务器收到的更新记入到从服务器自己的二进制日志文件中
log-slave-updates
# 控制binlog的写入频率。每执行多少次事务写入一次(这个参数性能消耗很大,但可减小MySQL崩溃造成的损失)
sync_binlog = 1
# 下面这两个参数非常重要
# 这个参数一般用在主主同步中,用来错开自增值, 防止键值冲突,master2上面改为2
auto_increment_offset = 1
# 这个参数一般用在主主同步中,用来错开自增值, 防止键值冲突
auto_increment_increment = 2
# 二进制日志自动删除的天数,默认值为0,表示“没有自动删除”,启动时和二进制日志循环时可能删除
expire_logs_days = 7
# 将函数复制到slave
log_bin_trust_function_creators = 1

执行systemctl enable --now mysqld运行Mysql

Read more...

【生产问题】分享一次Nginx正向代理的需求

最近接到了一个需求:通过 Nginx 代理把现网一个自研代理程序给替换掉,感觉有点意思,也有所收益,简单分享下。

需求背景

部门的生产环境异常复杂,有部分第三方引入的系统位于特殊网络隔离区域,请求这些系统需要通过 2 层网络代理,如图所示:

12

中心源系统请求目标系统 API 的形式各异,我简单收集了下,至少有如下 3 种:

1
2
3
4
5
curl --digest -u admin:xxxxxx 'http://10.xxx.xxx.xxx:8080/foo/boo?Id=123456789&vId=1234' 
 
curl -d '{"eventId": 20171116, "timestamp": 123456, "caller": "XXP", "version": "1.0", "interface": {"interfaceName": "XXPVC", "para": {"detail": {"owner": "xxxxxxx"}}}, "password": "xxxxxx", "callee": "XXPVC"}' http://10.x.x.x:8080/t/api
 
curl -X PUT -H "Content-Type: application/json" -d'{"vp":{"id":"ab27adc8-xxx-xxxx-a732-fbde162ebdd3"}}' "http://10.x.x.x/v1.0/peers/show_connectioninfos"
Read more...

【基础知识】Linux的xargs命令

昨天在给服务器做年终“大扫除”整理时,发现有个目录下因为文件过多而删除失败,最终使用xargs才搞定,于是顺便来记录下。

在执行某些命令时,当 Linux 某个目录下文件过多就会因为“参数列表过长”而报错无法执行。比如,我要清空/var/spool/clientmqueue/下的庞大数量的临时文件, 如果直接执行rm -f *,有时就会会出现“参数列表过长”的错误提示,因为 linux 下一般的命令的参数的总长度不能超过 4096 个字节。

这时,xargs就应该上场了了,由于服务器数量很多,我直接在每台服务器上执行如下命令,即可清理此文件夹内的所有文件:

1
2
#代码中的$8,不通系统发行版本可能有所区别,具体使用 ls -l 查看文件名在那一列即可
cd /var/spool/clientmqueue/  && ls -l /var/spool/clientmqueue/ | awk {'print $8'} | xargs rm -f
Read more...

【网络编程】从Linux角度以及JVM源码,深入NIO的细节

最近一段时间都在啃Linux内核, 也给了自己机会再度深入理解Java的NIO实现,希望能获得更多东西,尝试理解以前未能理解的,会涉及少量OpenJDK源码。

因为NIO本身的实现很多牵扯到操作系统,所以需要先稍微过一下,有理解不对的地方,请指出。

1、涉及的Linux知识

1.1、文件描述符

对于Linux来说,一切皆为文件,设备文件、IO文件还是普通文件,都可以通过一个叫做文件描述符(FileDescriptor)的东西来进行操作,其涉及的数据结构可以自行了解VFS。

1.1.1、设备阻塞与非阻塞

任意对设备的操作都是默认为阻塞的,如果没有或有不可操作的资源,会被添加到wait_queue_head_t中进行等待,直到被semaphore通知允许执行。此时可以通过fcntl()函数将文件描述符设置为非阻塞,若没有或有不可操作的资源,立即返回错误信息。

1.2、JVM内存结构 & 虚拟地址空间

众所周知,Linux下的每一进程都有自己的虚拟内存地址,而JVM也是一个进程,且JVM有自己的内存结构。既然如此,两者之间必有对应关系,OracleJDK7提供了NMT,用jcmd pid VM.native_memory detail可以查看各类区域的reserved,被committed的内存大小及其地址区间,再通过pmap -p可以看到进程内存信息。

肉眼对比地址区间可以发现,JVM heap是通过mmap分配内存的,位于进程的映射区内,而进程堆区可以被malloc进行分配,对应关系如图。 jvm内存虚拟地址

Read more...

Linux常用命令详解

  • ls
1
2
3
4
5
ls                # 显示当前目录的内容
ls -la            # 显示当前目录的所有文件(包括隐藏文件),并显示详细信息
ls /home/user     # 显示指定目录的内容
ls -R             # 递归地列出目录内容,包括子目录及其内容
ls -h             # 与 -l 结合使用,显示文件大小以可读形式(如 KB、MB)
  • touch
1
2
3
touch newfile.txt          # 创建一个名为 newfile.txt 的空文件
touch file1 file2          # 创建多个文件(file1 和 file2)
touch -c existingfile.txt  # 如果文件存在,则更新时间戳;如果不存在,不会创建新文件
  • cat
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# 使用 -n 选项:为每行添加行号,包括空行
cat -n file.txt
# 输出示例:
#  1  This is a line.
#  2  
#  3      This is indented.
#  4  Another line.
# 注:此选项为文件中的每一行编号,从 1 开始计数。

# 使用 -b 选项:为非空行添加行号,空行不编号
cat -b file.txt
# 输出示例:
#  1  This is a line.
# 
#  2      This is indented.
#  3  Another line.
# 注:与 -n 类似,但只为非空行编号。

# 使用 -s 选项:压缩连续的空行,只显示一个空行
cat -s file.txt
# 输出示例:
# This is a line.
# 
#     This is indented.
# Another line.
# 注:多个连续空行会被压缩为一个空行。

# 使用 -E 选项:显示每行末尾的 $ 符号,标示行的结束
cat -E file.txt
# 输出示例:
# This is a line.$
# $
#     This is indented.$
# Another line.$
# 注:在每一行的末尾加上 "$" 以标示行结束,有助于确认行尾换行符的位置。

# 使用 -T 选项:将 Tab 字符显示为 ^I
cat -T file.txt
# 输出示例:
# This is a line.
# 
# ^IThis is indented.
# Another line.
# 注:将 Tab 字符用 ^I 进行可视化显示,这样方便辨认文件中的制表符。

# 使用 -A 选项:显示所有不可见字符,等同于 -vET
cat -A file.txt
# 输出示例:
# This is a line.$
# $
# ^IThis is indented.$
# Another line.$
# 注:显示不可见字符、换行符 ($) 和制表符 (^I),有助于检查文件中所有控制字符和隐藏字符。
  • kill
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
kill -l
# 输出示例:
#  1) SIGHUP   2) SIGINT   3) SIGQUIT   4) SIGILL   5) SIGTRAP   ...
# 注:列出系统支持的所有信号,以及信号的编号。每个信号都有不同的作用,例如 `SIGHUP` 代表挂起、`SIGKILL` 表示强制终止等。

kill -9 1234
# 注:向进程 ID 为 1234 的进程发送 `SIGKILL` 信号(9),强制终止该进程。
# 该信号会立即结束进程,无法被捕获或忽略,通常用于无法响应 `SIGTERM` 的进程。
# 没有 -9,默认终止信号 (SIGTERM)

kill -HUP 1234
# 注:向进程 ID 为 1234 的进程发送 `SIGHUP` 信号(1)。
# 通常用于让守护进程重新加载配置,而不是完全终止。

# SIGHUP (1):挂起信号,通常用于让进程重新读取配置文件,比如 nginx、cron
# SIGINT (2):中断信号,通常由 Ctrl+C 发送
# SIGQUIT (3):退出信号,产生核心转储
# SIGKILL (9):强制终止信号,不能被忽略或捕获
# SIGTERM (15):请求终止信号,进程可以捕获并自行处理
# SIGSTOP:停止进程,类似于 Ctrl+Z,不能被捕获
Read more...

Oh My Zsh自动补全

shell 有多种,大多数人接触比较多的是 bash, 不管是 mac 还是各个 linux 发行版,默认的 shell 基本都是 bash, 虽然 bash 功能已经丰富了,但对于极客们来说,界面不够炫,提示功能也不够强大。而 zsh 功能及其强大,只是配置过于复杂, 后来就有了 oh-my-zsh 开源项目,配置难度大大降低。 Github地址: https://github.com/robbyrussell/oh-my-zsh 安装 1 sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" 更改系统默认 shell 1 chsh -s /bin/zsh 更改zsh配置文件 1 vim ~/.zshrc 修改主题 1 ZSH_THEME="robbyrussell" 配置插件 oh-my-zsh 还支持插件,插件存放目录为: 1 ~/.oh-my-zsh/plugins 这个目录中每个子目录都是一个插件,目录名即为插件名,默认不开启,需要在~/.zshrc中该配置开启,比如: 1 2 3 4 5 6 7 8 9 10 11 plugins=( git git-flow docker kubectl brew npm helm zsh-autosuggestions zsh-syntax-highlighting ) 这些插件可以给你常用的命令做用法提示,使用 tab 键触发。我这里再推荐另外三个不是内置的插件, 需要将它们单独下载到~/.
Read more...

Grep无法查找shell传过来的变量?

差不多两周前,同事告诉我发现一个诡异的问题,grep 无法搜索 shell 中的变量,着实很惊讶。到他所说的服务器上试了下,还真是不行!

大概就是这样一个要求:

  1. 有个文本为 userid.txt,里面每一行一个用户 id,类似如下:
1
2
3
4
5
0001
0003
0005
0007
0009
  1. 另外还有一个文本为 record.txt,里面是所有用户的操作记录,一行一条,并且包含有 id,类似如下:
1
2
3
4
5
6
7
8
9
[12 11 2014 11:03,198 INFO] userId:0001 gilettype:3
[12 11 2014 12:12,198 INFO] userId:0002 gilettype:3
[12 11 2014 13:02,198 INFO] userId:0003 gilettype:1
[12 11 2014 14:33,198 INFO] userId:0001 gilettype:3
[12 11 2014 15:13,198 INFO] userId:0002 gilettype:2
[12 11 2014 16:43,198 INFO] userId:0003 gilettype:1
[12 11 2014 17:32,198 INFO] userId:0001 gilettype:3
[12 11 2014 18:16,198 INFO] userId:0002 gilettype:1
[12 11 2014 19:25,198 INFO] userId:0003 gilettype:2
Read more...