The Mirages

樱桃沟夹事

close_wait真是一个让人崩溃的状态,常常只有几千个的时候就让服务器直接挂了。 可不这次又碰上了,报警说_close_wait_太多,查了一下是都是公网网卡那块_close_wait_ 通过tcp的4次挥手我们可以知道,close_wait_是发生在客户端往服务器端发送_FIN_请求后,客户端会把自己置为_finwait1, 而服务器返回给客户端后会把自己的状态置为_close_wait_,再等待一段时间后会发把自己置为_last_ack_ 理论上讲,_close_wait_的产生是由于程序意外中断导致的,但是原因可能是多种多样的。 用_netstat -s_也查看了下网络情况,因为这个是网络启动到现在的累积情况,所以需要对比之前5分钟的看,但是也没看出多少异常来。

266813 invalid SYN cookies received
7511 resets received for embryonic SYN_RECV sockets
3096 packets pruned from receive queue because of socket buffer overrun
11 ICMP packets dropped because they were out-of-window
603754 TCP sockets finished time wait in fast timer
12 time wait sockets recycled by time stamp
7082 packets rejects in established connections because of timestamp
890380 delayed acks sent
615 delayed acks further delayed because of locked socket
Quick ack mode was activated 161020 times
10129 times the listen queue of a socket overflowed
10129 SYNs to LISTEN sockets ignored
74494 packets directly queued to recvmsg prequeue.
29399 packets directly received from prequeue
20966540 packets header predicted
6813794 acknowledgments not containing data received
12672614 predicted acknowledgments
1 times recovered from packet loss due to fast retransmit
4237 times recovered from packet loss due to SACK data
42 bad SACKs received
Detected reordering 311 times using FACK
Detected reordering 56228 times using SACK
Detected reordering 35401 times using time stamp
683 congestion windows fully recovered
56047 congestion windows partially recovered using Hoe heuristic
TCPDSACKUndo: 19806
24593 congestion windows recovered after partial ack
5911 TCP data loss events
TCPLostRetransmit: 569
2 timeouts after reno fast retransmit
3830 timeouts after SACK recovery
1556 timeouts in loss state
60642 fast retransmits
6040 forward retransmits
17845 retransmits in slow start
79714 other TCP timeouts
493 sack retransmits failed
15031 packets collapsed in receive queue due to low socket buffer
160518 DSACKs sent for old packets
43 DSACKs sent for out of order packets
87404 DSACKs received
754 DSACKs for out of order packets received
3733 connections reset due to unexpected data
242941 connections reset due to early user close
10649 connections aborted due to timeout
TCPSACKDiscard: 1094
TCPDSACKIgnoredOld: 1384
TCPDSACKIgnoredNoUndo: 35778
TCPSpuriousRTOs: 103
TCPSackShifted: 21957
TCPSackMerged: 27204
TCPSackShiftFallback: 207287
TCPBacklogDrop: 1
TCPOFOQueue: 30173
TCPOFOMerge: 45
TCPChallengeACK: 21202
TCPSYNChallenge: 21096
TCPFromZeroWindowAdv: 117
TCPToZeroWindowAdv: 119
TCPWantZeroWindowAdv: 8861

然后认为是网卡队列堵了,因为netstat查看有很多_Recv-Q_,这个表明网卡接收队列堵了,于是就想着先优化一下tcp队列吧。那就优化下

net.ipv4.tcp_max_syn_backlog = 2000
net.core.netdev_max_backlog = 2000
net.ipv4.ip_local_port_range = 5000 65535
net.ipv4.tcp_max_tw_buckets = 5000

观察下效果好像是缓解了,但是看着并没有本质上解决。于是又看了下并发,也就2万左右,当初1台机器我们都可以抗20多万的并发呢,现在nginx怎么会抗不住呢,百思不得其解。 又看了下日志,发现这些请求都是https的相关请求,于是怀疑是ssl握手导致的,查看了当时cpu的状态,果然那个时候的cpu使用率都到了96%到97%了,这个明显是nginx响应不过来了,看了nginx的error log里很多stack traceback这样的错误信息,之前就一直以为是lua程序写的有问题。 既然找到了是https的问题,那就得优化下nginx关于tls部分的设置了。 ssl握手协议的时候RSA和ECDHE这2个算法开销会比较小,而RC4和MD5的开销会比较大。而默认ssl buffer size是16k,这样导致的结果当buffer比较小的情况下会继续等待满了16k才会返回,改成4k后会尽快的进行返回。

    ssl_ciphers          ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256;

    ssl_prefer_server_ciphers  on;
    ssl_protocols        TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_buffer_size 4k;

    ssl_session_tickets      on;
    ssl_stapling      on;
    ssl_stapling_verify      on;
阅读全文 »

这是小小球出生后(15个月)第一次出门远游,虽然去年已经坐过2小时的✈️了,但是这次4小时的旅程还是难免有所担心的。 既然是带娃出门,那肯定不能像原先一样到处逛了,所以找个舒适的亲子酒店还是很有必要的,因为也懒的折腾,这次就一步到位选了亚龙湾天域,不过现在看来这个选择也未必非常好。 有了第一次出门经验,这次知道直接打航空公司电话预定婴儿票就可以了,2周岁以内都可以。 2周岁以上就可以直接携程什么买儿童票了。 还得感谢浦发提供了送机服务,使这个旅程有了一个良好的开始。但是首都机场3个跑道变2个跑道的事情还是使我们在飞机上坐了1个小时,4个小时的飞机时间变成了5个小时,还好航空公司没有另外加收堵机钱。 小小球果然5个小时有点长,3个小时后就开始烦躁了,还好不是烦躁排行榜第一的,抱着就到处走啊走啊,看看书,玩玩贴纸。最后也还是顺利的下飞机了。 下了三亚凤凰机场,这叫一个热啊,好多人都在机场换衣服了,携程订的接机的司机不是很靠谱啊,这一下子多等了30分钟以上,然后路也不熟,绕了好久,结果到酒店已经晚上9点了。12点出门到21点才到酒店,这整整9个小时的路程,小小球路上也睡了3个觉,去机场路上,飞机上,去酒店路上。 首先感觉的是物价够贵的,第一天嫌酒店的饭太贵了,去KFC买的套餐,结果2个套餐95元就出去了,后面几天就外卖,酒店吃了基本。 来到亚龙湾就必须得看海啊。 这几天出门最远的就是百花谷了。 这三亚就是每天都大太阳啊,每天出门前这抹防嗮的时候这不高兴啊,天天就知道游泳和玩。 可是在玩的时候这嘴能咧的再大点不? 这几天都是1.8米的中浪,因此是无法下海的,小小球看到大海浪居然还怕。 这小家伙最爱的就是游泳池,以至于每天出门我们都得绕着游泳池走,不然必定有个挣扎的过程。 有时候玩累了我们也思考一下人生要。 难得来个全家福吧。 要回家了,这一脸的惊讶啊。

在阿里云上需要在lvm中增加一个新磁盘,但是挂载的时候居然报了vg not found。 网上找了一堆也没啥结果。 那就自己来吧。 首先一开始pv这一步是没有问题的,也没有报错,就是vgextend的时候报错,但是vgdisplay又都正常。问了下阿里云居然让我做好备份重新做lvm。 找了下vg相关的命令,主要有如下:

1
vgcfgbackup vgchange vgconvert vgdisplay vgextend vgimportclone vgmknodes vgremove vgs vgsplit vgcfgrestore vgck vgcreate vgexport vgimport vgmerge vgreduce vgrename vgscan 

看着像是vgck比较符合,但是没啥效果。最后找到vgscan, 默认会扫描所有vg的,问题也就解决了。  

1
2
3
4
5
6
7
8
9
vgscan 
Reading all physical volumes. This may take a while...
Found volume group "data" using metadata type lvm2
vgextend -vd data /dev/vdc Using volume group(s) on command line.
Found same device /dev/vdb with same pvid VViS1rAcC3xxE1DzWM8C6EoAEbfKn5H3
Found same device /dev/vdb with same pvid VViS1rAcC3xxE1DzWM8C6EoAEbfKn5H3
Adding physical volume '/dev/vdc' to volume group 'data' Volume group "data" will be extended by 1 new physical volumes
Creating volume group backup "/etc/lvm/backup/data" (seqno 3).
Volume group "data" successfully extended

在上个星期之前一直不知道redis居然还有事件机制,一个研发同事问了下我,居然一直都不知道,但是BLPOP和RPUSH也算是事件啊。一直只是把它当做一个高速缓存和队列来使用。

具体的这个介绍可以参考: https://redis.io/topics/notifications  

在每个redis里可以设置3种事件,测试过把所有加上并不起作用,具体列表如下:

1
2
3
4
5
6
7
8
9
10
11
12
K     Keyspace events, published with __keyspace@<db>__ prefix.
E Keyevent events, published with __keyevent@<db>__ prefix.
g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...
$ String commands
l List commands
s Set commands
h Hash commands
z Sorted set commands
t Stream commands
x Expired events (events generated every time a key expires)
e Evicted events (events generated when a key is evicted for maxmemory)
A Alias for g$lshztxe, so that the "AKE" string means all the events.

设置的方式如下:

1
$ redis-cli config set notify-keyspace-events KEA 
阅读全文 »

在一台nginx服务器上,本地弄了个redis,使用https://github.com/openresty/lua-resty-redis 做一些简单的逻辑判断使用,可奇怪的时候一直产生大量的time_wait,机器连接数总共才2000多,可time_wait居然要2万多。 按理说lua-resty-redis是有连接池的,看了下写法也没有问题啊,网上那个坑1坑2坑3也都没有问题啊,可就是继续大量time_wait。 https://moonbingbing.gitbooks.io/openresty-best-practices/web/conn_pool.html  这段反反复复看了好多遍,也没想出是什么原因。 从time_wait的产生分析也是nginx产生的,不是本地redis配置的问题,而且redis也本来就配置的keepalive。 于是就继续使用tcpdump大法了,看看为什么nginx发了FIN没有得到ack。dump出来结果也是这样。 redis-dump redis-server这里没有对FIN 进行ack, 导致nginx一直保持time_wait状态,而且这个状态必须要等1分钟后2MSL(最大报文段生存时间)才会到close状态。这个是无法通过sysctl.conf来进行修改的。 这个时候就完全到到lua-resty-redis这个模块的问题,去github上更新了最新的,然后看到文档里又有依赖对应的nginx-lua版本,也都检查了没有问题。 这个时候那就只能是代码本身的问题,看lua-resty-redis的邮件列表也没有什么人说有不能keepalive的问题。 然后把代码恢复成官网事例一样,结果发现好使。 过了一遍代码果然找到了问题所在

1
2
3
4
5
if not ngx.var.cookie_userid 
then
userid = 0
-- return
end

原先代码里是判断如果cookie里没有userid就直接return,但是一旦return出来之后就用不到后面的keepalive了,所以将这里直接赋值一个0无效的userid,然后再继续后面的判断。 从这个问题来看主要还是对lua的循环跳出机制还是不够了解,忙活了4个小时答案就是这个。

上周就开始阅读了,作为一个伴随着腾讯长大的80后,同时也身处互联网中的网中人还是挺有感触的。


其实在追新这方面我还是挺后知后觉的,除了饭否和豆瓣是第一时间开始用的,其他基本都很落后,98年开始上网,一直到01年才开始申请QQ号,微信号更是在微信红包大战的时候才申请了。而书中说的msn在06年已死,可我居然一直用到07年底,而360的东西更是从来没接触过。


对于腾讯这个公司,其实在11年以前是没有什么好感的,抄袭的王者,但是读罢以后发现还是小看了他们,其实也是自己没有很深的思考和阅历导致的。08年做视频,总觉得很简单,不就是视频文件分割走CDN,而自己负责的恰恰就是CDN,我所看到的也就是CDN,而对于调度,p2p,合并,加速视频流这些居然都视而不见。其实这些才是这家公司的核心啊,至于CDN这些都是很外围的,用自己和别家区别不大(akamai除外)。


阅读全文 »

刚上大学的时候,正是生物特别热门,那时候最好的学生都被忽悠进生物系了,这个可是改变人类未来命运的,生物医药,基因工程,可15年过去了,生物系出来的大多是当生物老师,或者转行了,水木上有生物大神最后也去了MBB中的一家做咨询了。虽然未来还是可期的。 而现在机器学习的崛起,是不是意味着我们很多工作都基本也会被替代了,首当其冲我觉得运维是最容易被替代的,一个云计算基本把所有系统运维的活给替代了,而后面的PAAS的全面普及和优化,那基本没啥应用运维的事情了,这些岗位可能在云计算公司里还会存在,但是其他公司内基本就可以取消了。 按这个逻辑下去真是越想越可怕,除了完全需要创造类的工作,其他机器都可以做啊,矮大紧在一集好莱坞的介绍里讲了好莱坞挑选剧本就完全属于一个机器行为,多少时间铺垫,什么时候高潮,有多少个高潮,结局如何收尾都是有固定模式的,但为什么好莱坞也会出好片呢? 最近在看《腾讯传》里说的一点就是微创新可以很好的解答上面那个问题,很多东西是有一定规律,机器完全胜任,但是这个规律我们是不是再修正下,就比如PAAS平台,就拿最简单的redis来说,针对每个服务需要优化的地方也是非常多的,那我们就一点点修正,直到出来一个公式可以适配这些不同的应用,不过这个没啥难得,连AlphaGo这样超复杂的围棋机器人都可以做,这点条件根本不算啥,但是这当中就是一个训练机器人的过程。 这些所有的微创新机器人至少不能提前做,但是能很快学会。 看到国外有一个新职业叫训机师,就是给机器人喂数据,但是可悲的是这个职业的目标居然是让机器人来取代自己。 但这个世界就是这样啊,汽车出现会导致了马车的沉寂,当然现在很多旅游景点还是有的,接下来该失业的估计就是汽车司机了吧。很多职业都会随着技术的进步而消亡,只是在IT行业这个消亡的速度会非常之快。 近期看运维是最危险的了,然后写代码也挺危险了,你只要描述伪代码就直接产生对应的程序,这种工具现在有,只是还不成熟罢了,最终会不会演变成只要产品文档符合某种规范就直接生成了呢? 虽然说是近期,那估计还能活5年吧,但是5年后的事情真是难说了。看来要不被社会所淘汰,得加快步伐了。

2016年如果从工作上来看,几乎是一事无成啊,也没研究点啥,也没提高啥,就跟黄舒骏的《马不停蹄的忧伤》里唱的一样。 从博客的荒废程度就知道今年啥都没干了。 但是自己干的很苦逼,底下兄弟们也很苦逼,整个技术部也很苦逼,原因呢? 其实最苦逼的倒不是工作忙,忙的有意义经常还让人精神振奋,无意义的才会感觉苦逼。 看来现在是已经过了自由自在搞技术的年代了,邹哥说之前会上有人问运维能否做到40岁,中国运维的起步是1999年,到现在已经17年了,当年23岁的小伙现在也已经40岁了,不过当年那批运维现在都是各厂的管理层了,所以应该现在是没有的,未来说不好,也许运维这个岗位随着云计算的快速发展就会继续萎缩下去,最终只有一些大厂里才会存在的了。 有些趋势你是阻止不了的,你可以往基础上更专,那样确实很有前途,也可以在需求上更广。 怎么说呢,互联网发展那么多年了,但是总离不开tcp/ip的,搞这些基础的要有深度才行。常说移动电信最终给他人做嫁衣,但是那些应用厂商真的离得了这些基础运营商? Fenng说过一句话现在看来是挺对的,“技术总是在短期内被高估,但是在长期又被低估。” 放在国内任何中小厂里都是适用的,毕竟生存是第一位的。在生存都有问题的情况下谈什么自行车呢?对于商业来说短期利益永远都是第一位的,至于长期的东西谁又能说的清楚呢? 虽然工作上和技术上没有任何长进,但是从生活上来说是进步很多,小小球一天天的长大,球子也恢复的还不错,只是北京这雾霾天让我对家人的健康很是担心了,而且现在一点没有趋好好迹象,某些发誓2017年前要治理好雾霾的领导也滚蛋了,最终也没有提头来见。 在年末的时候老妈脚骨折了,本来还说过来给小小球过生日的计划也泡汤了,定的机票也给退了。还好恢复的挺快,居然已经拆线了,不过里面的钢钉要不要拿出来还是未知数。老妈住院几乎所有亲戚都来看了,老妈应该还挺欣慰,最好的还是姐妹俩的感情深啊。 2016年的美元价格直线上升啊,但是算了下其实1年差不多是10%的样子,但是买美元可不是为了这个,只是资产的多样配置。2016年我们见识了太多的黑天鹅事件了,所谓的民调现在看来是并不可靠,看来大多数人不会在公共场合中表达自己的真实想法,所以产生了英国脱欧,特朗普当选这样的事件。

直接使用的 https://github.com/airbnb/kafka-statsd-metrics2.git 这个将metric汇报到statsd中。 statsd是使用了collectd自带的plugin来实现的。这样等于每台服务器上都有statsd了。 最后collectd将收集到数据存储到influxdb集群中。 这个jar包在kafka 0.8.2和0.10.0上使用都没有问题。 不过在官网的readme中有些问题,故还是走了点弯路。 必须要自己编译一下。 c git clone https://github.com/airbnb/kafka-statsd-metrics2.git ./gradlew shadowJar 这样我们就可以获得 kafka-statsd-metrics2-0.4.1-all.jar 这个jar包,放入到kafka的libs下。 由于这个是依赖了datadog的statsd client,因此还要下载一个jar包。 https://repo1.maven.org/maven2/com/indeed/java-dogstatsd-client/2.0.16/java-dogstatsd-client-2.0.16.jar   配置文件官网写的没有问题,直接使用就可以了 ```c
#for metric # declare the reporter kafka.metrics.reporters=com.airbnb.kafka.KafkaStatsdMetricsReporter # enable the reporter, (false) external.kafka.statsd.reporter.enabled=true # the host of the StatsD server (localhost) external.kafka.statsd.host=localhost # the port of the StatsD server (8125) external.kafka.statsd.port=8125 # enable the support of statsd tag extension, e.g. datadog statsd (true) external.kafka.statsd.tag.enabled=true # a prefix for all metrics names (empty) external.kafka.statsd.metrics.prefix= # note that the StatsD reporter follows the global polling interval (10) kafka.metrics.polling.interval.secs=60


微服务是去年开始很热门的词汇,有幸碰到老板也想实践微服务的。但是这这中间确实碰到了很多的问题。 首先是api的规范问题,这也是从运维角度来说最重要的部分。 由于之前是单jar包的方式,原先的开发者也不关注api的规范,导致api的URL完全是凭感觉编的,这个在拆分服务的时候就特别头疼。 /api/stat/1 是指向A服务 /api/stat  又是指向B服务 另外一个是输入和输出的问题,api最关键的是保证输入输出能够长期保持一致,就跟你用第三方的api,你总不能让你新增加的response啥的吧,或者json里再增加点新的内容,当然在公司内部,我们还是可以商量的,但是不能今天这个API是做这个功能,明天就变成B功能了。 这个就很头疼了。 配置文件的统一管理,这个因为拆分成很多服务了,所以再也不能一个配置文件解决所有的问题了,那统一起来管理还是很有必要的了。 基础服务saas化(比如redis,cassandra, kafka,  MySQL),这些基础通过程序包装起来供程序来申请资源,调用,容灾,升级等。这个也是对于原先的运维团队工作量最大的地方。但是也是必须的。 因为拆分成微服务后,各个服务都可能需要用到redis,是分个大redis池,还是每个服务单独一个池子呢? 在微服务领域一般都是一个服务给一个池子,但是不应该一概而论的。我们还是要综合评估的。不能为了微服务而微服务的。 日志的汇总收集,展示。这个标准做法就是通过ELK来完成了,当然我们还用到了kafka来做这个。不过前期是做好日志格式的定义。还有别忘记分了新服务出来后要reload下日志插件,不然都还是找的老的服务。这个就扔部署脚本里一起做了。 在实际使用中发现 consul缺乏服务使用率情况,这个现在是通过监控去收集各个服务的信息再汇总到grafana中,后期是想通过kong来做api调度,然后通过这样的https://getkong.org/plugins/runscope/ 插件来实时查看。 而且consul要跟upsync模块结合的话还要自己写程序去迁移consul中service的内容到kv中,这个实时性就不高了。后面准备自己写入和删除kv。 最后:微服务的优势就是为了更好更快的扩展,降低服务之间的耦合性,但是对于开发的要求更高了,对于运维的要求也同样更高了。

0%