Showing posts with label linux. Show all posts
Showing posts with label linux. Show all posts

Monday, May 28, 2018

HTTP部分时候请求长时间卡死超时问题排查思路

部分业务方用户反映有些时候hue刷新页面会卡死2-5min无响应。个人也遇到过几次,在页面访问卡住的同时,通过curl url:8890 -I -L一样会卡住无法返回页面内容。
通过记录事故时间点反查linux TCP相关信息,发现在卡死的时刻,TCP connection数量骤增到2-3k (ss -s),同时TCcpExt的ListenDrops和TcpExt.ListenOverflows会相对较高:


此时感觉是因为sysctl中关于TCP连接的部分参数没有优化导致,所以添加了如下参数并重启了hue服务,但问题依旧。
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_max_tw_buckets = 400000
net.ipv4.tcp_orphan_retries = 1
net.ipv4.tcp_retries2 = 5
net.core.netdev_max_backlog = 512000
net.ipv4.tcp_syn_retries = 3
net.ipv4.tcp_synack_retries = 3
net.ipv4.tcp_slow_start_after_idle = 0
vm.min_free_kbytes = 360448
vm.zone_reclaim_mode = 1
net.core.somaxconn = 65535
#net.netfilter.nf_conntrack_max = 1655350
#net.netfilter.nf_conntrack_tcp_timeout_established = 7200
#net.netfilter.nf_conntrack_tcp_timeout_time_wait = 10
kernel.shmall = 4294967296
kernel.shmmax = 68719476736
kernel.msgmax = 65536
kernel.msgmnb = 65536
此时想关注下到底是哪个进程导致了TCP连接数骤增,ss -n后发现主要为:50010端口。netstat -nlp | grep :50010后发现是DataNode服务。
此时通过dmesg发现如下报错内容:
[12522087.589828] TCP: request_sock_TCP: Possible SYN flooding on port 50010. Sending cookies. Check SNMP counters.
[12547933.126955] TCP: request_sock_TCP: Possible SYN flooding on port 50010. Sending cookies. Check SNMP counters.
也即TCP连接已经全被50010吃满了,导致新来的hue请求无法正常建立connection导致用户角度的卡死和超时(参考:https://help.marklogic.com/Knowledgebase/Article/View/182/0/possible-syn-flooding-messages-in-system-logs
同时,通过sar -n DEV 3发现下行带宽已经占了1.2GB/s, 已经达到机器对应的最大下行带宽,所以数据传输不出去也是可能的因素之一。
最终,将混部的服务拆分到独立的节点,问题解决。

Monday, August 28, 2017

Monitoring Health Metrics Regarding Each Process on Linux


ps axo pid,ppid,rss,vsz,nlwp,cmd --sort=-rss,-vsz

Output columns:
  • pid - Process ID
  • ppid - Parent Process ID
  • rss - Resident Set Size - physical memory
  • vsz - Virtual Set Size - virtual memory
  • nlwp - Number of Light Weight Processes - thread count
  • cmd - Command
  • --sort
    • specify sorting order. Sorting syntax is [+|-]key[,[+|-]key[,...]]
    • Choose a multi-letter key from the STANDARD FORMAT SPECIFIERS section.
    • The "+" is optional since default direction is increasing numerical or lexicographic order.

Thursday, November 12, 2015

What Does ^m In Vim Mean And What Will It Possible Affect

There's a problem occurring to me when executing BigQuery load data operation, a seem-to-be one-line string in Vim is actually treated as multiple lines when I examining into the error log.

After opening this file in Vim, we could see that there're several ^m marks in the string (if it's not visible, invoke `:set list` command). According to Vim's digraph table, this is the representation of CARRIAGE RETURN (CR).



A specific sum-up for \r and \n is as follows:

    \r = CR (Carriage Return) // Used as a new line character in Mac OS before X
    \n = LF (Line Feed) // Used as a new line character in Unix/Mac OS X
    \r\n = CR + LF // Used as a new line character in Windows

Consequently, we should merely use \n as the new-line-character since almost all server are Unix-based, thus omitting \r when programming.

The way to replace \r\n with \n in Vim is to execute `:%s/\r//g`, whereas in CLI, we could apply `cat original_file | tr -d '\r' > remove_cr_file` to achieve the same effect.












Friday, June 12, 2015

Troubleshooting On SSH hangs and Machine Stuck When Massive IO-Intensive Processes Are Running

It is inevitable that some users will write and execute devastating code inadvertently on public service-providing machines. Hence, we should enhance the robustness of our machine to the greatest extent.

Today, one of our users forked processes as many as possible, all executing `hadoop get`. As a result, it ate up all of our IO resources even though I've constrained CPU and Memory via `cgroups` upon this specific user. At this time, the phenomenon is that we could neither interact with the prompt nor ssh to this machine anymore. I managed to invoke `top` command before it was fully stuck. This is what it shows:
top - 18:26:10 up 238 days,  5:43,  3 users,  load average: 1782.01, 1824.47, 1680.36
Tasks: 1938 total,   1 running, 1937 sleeping,   0 stopped,   0 zombie
Cpu(s):  2.4%us,  3.0%sy,  0.0%ni,  0.0%id, 94.5%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  65923016k total, 65698400k used,   224616k free,    13828k buffers
Swap: 33030136k total, 17799704k used, 15230432k free,   157316k cached

As you can see, load average is at an unacceptable peak, and %wa is above 90 (%wa - iowait: Amount of time the CPU has been waiting for I/O to complete). In the meantime, memory has swallowed almost all memory with 17GB swap space being used. Obviously, this is due to the too many processes executing `hadoop get` command.

Eventually, I set the maximum number of processes and open files that the user can fork and open respectively. In this way, conditions will be alleviated to an acceptable scenario.

The configuration is at '/etc/security/limits.conf', we have to edit it in root user. Append the following content to the file:
username      soft    nofile  5000
username      hard    nofile  5000
username      soft    nproc   100
username      hard    nproc   100

Also, there's a nice post regarding how to catch the culprit causing high IO wait in linux.

Reference:
1. Limiting Maximum Number of Processes Available for the Oracle User
2. how to change the maximum number of fork process by user in linux
3. ulimit: difference between hard and soft limits
4. High on %wa from top command, is there any way to constrain it
5. How to ensure ssh via cgroups on centos
6. fork and exec in bash



Saturday, May 30, 2015

Constrain Memory And CPU Via Cgroups On Linux

Limitations on memory and CPU is required inevitably on public-service-provided linux machines like gateways, since there are times that resources on these nodes have been eaten up by clients so that administrators could hardly ssh to the problematic machine when it's stuck.

cgroups (abbreviated from control groups) is a Linux kernel feature that limits, accounts for and isolates the resource usage (CPU, memory, disk I/O, network, etc.) of a collection of processes. And the way to limit a group of users to a specific upperbound for both memory and CPU is as follows.

Firstly, we have to install cgroups just in case it is not on your linux server. In my scenario, the environment is CentOS-6.4 and the following command will just complete the installation process (you need to enable EPEL repository on CentOS of yum command and ensure that CentOS has to be version 6.x).
yum install -y libcgroup

Make it persistent by changing it to 'on' in the runlevel you are using. (Refer to chkconfig and Run Level on Linux)
chkconfig --list | grep cgconfig
chkconfig --level 35 cgconfig on

After that, cgroups is already installed successfully.


Just before we move on to configure limitations via cgroups, we should first put all of our client users in the same group for the purpose of management as a whole. Related commands are as below:
/usr/sbin/groupadd groupname    # add a new group named groupname
usermod -a -G group1,group2 username    # apply username to group1 and group2
groups username    # To check a user's group memberships, use the groups command


Now it's time to configure memory and CPU limitation in '/etc/cgconfig.conf', to which, append the following settings:
group gateway_limit {
    memory {
        memory.limit_in_bytes = 8589934592;
    }

    cpu {
        cpu.cfs_quota_us = 3000000;
        cpu.cfs_period_us = 1000000;
    }
}

Configuration for memory is well self-explained, and that for CPU is defined in this document. In essence, if tasks in a cgroup should be able to access a single CPU for 0.2 seconds out of every 1 second, set cpu.cfs_quota_us to 200000 and cpu.cfs_period_us to 1000000. Note that the quota and period parameters operate on a CPU basis. To allow a process to fully utilize two CPUs, for example, set cpu.cfs_quota_us to 200000 and cpu.cfs_period_us to 100000. If relative share of CPU time is required, setting 'cpu.shares' could be applied. But according to this thread, 'cpu.shares' is work conservingly, i.e., a task would not be stopped from using cpu if there is no competition. If you want to put a hard limit on amount of cpu a task can use, try setting 'cpu.cfs_quota_us' and 'cpu.cfs_period_us'.

After that, we should connect our user/group with the above cgroups limitations in '/etc/cgrules.conf':
@gatewayer      cpu,memory      gateway_limit/

it denotes that for all users in group 'gatewayer', CPU and memory is constrained by 'gateway_limit' which is configured as above.

Notice that if we configure two different lines for the same user/group, then the second line setting will fail, so don't do that:
@gatewayer      memory      gateway_limit/
@gatewayer      cpu      gateway_limit/

Now we have to restart all the related services. Note that we have to switch to path '/etc' in order to execute the following commands without failure, cuz 'cgconfig.conf' and 'cgrules.conf' is available in that path.
service cgconfig restart
service cgred restart  #cgred stands for CGroup Rules Engine Daemon

Eventually, we should verify that all settings have all been hooked up to specific users as expected.

The first way to do that is to login to a user who is in group 'gatewayer', invoking `pidof bash` to check out current PID for the bash terminal. Then `cat /cgroup/cpu/gateway_limit/cgroup.procs` as well as `cat /cgroup/memory/gateway_limit/cgroup.procs` to see whether the former PID is in here. If so, it means memory and CPU is monitored by cgroups for the current user.

The second way to achieve this is a little bit simpler, for you only have to login to a user, execute `cat /proc/self/cgroup`. If gateway_limit is applied both to memory and CPU as follows, then it is well configured.
246:blkio:/
245:net_cls:/
244:freezer:/
243:devices:/
242:memory:/gateway_limit
241:cpuacct:/
240:cpu:/gateway_limit
239:cpuset:/

As for testing, here's a memory-intensive python script that could be used to test memory limitation:
import string
import random
import time

if __name__ == '__main__':
    d = {}
    i = 0;
    for i in range(0, 900000000):
        d[i] = some_str = ' ' * 512000000
        if i % 10000 == 0:
            print i

When monitoring via `ps aux | grep this_script_name`, the process is killed when the consuming cpu exceeds the upperbound set in cgroups. FYI, swappiness is currently set to 0, thus no swap space will be used when physical memory is exhausted and the process will be killed by Linux kernel. If we intend to make our Linux environment more elastic, we could modify swappiness to a higher level (default is 60).

For CPU-intensive test, referencing to this thread, the following command will be executed on the specific user to create multiple processes consuming CPU time. On another terminal window, we could execute `top -b -n 1 | grep current_user_name_or_dd | awk '{s+=$9} END {print s}'` to sum up all the dd processes CPU time.
fulload() { dd if=/dev/zero of=/dev/null | dd if=/dev/zero of=/dev/null | dd if=/dev/zero of=/dev/null | dd if=/dev/zero of=/dev/null & }; fulload; read; killall dd



Reference:
1. cgroups documentation
2. cgroups on centos6
3.1. cgrules.conf(5) - Linux man page
3.2. cgconfig.conf(5) - Linux man page
4. how-to-create-a-user-with-limited-ram-usage - stackexchange
5. how-can-i-configure-cgroups-to-fairly-share-resources-between-users - stackexchange
6. how-can-i-produce-high-cpu-load-on-a-linux-server - superuser
7. shell-command-to-sum-integers-one-per-line - stackoverflow
8. Why does Linux swap out pages when I have many pages cached and vm.swappiness is set to 0 - quora




Tuesday, January 13, 2015

Deal With Error "A semaphore set has to be created but the system limit for the maximum number of semaphore sets has been exceeded"

There are some time that a specific node in our Hadoop cluster will be stuck at ssh connection procedure, whereas ping command is traversable. When this node recovers by itself, I look through the system messages in '/var/log/messages', where all of the content is:
A semaphore set has to be created but the system limit for the maximum number of semaphore sets has been exceeded

There are some commands that we could apply to check on semaphore status. You can run ipcs -s to list all of the semaphores currently allocated on your system and then use ipcrm -s <id> to remove a semaphore (if you're reasonably sure it's no longer needed). You might also want to track down the program that created them (using information from ipcs -s -i <id>) to make sure it's not leaking semaphores.

Alternatively, you could check the semaphore setting in sysctl(8) via issuing command `sysctl -a | grep kernel.sem`, it is equivalent to invoke command `ipcs -ls`, which would show descriptions to all values:
$ /sbin/sysctl -a | grep kernel.sem
kernel.sem = 250 32000 32 128

$ ipcs -ls

------ Semaphore Limits --------
max number of arrays = 128
max semaphores per array = 250
max semaphores system wide = 32000
max ops per semop call = 32
semaphore max value = 32767

The preceding error is related with the 'max semaphores system wide', thus we could increase this value by increasing either 'max number of arrays' or 'max semaphores per array'. However, there's something should be noticed, that when revising, we should always validate the equation: (max number of arrays)*(max semaphores per array)=(max semaphores system wide).

In my case, I changed the 'max number of arrays' to 1280, and 'max semaphores system wide' to 320000 correspondingly by appending "kernel.sem = 250 320000 32 1280" to '/etc/sysctl.conf' and execute `/sbin/sysctl -p`.



Reference:
1. Answer from ServerFault
2. Power Panel process fails to start - Parallels
3. 8.5. Setting Semaphore Parameters - RedHat
4. Setting the Kernel Parameters - SYBASE



© 2014-2017 jason4zhu.blogspot.com All Rights Reserved 
If transfering, please annotate the origin: Jason4Zhu

Sunday, January 4, 2015

Deal With "java.lang.OutOfMemoryError: unable to create new native thread" Error in Java

Upon upgrading CentOS from release 5.3 to 6.4, "java.lang.OutOfMemoryError: unable to create new native thread" is thrown after starting NodeManager in Hadoop for a while. This is because in CentOS 6.x, there is limit to the number of created threads / processes, whose default setting is 1024. In CentOS 5.x, it can be more than 40000 or no limit.
//---- CentOS 5.3 ----
$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 530432
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 100000
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 530432        //Comparison 1
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

//---- CentOS 6.4 ----
$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 514891
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 100000
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1024          //Comparison 2
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Thus, we have to enlarge the maximum number of user processes by increasing the number of the following parameter in "/etc/security/limits.d/90-nproc.conf":
*          soft    nproc     1024

Eventually, start a new session for the change to take effect.




Tuesday, October 28, 2014

Find And Replace Specific Keyword In All Files From A Directory Recursively

If we intend to replace keyword '<abc>' with '<def>' in all *.java files from $ROOT_PATH, we can simply achieve this by:
find . -name "*.java" -print | xargs sed -i "" "s/<abc>/<def>/g"

The first part "find . -name "*.java" -print" will print all the relative paths of files which matches the pattern "*.java", just like:
./a.java
./dir1/b.java

Then all the output lines will be passed to sed command via xargs, thus the equivalent of the latter part is as below:
sed -i "" "s/<abc>/<def>/g" ./a.java
sed -i "" "s/<abc>/<def>/g" ./dir1/b.java

'-i' stands for:
-i[SUFFIX], --in-place[=SUFFIX]

    edit files in place (makes backup if extension supplied)

which will output the replaced file to a file.

But here's a tricky part. As mentioned above, the '-i' is optional on Ubuntu, whereas it is kind of mandatory to give '-i' a value in Mac osx, or some error like 'invalid command code .' could be thrown. Consequently, it is recommend that we add '-i ""' to our command, although it's a little bit cumbersome :)

© 2014-2017 jason4zhu.blogspot.com All Rights Reserved 
If transfering, please annotate the origin: Jason4Zhu

Friday, October 24, 2014

Linux: Kill Processes With Specific Keyword

When we are going to kill a process with specific keyword, we can simply find the PID(process id) by command as follows (PID is always shown in the second column of the result):
ps aux | grep "keyword"

Then the process can be forcibly killed by:
kill -9 PID

This method works fine when there is only one or a few processes to be terminated. As the number of process grow larger and larger, it is too painful to do it manually. Consequently, we have to deal with it in some other way.

Note: All the solutions below will kill processes which is listed on the screen via command 'ps aux | grep "keyword"'.

Solution 1:
pgrep keyword | xargs kill -9

Solution 2:
ps aux | grep keyword | awk '{print $2}' | xargs kill -9

Solution 3:
kill -s 9 `pgrep keyword`

Solution 4:
pkill -9 keyword

Pick one that you're most comfortable with :)

© 2014-2017 jason4zhu.blogspot.com All Rights Reserved 
If transfering, please annotate the origin: Jason4Zhu

Wednesday, October 22, 2014

Keep the Original Format Of Text When Pasting to Vim (A.K.A. Turning Off Auto-Indent Feature Of Vim)

Sometimes when we paste some text to vim, we are more likely to retain the format of the text. But by default, vim will add indent to our text automatically, just like:



Solution 1:
Vim provides the ‘paste’ option to maintain the pasting text unmodified:
:set paste
:set nopaste 

Solution 2:
Alternatively, vim offers the ‘pastetoggle’ option to turn ‘paste’ on and off by pressing a key. What we need to do is appending the following code in ~/.vimrc. Then we can just press key 'F2' to switch between ‘paste on’ and ‘paste off'.
set pastetoggle=<F2>


© 2014-2017 jason4zhu.blogspot.com All Rights Reserved 
If transfering, please annotate the origin: Jason4Zhu

Generate Public Key From A Private Key

When we've got the private key, say id_rsa,  we can regenerate the public key by:
ssh-keygen -f ./id_rsa -y > ./id_rsa.pub

It is well-explained in ‘man ssh-keygen’:
-y    This option will read a private OpenSSH format file and print an OpenSSH public key to stdout.
-f    Specify the private key file.


© 2014-2017 jason4zhu.blogspot.com All Rights Reserved 
If transfering, please annotate the origin: Jason4Zhu

Sunday, October 19, 2014

Search Keyword in a Specific Directory Recursively in Linux

We can search a string recursively in a directory via grep command in linux.

Do the following:

grep -r "word" . In which, -r stands for recursive.

More advanced option:

grep -ril "word" *.log -i means ignore-case;
-l will only show the file name which contains the keyword, without printing the context of the keyword.

grep --exclude=*.txt -r "word" . --exclude will search all the files in current directory whose file name does not match the pattern "*.txt".

grep --include=*.txt -r "word" * Likewise, --include is just the opposite condition of --exclude.


© 2014-2017 jason4zhu.blogspot.com All Rights Reserved 
If transfering, please annotate the origin: Jason4Zhu