The Mirages

樱桃沟夹事

当孩子刚出生的时候,我们总会寄予太多的期望。

而整个社会总归会是橄榄型的,不可能有那么多的天才,我们得承认自己孩子就是普通的。但是并不代表因为承认了这点,做父母的就可以懈怠了。

孩子的兴趣是需要扶持和培养的,还有三观要正确。

经常我们想的太过遥远了,连长大后学什么专业,从事什么职业都已经规划好了。就跟我们小时候,老师问长大要做什么啊,90%都是科学家,可最终呢?

还是每个阶段做好应该做的事情,未来怎么样谁又能知道呢,上大学前我都没想过要学计算机的,可最终还是干上IT了。

既然3岁前,那就好好玩,看看各种不同的文化和自然环境,每天在家看看绘本,至于什么时候会爬,什么时候会走,什么时候认识多少字,这些有那么重要吗?不就是早点晚点的事情。

阅读全文 »

现在在上爱尔惠母的亲子课,但是自从升级到音乐课后,大家普遍反馈不好。于是踏上了慢慢试课的旅程。

上周是试了小小运动馆,从头到底一个老师就让大家自己玩了,当中稍微指导下,还特别贵,400块一节课。

于是这周试一下美吉姆的课,我们试的是14-23个月的,这个跨度也太大了。

全程都是中英文进行授课的,一个老师,一个辅助。活动也挺多样的,但是因为孩子都跨度太大,导致有些活动对于一些孩子太简单,而且对于怯场的孩子没有很好的关心。

各个家长和孩子都没有任何交流,感觉大家都不认识的,而在爱尔惠母,因为孩子最大的年龄差距就1个月,所以基本还是很一致的,而且待的时间长了,各个家长和孩子之间会有很多的沟通帮助什么的。

想想试课的目的是为了小小球的感统训练,其实就是他现在有点胆小。现在看来没有什么课程是合适的,是不是应该从我们家长开始着手进行,多带出去走走看看,多跟哥哥姐姐一起玩玩。

阅读全文 »

北京植物园里的樱桃沟是两山之间的一个风景区,离门口非常远,风景不错。
<夹边沟记事>被誉为中国的<古拉格群岛>, 结果这书现在成了禁书了,而<古拉格群岛>还居然可以销售。
<樱桃沟夹事>是一个梦境中写的书的名字,还有封皮是土黄色的,其他详细的实在记不清楚了,所以想起很多东西我还是需要记录下来,不然以后可能都没得回忆了。
blog里放的可能都整理过的,这里放的基本都是想到什么就说什么的。

本来以为confluence这样的东西应该很好恢复,就一个程序一个数据库,迁移换个地方再导入重新启动就行了。 但是这次数据意外出现了问题,导致只能用MySQL备份的数据来进行恢复了,这样首先肯定是很多附件没有了。 首先是新装一个confluence,在页面中进行安装,刚开始出现server-id的部分,暂停安装,关闭confluence应用,修改confluence.cfg.xml 这个文件的confluence.setup.server.id这里的值跟你原先的保持一样。 要找原先的serverid就需要把原先的备份数据库导入到mysql中,取名为confluence, select * from BANDANA where BANDANAID=1; 就可以取得。 然后修改完confluence.cfg.xml 的server.id后我们继续启动confluence安装程序,在连接数据库的部分要写一个新的库,比如confluence_new, 然后db的用户名密码和原先一样。 这样就使用新库就安装完成了。 接下来就是关闭confluence进程,然后继续修改confluence.cfg.xml这个配置文件中hibernate.connection.url 这里的数据库地址到老的db(confluence)上。 然后我们再次进入mysql命令行,将confluence_new这个库里BANDANA表里的BANDANAID 1到4的内容全部update到老的db中。 我们再次启动confluence,这样就用上了原先备份的数据库内容了。 不过我实际过程中还多了一步,因为原先confluence和jira是互联的,而现在这2个都更换了IP重新部署了,而confluence我们又是用的jira的账号进行登录的,因此还要设置cwd_directory_attribute这个表里的数据。主要是attribute_name: user_encryption_method,attribute_name: application.name,attribute_name: application.password,attribute_name: crowd.server.url 这4条数据。   而如果你使用了confluence自己导出的备份,那是一个全量备份,那就只要安装好新的,然后导入就可以了,但是那个confluence数据的目录也是需要还原回去的。不然很多附件也是会丢失的。 所以所有新玩意第一次备份的时候一定要验证备份的可恢复性。切记切记!

已经很多场合说过普通运维在未来5年内是要消亡的言论。只有大型IT企业才会需要专职的运维,就跟网络工程师的消亡是一样的道理。 先看看运维对于一个公司的价值是在哪里。 成本: 一般而言运维是花钱的部门,控制成本自然是从多方面都要做。购买云服务和各种固定资产,一个合格的运维自然懂得最高性价比的东西,之前我们这些每年省下的钱招5个工程师,或者加20个服务器都有富余。 控制成本另外是减少产品成本,之前有过一个很简单的例子是,产品要求点播节目单是实时推送的,这个算出一个很大的天文数字来,但是如果我们改成5分钟推送一次,这样可以降低80%的费用,而且本来这个节目单的变更也不是非要实时的。除非你们家产品完全没有成本压力,不然很明显知道选哪个。 数据驱动:之前在做SNS的时候,会把每个广告位进行编号,总能发现一些位置的点击率就是比另外的高,而在带宽支出是一样的情况下,很明显推算出哪些是需要提高价格投放,哪些是降低价格,至于DSP这样的就另说了。 技术架构: 稳定,安全,高效,复用,冗余是运维要考虑的出发点,这个跟大部分开发的出发点是不一样的。 稳定的意思是说,这个东西是大家熟悉的,迭代过多年的,在高可用方面有成熟的方案。 之前我们有用redis要当存储,虽然redis本身有bgsave,那时候也没有redis cluster,哨兵浪费机器有点多,还有IP切换等问题,但是redis本身又不适合作为最终存储,但是开发人员为了要在99.9%请求要在2ms内返回,那就只能用这个,但是数据的安全性就必须要处理,那就得跟开发一起讨论了,最终讨论出来基于一致性hash的redis集群,一致性hash在redis客户端进行实现,每个key至少存放2份,同时加上redis node的监控(响应时间,内存剩余),这样这个系统在上线前我们基本就心中有底了。 效率 对于外面人来看这个就是救火的速度。但是对于内部来说一个是平时的演练,另外就是一个自动化的程度。这个一定是自己来做的,因为当平时没有故障的时候,这些东西是完全看不出的。 随着现代应用越来越复杂的趋势,要做好故障演练,benchmark这些是非常耗费资源和人力的。 安全 同效率一样,这个只有大公司才会重视的,当初创公司连业务都做不完谁会去关心这个呢,而且这两项都是需要花钱的。 安全一个是对外的安全,比如外部防火墙和入侵检测,DDOS这些。另外一个是内部的安全:账号密码管理,操作审计,备份安全等等。 同样这个也是平时根本看不出成绩,

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个小时答案就是这个。

0%