-
DNS隧道
前一段时间, 回到家发现电信欠费不能上网了, 赶紧充值的同时, 想到DNS隧道.
host www.baidu.com 发现是可以正常返回的. 但当时手头没有现成的DNS隧道工具, 萌发了自己写一个的想法.
原理应该算是比较简单的, 但是在实现的过程中遇到了一些麻烦, 现在还未完成…
先把这些困难记录一下, 也练练把事情说清楚的能力.
-
dns发送消息过长
- 你可能也听过这句话, UDP是基于帧的, TCP是基于流的.
- IP包是有长度限制的. 超过一定长度, TCP的话, 内核会帮你分成多个包发出去. UDP呢?
我之前只有印象, IPTCP协议详解中, 不记得哪一章了, 有提到, UDP的长度是有最大限制的, 各系统不同, 可能达到不了理论上的IP包最大值. 但我却从没有想到, 如果超过了会怎么样.
因为在尝试实现DNS隧道, 需要确认一下这个问题. 刚才用GO语言试了一下, 如果消息过长, 是会报错的: write udp 127.0.0.1:59933->127.0.0.1:10000: write: message too long
-
nginx 500 错误: client_body_temp Permission denied
nginx做代理, proxy_pass代理后面的应用. 用户反应大量请求的时候, 会得到500错误.
我看了是access日志之后, 发现request body为空. 以为是用户调用出错.
后来配合用户做tcpdump, 发现client还在发送request body, 没发完呢, nginx就直接返回500, 然后close connection了. client还在坚持继续发完了request body, 然后close.
然后上网搜索, 我盲目的关键词居然很快就找到了答案. https://wincent.com/wiki/Fixing_nginx_client_body_temp_permission_denied_errors google 真好.
报错是因为request body比较大的时候, nginx会先把一部分数据缓存到磁盘, 但写磁盘的目录又没有权限, 所以直接抛出了500报错.
解决方案也简单, 就是给权限, 或者重新配置一下 client_body_temp_path
多看一眼error.log就能直接找到解决方案的. 不过在tcpdump的过程中学到了sack的的用法, 也挺好的.
-
vim和python中正则匹配的lookahead模式
lookahead
之前只知道python中的
lookahead
模式(?=…)怎么写, 今天看到vim的help文档, 看了好一会没看明白. google了一下才清楚了,记录一下.举例说明一下, 我想匹配这条”狗”是谁的, 只把主人匹配出来, 但猫我不管.
In [136]: re.match(r'^my(?= dog)','my dog').group() Out[136]: 'my' In [139]: re.match(r'^my(?= dog)','my cat') is None Out[139]: True
也就是说, 我只取了my这个词, 后面的dog没有消费, 但是一定要保证my后面跟的是dog
positive lookahead
与之对应的还有
positive lookbehind assertion
, 也举例说明一下.我想匹配”我的”狗, 而不是别人的, 如下.
In [154]: re.search(r'(?<=my )dog','my dog').group() Out[154]: 'dog' In [156]: re.search(r'(?<=my )dog','her dog') is None Out[156]: True
注意 这里没有用match, 而是用的search. 因为这两种模式只是”确保”前后有东西, 而不消费任何内容. python里面的match其实是要从头匹配的, dog并非顶头的内容, 所以用match匹配不到.
VIM
在vim里面也有相应的功能, 但语法有些不一样, 不多说了, 直接举例.
- 匹配dog, 但必须是我的.
/\(my \)\@<=dog
- 匹配主人, 但必须是狗的主人
/\w\+\( dog\)\@=
-
一行python代码求素数
看了如何读懂并写出装逼的函数式代码就想实验一下, 然后看到朋友圈有人转, «一行python代码», 求拿求素数爽了一把, 写完之后再也不想多看一眼了
先来个只是不用for循环的:
print filter(lambda n:'' if any(filter(lambda i:n%i==0,range(2,1+int(n**.5)))) else n, range(2,100))
然后增加一点细节把filter去掉
print (lambda f:f(f))(lambda f:lambda n: [] if n==1 else f(f)(n-1) + (lambda n:[n] if ((lambda f:f(f))(lambda f: lambda n, i: n if i**2 > n else '' if n % i == 0 else f(f)(n, i+1)))(n,2) else [])(n))(100)
-
hangout中GeoIP2的性能统计
在hangout里面, 有个GeoIP2插件, 可以根据IP添加地理信息. 我们在使用这个插件之后, 发现处理速度有些下降, 于是通过日志统计了一下这个插件的性能.
我们是跑在marathon + docker平台上的, 可能统计会有所偏差.
每批60000条数据, 处理好之后, bulk到ES. 日志会记录bulk的时间, 和bulk结束拿到response的时间, 根据这两个时间统计.
使用GeoIP2之前的 filter: 234055次 平均8.51832039051秒 (不包括GeoIP2, 但有其他的Filter) bulk: 234048次 平均 5.99807413009秒 之后的 filter: 9145次 平均 13.0438958994秒 (在之前Filter的基础上, 添加了GeoIP2) bulk: 9146次 平均 3.70712070851秒
后面bulk快可能是因为ES做过扩容.
但是filter时间多了4.5秒, 每批6W条数据, 平均一条数据0.000075秒. -
elasticsearch中rebalance策略分析及参数调整
在做一些维护的时候, 比如删除/关闭索引, ES会触发rabalance, 但有时候觉得它过于敏感了.
分析一些ES的rebalance策略是怎么样的, 有些不确定, 属于猜测.
举例现在web-2016.10.03正在weak节点上做rebalance:
web-2016.10.03 4 p RELOCATING 450308191 757.5gb 10.0.0.1 10.0.0.1-> 10.0.0.2 0zDpSrgmT1mSrtEywH86zg 10.0.0.2
源10.0.0.1上面有52个shard, 目的10.0.0.2有48个shard. 总的shard 是33400, web-2016.10.03一共10shards, 无复制片, 共129个Node.
先按公式计算每个Node的weight (这个公式我不是很确定, 之前见到过, 但找不到了, 一部分凭印象, 部分参考代码https://github.com/elastic/elasticsearch/blob/2.4/core/src/main/java/org/elasticsearch/cluster/routing/allocation/allocator/BalancedShardsAllocator.java, 还有一部分算是蒙的吧)
1的权重是 0.45(52-33400/129)+0.55(1-10/129)
2的权重是 0.45(48-33400/129)+0.55(0-10/129)两个权重的差值是 0.45(52-48) - 0.55(1-0) = 2.34, 大于1.
第二个部分先认为是固定不变的(源不大可能大于1,毕竟总shard是10个, 加上复制片才20, 总节点远超过这个. 目标也一般是0) 所以主要影响因素就是0.45*(52-48), 如果想控制, 相差<=3的时候不做迁移, 阈值设置成2就可以.
-
elasticsearch中的common terms query
翻译自https://www.elastic.co/guide/en/elasticsearch/reference/2.3/query-dsl-common-terms-query.html
common terms query 是stopword一个替代方案(但我感觉比单纯的stopword好多了). 它可以提升精确度, 还不会牺牲性能.
The Problem
在Query中, 每个Term都消耗一定的资源. 搜索”The brown fox”需要三次term query, 这三个term都会在索引中的所有文档中执行,但是 “The” 这个term对相关性的影响比其他两个term要小.
之前的解决方法是把”the”这种高频词当成stopword, 可以减少索引大小, 在搜索的时候也会减少query次数.
但是, 虽然高频词对相关性的影响小, 但是他们依然很重要. 如果把stopword去掉, 会丧失精确性, 比如说”happy”, “not happy”就区分不了了. 而且, “The The” , “To be or not to be” 这种文本就丢失了.
解决方案
common terms query把query temrs分成2组, 一组是更重要的(低频词), 一组是不太重要的(高频词,之前被当成stopword).
第一步, 先搜索更重要的term, 它们是低频词, 对相关性的影响更大.
第二步, 再对高频词执行第二次搜索. 但是它不对所有匹配的文档打分, 只对第一步中匹配的文档打分. 这样的话, 高频词也可以提升结果的相关性, 同时还不会增加很多负载.
上面这个第二步没有很理解, 为什么不会增加很多负载. 因为对query的执行原理不清楚 :(
如果query里面的term全是高频词,那么query会按照 AND queyr来执行(默认是or). 这样的话, 虽然每个term都匹配好多文档, 但AND之后,结果集就会小很多.
也可以用 minimum_should_match 这个参数控制用 OR query, 最好使用一个大点的值~ -
TCP连接中的状态变迁
关于TCP的状态变迁, 这张截自TCP/IP协议详解一书的这张图,简单明了.
这篇文章总结一下各状态变迁对应的编程语言中对应哪一个方法调用.
-
幽灵堵车
如果你在高速公路上开过车,你可能会碰到这种情况。车流越来越慢……变的慢慢挪……然后最后完全停下来。几分钟之后,车流又依次开始移动,然后突然你就有可以全速行驶了。最匪夷所思的地方是,发生这种交通现象时,并没有任何施工、交通事故或其他可情况发生。到底这是为什么呢?
如果在高速公路上有足够多的车辆,任何轻微的交通流量中断,都会导致循环、放大式的连锁反应:一辆车轻轻地稍微刹了一下车,跟在后面的一辆车就会刹车得更重一点以免撞上前面那辆车,最后刹车量被逐级增大,直到产生交通流的波动、车流变慢甚至停止。
在网页上模拟 直观的感受下.
- 在200*200的正方行街区, 排列了一辆辆的汽车, 每辆车长3米, 相邻的两车间隔10米,以每秒20米的速度前行.
- 与前车间隔小于10米时,以0.2的系数减速.例如间隔8米时,速度降至20-2*0.2=19.6米/秒.
- 当与前车间隔小于4米时, 停止. 与前车距离大于50米时, 以30米/秒稳速行进.
- 第一秒时, 第一辆车因为某种原因停了5秒, 然后又正常启动.
- 红色是最慢的一辆车, 橙色是速度小于10米/秒的车
这5秒的故障会导致50秒的时候,还有车的速度低于10米/秒. 这时候第一辆车应该已经在1.4公里之外了. 但这个圈只有800米,所以他追上最后一辆时, 他的速度也只能在6米/秒, 它大概想不到这么慢的速度就是因为他自己停了5秒钟造成的.