netstat -s统计输出的所有字段详细解释

今天工作上碰到一个问题需要知道udp的丢包数据。实际上我不相信能简单地得到udp的丢包精确数据。理由是,网卡负载太高时有些包连网卡都没收到,根本不可能来得及汇报给内核。另外,如果是路由器把udp丢了,那udp的目的端机器当然更不可能感知到有丢包了。 这时,同事说netstat -us (–statistic)可以看到udp的丢包。这里的u选项指的是只展示udp相关的统计,s选项自然表示的是统计了。如果不用u选项,则出显示所有统计数据。下面是我的机器上的输出。 Ip: 203440255187 total packets received 0 forwarded 0 incoming packets discarded 201612429535 incoming packets delivered 1064529177 requests sent out 15 fragments dropped after timeout 3058122492 reassemblies required 1230296840 packets reassembled ok 15 packet reassembles failed Icmp: 14869220 ICMP messages received 3965512 input ICMP message failed. ICMP input histogram: destination unreachable: 6054246 timeout in transit: 687 echo requests: 8570532 echo replies: 243755 12913011 ICMP messages sent 0 ICMP messages failed ICMP output histogram: destination unreachable: 4097869 time exceeded: 5 echo request: 244605 echo replies: 8570532 IcmpMsg: InType0: 243755 InType3: 6054246 InType8: 8570532 InType11: 687 OutType0: 8570532 OutType3: 4097869 OutType8: 244605 OutType11: 5 Tcp: 111681768 active connections openings 4186820 passive connection openings 24951865 failed connection attempts 55064041 connection resets received 275 connections established 1033901799 segments received 1776166765 segments send out 12156205 segments retransmited 6705 bad segments received. 106348033 resets sent Udp: 198894689917 packets received 472986510 packets to unknown port received. 1146976531 packet receive errors 116750744 packets sent 110301286 receive buffer errors 0 send buffer errors UdpLite: TcpExt: 423 invalid SYN cookies received 693 packets pruned from receive queue because of socket buffer overrun 19 packets pruned from receive queue 11309370 TCP sockets finished time wait in fast timer 106 packets rejects in established connections because of timestamp 10210477 delayed acks sent 20811 delayed acks further delayed because of locked socket Quick ack mode was activated 8856 times 17118697 packets directly queued to recvmsg prequeue. 301717551 bytes directly in process context from backlog 152118951904 bytes directly received in process context from prequeue 104771733 packet headers predicted 15179703 packets header predicted and directly queued to user 218747377 acknowledgments not containing data payload received 102637644 predicted acknowledgments 7293 times recovered from packet loss by selective acknowledgements Detected reordering 40 times using FACK Detected reordering 27 times using SACK Detected reordering 1088 times using time stamp 476 congestion windows fully recovered without slow start 5287 congestion windows partially recovered using Hoe heuristic 236 congestion windows recovered without slow start by DSACK 151673 congestion windows recovered without slow start after partial ack 1 timeouts after reno fast retransmit 4 timeouts after SACK recovery 10540 timeouts in loss state 7232 fast retransmits 649 forward retransmits 1871 retransmits in slow start 11612658 other TCP timeouts TCPLossProbes: 93185 TCPLossProbeRecovery: 14667 2431 packets collapsed in receive queue due to low socket buffer 8814 DSACKs sent for old packets 3350 DSACKs received 1 DSACKs for out of order packets received 90851 connections reset due to unexpected data 214 connections reset due to early user close 352 connections aborted due to timeout TCPDSACKIgnoredNoUndo: 1571 TCPSpuriousRTOs: 7 TCPSackShifted: 94 TCPSackMerged: 131 TCPSackShiftFallback: 21183 TCPTimeWaitOverflow: 1876775 TCPRcvCoalesce: 15711184 TCPOFOQueue: 3194 TCPChallengeACK: 2337394 TCPSYNChallenge: 13608 TCPSpuriousRtxHostQueues: 1982796 IpExt: InBcastPkts: 46443933 InOctets: 44312451521655 OutOctets: 1915626725817 InBcastOctets: 6827280595 喂,要是转载文章。麻烦贴一下出处 ykyi.net 采集爬虫把链接也抓走 ...

November 23, 2018 · 3 min · kamus

Linux系统级/进程级最多打开文件数,FD文件描述符数

如何增加Linux系统最大文件打开数目呢? 查看系统最大可打开文件数 以下命令查看操作系统级最多可打开文件数,fd数目 $ cat /proc/sys/fs/file-max 我用ubuntu 16输出: 573738 怎么调整系统最大可打开文件数 # sysctl -w fs.file-max=1000000 需要用root用户执行以上命令,设最大为一百万。 但在命令行上修改了这个配置,会在下一次操作系统重启后重置为以前的值。要一劳永逸的改变系统最大打开文件数,需要修改 /etc/sysctl.conf 文件。 fs.file-max = 1000000 在/etc/sysctl.conf文件中增加上述一行。 ulimit命令查看/调整进程级最大文件打开数 $ ulimit -Sn 1024 这个命令查看一个ulimit的软极限值(soft limit),本用户起的进程的最大文件打开数的限制。我的ubuntu 16显示进程最多开1024个fd。如果要提高每个进程可同时打开的文件数,需要更改这个值。 $ ulimit -Sn 2048 bash: ulimit: open files: cannot modify limit: Invalid argument 但我想把每个进程可同时打开的文件数增加到以前的两倍时,报错了。这是因为,软极限值(soft limit)不能够越过(Hard Limit)。我看了一下Hard limit,也是1024 $ ulimit -Hn 1024 那没办法罗,需要以root用户登录更改Hard Limit。 怎么修改普通用户的硬极限hard Limit 用root账户登录后,编辑 /etc/security/limits.conf文件,假如普通用户名是kamuszhou。 kamuszhou hard nofile 10000 kamuszhou soft nofile 5000 以上配置修改kamuszhou普通用户的最多打开文件数的hard limit为10000,soft limit为5000。 对于ubuntu 16,如果使用图形桌面,还需要修改 /etc/systemd/system.conf 和 /etc/systemd/user.conf。 加上这么一行: ...

November 22, 2018 · 1 min · kamus

如何定制一个python的logging Handler

上个月用python的gevent协程库写了一个tcp服务。日志库使用python标准日志库logging。一个月后,发现一个偶发的bug。这个bug发生时,用python的标准日志库自带的FileHandler写的日志会发往socket占用的文件描述符fd。结果就是,客户端收到了本要打印到磁盘上的日志。花了不少时间定位排查这个bug,仍然没有结果。我开始怀疑是gevent协程库和python的标准日志库logging有冲突。协程库会错误的把logging打开的文件描述符fd关闭并分配给新创建的socket,于是日志就打印到socket占用的fd了。 后来,写了一个检测脚本用来监控这个情况发生的概率。该脚本每分钟会检查进程占用的所有fd,一但发现用来打印本地日志的文件fd不见了,就重启服务进程。核心代码如下: lsof -p $pid | grep -q ${log_file_name} if [ $? != 0 ] then # 报警代码 ... fi 发现bug发生的频率大概是一个星期一次。但这毕竟根本上解决不了问题啊,又找不到bug的原因,怎么办? 那就自定义一个File Handler吧! 决定自定义一个File Handler,这个File Handler工作在另外一个单独的进程,这样无论如何日志用的fd都不会跟主进程的各种socket用的fd冲突了吧。 代码如下,主要用到的技术进程通讯和用python的__getattribute__魔法把截获类实例的方法调用。这样,只需要把旧的代码中的File Handler(我用了TimedRotatingFileHandler)换成自定义的Handler Class,所有其他旧代码都无需改动。 #!/usr/bin/env python3 ''' created by kamuszhou*AT*tencent.com, zausiu*AT*gmail.com http://ykyi.net Nov 20, 2018 ''' import logging import logging.handlers from functools import partial from multiprocessing import Process, Queue class MySpecialHandler(logging.StreamHandler): def __init__(self, *args, **kargs): self._q = Queue() self._p = Process(target=MySpecialHandler.__run, args=(self._q,)) self._p.start() self._q.put(('__init__', args, kargs)) def join(self): self._p.join() def __run(q): handler = None while True: # op, params = q.get() method, args, kwargs = q.get() if method == '__init__': handler = logging.handlers.TimedRotatingFileHandler(*args, **kwargs) else: # 主进程的日志调用实际上被转到这里 getattr(handler, method)(*args, **kwargs) def __proxy(self, name, *args, **kwargs): # 把调用的方法名和方法参数通过Queue传到专门的日志进程。 self._q.put((name, args, kwargs)) fun = logging.StreamHandler.__getattribute__(self, name) # print('call method: ', name, args, kwargs) # 如果是setLevel函数,再调用一次父类的方法 if name in {'setLevel'}: return fun(*args, **kwargs) def __getattribute__(self, name): ''' Hook大法!截获所有方法 ''' attr = logging.StreamHandler.__getattribute__(self, name) if hasattr(attr, '__call__') and name not in {'join', 'emit'}: return partial(MySpecialHandler.__proxy, self, name) else: return attr if __name__ == '__main__': handler = MySpecialHandler('/data/tmp/ttt.log', when='D', interval=1, backupCount=90) handler.setLevel(logging.DEBUG) formatter = logging.Formatter('%(asctime)s: %(levelname)s %(message)s') handler.setFormatter(formatter) logger = logging.getLogger(__name__) logger.propagate = False # Don't propagate the logging to ROOT logger.setLevel(logging.DEBUG) logger.addHandler(handler) logger.debug('debug testtttttttt') logger.info('info testtttttttttt') logger.warn('warn testtttttttttt') logger.error('error testtttttttt') logger.critical('critical testttttt') handler.join() 这里自定义的日志进程类只是一个很粗糙的实现,一但跑起来,只能手动杀进程。反正我的使用场景是一个服务。所以,我也懒得加‘优雅的退出代码’。 ...

November 20, 2018 · 2 min · kamus

伯努利(Binomial)分布和伯努利试验的区别,负伯努利分布及几何分布,超几何分布

[mathjax]我又重新把概率,统计书拿起来了。这次是真的,要把机器学习(统计学习)学好。显然,学好机器学习并不是一件容易的事情。需要要扎实的数学基础。好在我的数学储备还勉强可以,但远算不上“基础扎实”。所以,我有了一个长期远景规划,重新开始学习吧! 今天看了伯努力分布,负伯努利分布,超几何分布,几何分布这几个知识点。下面我一边写回顾今天学到的,一边写文章。 伯努利分布和伯努利试验的区别 伯努利试验(Binomial Experiment)指的仅仅是”一次试验”,或者成功,或者失败。伯奴利分布是一个常用分布,这是完全不同的两个概念。 每次伯努利试验的成功概率记为p,又把重复很多次伯努利试验称为伯努利过程(Binomial Process)。一个重复了n次伯努利试验的伯努利过程中,成功的试验次数记为X,这个X则是伯努利随机变量。X的概率分布被称为伯努利分布。 伯努利分布: $$b(x;n,p) = {n \choose x} p^k (1-p)^{ n-k}$$ 其中,n表示试验次数,p表示每次独立试验成功的概率,x表示成功次数。 什么是负伯努利分布(Negative Binomial Distribution) 伯努利分布和负伯努利分布的大多数设定都是一样的,都不断重复伯努利试验,要么成功要么失败。 不同点是:伯努利分布的随机变量X,表示的是在前n次伯努利试验中成功了x次;而负伯努利的随机变量x,表示的是要达成k次成功试验,需要试验x次(即第x次试验成功,前x-1次试验成功了k-1次)。伯努利分布限定了试验次数记为n,负伯努利限定了成功次数记为k。 负伯努利分布: $$b^*(x;k, p) = {{x-1} \choose {k-1}}p^kq^x-k$$ 几何分布和超几何分布 再以伯努利分布为讨论的基础,仅更改一处,即把伯努利过程中的放回抽样(with replacement)改成不放回抽样(without replacement),即可得到超几何分布。 以负伯努利分布为讨论的基础,仅更改一处,即k设为1,表示成功一次。即不断重复伯努利试验,直到第一次成功就结束,得到了几何分布。 伯努利分布,负伯努利分布的命名 为什么叫伯努利分布 因为伯努利展开式$$(q+p)^n$$的n+1个项对应伯努利分布取各个值时的情况。 为什么叫负伯努利分布 因为展开式$$p^k(1-p)^(-k)$$中的每个项对应$$b^*(x;k,p)$$取x=k, k+1, k+2, …时的情况。

November 13, 2018 · 1 min · kamus

安装MathJax-LaTeX插件,让wordpress显示数学公式

最近看统计学,涉及很多数学公式。于是,想找到一款wordpress的插件可以显示数学公司。 当然,于是就找到了 MathJax-LaTex这个插件。虽然插件名字中有LaTex,但实际上不仅仅可以用LaTex语法描述数学公式,亦可用AsciiMath,以及MathML。 本以为像其它所有wordpress插件一样,安装很简单,很容易就能上手使用。没想到还是花了一些时间。 MathJax-LaTex插件依赖MathJax这个javascript开源工程。原因貌似是MathJax默认用的CDN在大陆被墙了,还是因为浏览器的同源策略被浏览器禁了??我懒得重现排查真正原因了。总之,我用MathJax-LaTex默认配置没有成功,于是我自己手动下载并安装到自己的服务器,运行OK。 首先到 https://github.com/mathjax/MathJax{.wp-editor-md-post-content-link} 下载源代码。熟悉git的同学可以用git下载,亦可用右边的 Clone or Dowload 按钮下载zip包。 把zip包上传到自己的服务器,找一个目录解压缩。 打开MathJax-LaTex的配置web页面,如下图如示,去掉Use MathJax CDN Service 的勾,不要用MathJax自己的CDN;然后,在Custom MathJax location选项中填上自己的路径。假如刚才zip包MathJax解压缩到的目录是/tools,那么就填上 /tools/MathJax-2.7.5/MathJax.js 。 {.wp-editor-md-post-content-link} 然后创建一篇新博文,现在可以录入数学公式啦。装逼必备!比如下面的伯努利分布的公式: [mathjax] $$b(x;n,p) = {n \choose x} p^k (1-p)^{ n-x}$$ 要输入上述方程式,在文章开头输入**[mathJax]** ,这个标志让MathJax-LaTex插件加载显示数学公式相关的javascript代码。然后敲两个美元号 $$,敲入公式 b(x;n,p) = {n \choose k} p^k (1-p)^{ n-k},再敲入两个美元号结尾。即用双美元号$$把公式围起来。亦可用[latex][/latex]这对标签把公式围起来。这对标签这里的公式描述用了 asciiMath语法. n choose k即一个组合。在网上搜索相关语法参考。 在这个页面可以看到更多用MathJax显示的数学公式的例子,用浏览器的查看源代码功能(ctrl-u)查看使用的语法: 使用LaTex语法: http://ykyi.net/zausiu/MathJax-2.7.5/test/sample.html{.wp-editor-md-post-content-link} 使用AsciiMath语法: http://ykyi.net/zausiu/MathJax-2.7.5/test/sample-asciimath.html{.wp-editor-md-post-content-link} 使用MathML语法:http://ykyi.net/zausiu/MathJax-2.7.5/test/sample-mml.html{.wp-editor-md-post-content-link}

November 13, 2018 · 1 min · kamus

C/C++用万恶的libcurl透过HTTPS发POST+JSON请求

相比python, nodejs这样的脚本开发语言已有非常好用的RESTful开发库,很多C/C++程序在调用RESTful接口时,还在使用非常难使用的libcurl纯C接口。下面是用libcurl透过HTTPS发POST请求的代码代段,http body是json字符串: #include <curl/curl.h> CURL* curl; struct curl_slist* headers; curl = curl_easy_init(); headers_ = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM"); curl_easy_setopt(curl, CURLOPT_SSLCERT, cert_file_path.c_str()); curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, "PEM"); curl_easy_setopt(curl, CURLOPT_SSLKEY, key_file_path.c_str()); curl_easy_setopt(curl, CURLOPT_CAINFO, ca_file_path.c_str()); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1L); // jv_text存了json字符串 curl_easy_setopt(curl_, CURLOPT_POSTFIELDS, jv_text.c_str()); curl_easy_setopt(curl_, CURLOPT_URL, path.c_str()); CURLcode res = curl_easy_perform(curl_); if (res != CURLE_OK) // 没有成功 { LG_ERR("curl_easy_perform() failed: %s", curl_easy_strerror(res)); } else // 成功了 { } curl_easy_cleanup(curl);

June 21, 2018 · 1 min · kamus

openssl签发证书肘后备急方(cheatsheet)

生成一对新的RSA非对称密钥,2048bits长。 generate an RSA private key openssl genrsa -out private.key 2048 从私钥中提出公钥。 extract the public key openssl rsa -in mykey.pem -pubout > my_pubkey.pub 创建自签名证书。create a self-singned certificate openssl req -config openssl.conf -x509 -sha256 -days 3650 -newkey rsa:4096 -keyout ca.key -out ca.crt 签署CSR。sign the CSR openssl ca -config openssl.conf -days 375 -notext -in test.csr -out test.crt 检验签书。verify the certificate openssl verify -CAfile ca.crt test.crt 生成一个CSR。Generate a new private key and CSR(Certificate Signing Request) openssl req -config openssl.conf -out CSR.csr -nodes -new -newkey rsa:2048 -nodes -keyout private.key ...

June 20, 2018 · 2 min · kamus

nginx架设HTTP服务器接受PUT方法上传文件

最近用nginx架了个http服务器,通过http上传文件。 nginx的配置如下: location ~ ^/wraith { root /data/tmp; dav_methods PUT; dav_access user:r group:r all:r; create_full_put_path on; limit_except GET { } } 如上,子目录/wraith将接受PUT方法。 $curl -XPUT --data-binary @${TAR_PATH} --noproxy '*' http://xxx.xxx.xxx.xxx/wraith/${TAR_FILE} 如上用curl通过http上传文件到服务器的/data/tmp目录下,文件命名为${TAR_FILE}

March 27, 2018 · 1 min · kamus

utf8中文字符串的多模式匹配算法的优化

utf8中文字符串的多模式匹配算法的优化 信息安全部接口组 kamuszhou@tencent.com 效果 本节仅展示优化效果,对一些业务逻辑和背景未做解释,读者可直接跳至下一节。 上个月接触到了我组的一个关于在海量文本中匹配字符串业务。读源代码时发现一些问题,并针对这些问题做了优化工作,效果非常明显。 测试的硬件环境是只用一颗主频2.4G的Intel至强处理器核心。OS是tlinux2。该业务目前载入11万3千条规则。优化前后的效果如下: |载入 | 旧算法 |旧算法简版| 新算法 | 提升效果 | |:—:|:——:|:——–:|:——-:|:——-:| |速度 | 26分钟 | 3分钟 | 3秒 |60倍或250倍| |内存 | 4327M | 4327M | 不到200M| 20倍 | 表中的“旧算法简版”指去掉了一个繁琐的预计算步骤 |处理速度 | 旧算法 | 新算法 | 提升效果 | |:—:|:——:|:——–:|:——-:| |用11万3千条规则作为待检测文本|52秒|2秒|26倍| |10倍四大名著共88M,平均每行143个汉字|59秒|10秒|近6倍| |文字选自四大名著共87M,平均每行10个汉字|161秒|5秒|32倍| 用11万3千条规则作为待检测文本使得新旧算法都会密集地走到“命中逻辑”,旨在比较“命中逻辑”的性能。 用四大名著作为待检测文本,使得新旧算法几乎不会走到“命中逻辑”,旨在比较算法处理正常文本时的性能。而每次处理文本的长度亦可能影响到性能表现。如表所示,处理短文本(10个汉字)时,新算法的优势有所降低,可解释为旧算法为启动每一次处理消耗较大的资源,而如果处理的文本较长时,这个资源消耗分摊到每个待处理字符就相对不那么明显了。 在一台24核的M2机器上,理论估计新算法一天可以处理36,495,360M文本,36个T~ 业务简述 该业务的核心问题简单地近似概括为: 有几十万甚至更多的模式(短字符串)集合P={P1, P2, …, Pn},输入一个utf8编码的字符串string,输出有哪些模式Px在string中出现。 实际问题比上面的描述稍微复杂一点点。业务需要通过找到的模式判断是否命中预定的规则。一个模式串或多个模式都可以组成规则。比如,单独的一个Px组成一条规则,多个不同的模式则会组合成一个 与 关系的规则(目前业务只支持与关系,支持更复杂的匹配规则是将来需要增强的地方)。比如,有下面几条规则: 铁王座 雪诺 & 提利昂 雪诺 & 艾莉亚 & 2 雪诺 & 龙母 & 床 雪诺 & 夜王 & 异鬼军团 & 守夜人 下文的讨论将继续引用这个规则列表。 ...

November 20, 2017 · 2 min · kamus

服务器端的tcp有大量TIME_WAIT怎么办

公司的群里讨论tcp的TIME_WAIT的问题。TIME_WAIT这个状态可是面试时经常问的知识点啊。 讨论的问题是:有一个服务器,它对外网提供服务,同时它作为客户端连接很多后端的其它服务器。这位同事连后端其它服务器时用了短tcp连接。结果出现了大量的tcp TIME_WAIT状态,吞吐量上不去,怎么办? 先说结论: 如果该服务器要处理外网IP的入流量,那最好的办法应该是用tcp长链接改造它与后端服务器的连接。如果用中间件,比如上zeromq那更省心了。 如果不想做改动,并且在应用层确认已经交互已经完成,则可以用shutdown()直接发RST结束tcp会话,而不走正常的4次挥手。查阅shutdown系统调用的文档获知如何发RST。 如果该服务器不需要处理处网IP请求的话,那么,启用port reuse 即打开net.ipv4.tcp_tw_reuse不会有太大问题(如果处理外网请求就有问题,和NAT相关,见https://vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux),或者更好的,把/proc/sys/net/ipv4/tcp_fin_timeout改小,改成1或者2。让TIME_WAIT只保持很短的时间。 首先,需要知道一个tcp会话由 src_ip, src_port, dest_ip, dest_port 四元组确定。 我们公司的IDC环境中, 上述的服务器作为客户端再发起tcp连接联后端服务器,则 src_ip 固定了, dest_ip是后端服务器的ip, port是后端服务器监听端口。这样只有 src_port 是可变化的,但port只有16个bits还不能用well-known ports,这样就更少了。 再说,主动关闭时,tcp连接需要进入TIME_WAIT状态,保持两倍MSL时长,是为了处理两种情况: 让当前这个会话的迷路包在网路中消失。这样不会干扰到新建的会话。 确保主动关闭方的FIN-ACK包,如果丢失的话,还能重发。 1981年的TCP RFC上把MSL设成两分钟,https://tools.ietf.org/html/rfc793 Maximum Segment Lifetime, the time a TCP segment can exist in the internetwork system. Arbitrarily defined to be 2 minutes. MSL设置这么长,因为以前的网络环境差啊。不过现在因为移动互联网,比较差的网络状态也是非常常见的。但RFC允许实现方减少MSL值。事实上linux的MSL写死在代码中为1分钟并且不可在运行期配置。 如果tcp连接的双方都在性能高速稳定的内网中,这个MSL就太长了。 调试时,还发现如果port用完了,connect的时候内核代码会用自旋锁忙等检查port资源。有linux内核开发基础的开发者都知道spin_lock的时候是不会让出cpu的,于是cpu全被spin_lock吃掉了。一直要等到有port被释放。再后来又发现,如果scoket没有设定SO_REUSEADDR选项,则connect()系统调用会返回EADDRINUSE。 tcp的连接双方都是确定且长期的,用什么tcp短连接呢??改造吧~~~

October 20, 2017 · 1 min · kamus