2016年12月19日星期一

LDAP Proxy连接丢失问题

架构:Client -> LDAP proxy -> AD服务器。代理用的ldaptor

问题:配置Confluence或者Jenkins使用LDAP代理进行认证,有时候登录卡住,在代理的日志里面看到的是代理到AD服务的Connection lost。经过多番观察和排查,发现在客户端、代理和服务端共同导致了这个问题。

Confluence使用了连接池,应该是Java的连接池,到代理的连接会一直保持。而代理到AD服务的连接,会在15分钟后被AD强制切断,这样Confluence下次使用连接的时候,代理到AD的连接就会断掉。

解决办法:
一开始看到Connection lost,就打开了两组连接的TCP keepalive,但是问题依旧。


因为客户端和AD端都不好改动,只能通过改进代理解决。在代理到AD的连接断掉之后,如果对应的客户端到代理的连接还没有关闭,就关闭之。用的Twisted,不熟悉,所以比较麻烦。

2016年10月25日星期二

Chrome vs Safari

用了快一年Safari了,觉得比Chrome好。Safari在如下方面胜过Chrome:
  1. 速度。觉得Safari打开和切换标签的速度比Chrome快。
  2. 稳定性。Safari崩溃次数少于Chrome。
  3. 省电。据说Safari更省电,比如网页里面只有可见的部分才渲染,被其它窗口挡住就不渲染。
  4. 同步方便。在iPhone和iPad上,可以用iCloud tabs和AirDrop同步打开的标签,很方便。Chrome的同步似乎需要翻墙。
  5. 阅读方便。Reader把杂乱的页面的正文格式化成很清爽的格式,Reading List方便稍后阅读。配合上对应的快捷键,方便至极。
  6. 侧边栏。Safari有而Chrome没有侧边栏。在宽屏上侧边栏让屏幕更高效利用。对有些太宽又不能用Reader阅读的网页,打开侧边栏可以让页面宽度减少到更适合阅读。
  7. 界面。界面和OS X系统的界面更一致,比起Chrome也更精致和简洁。
  8. 其它。Show all tabs功能比较酷炫和方便。Chrome应该有扩展实现。
我的Safari扩展
Safari比起Chrome的不足之处:
  1. 扩展数量和质量。扩展少、质量差。数量不比多言,不过我在Safari装的10个扩展也够用了。质量方面,扩展常会影响浏览器工作。比如Ghostery的某条目影响了某些网页的正常打开,装了个模拟Vim快捷键的扩展sVim,结果让所有网银的登陆表单坏了,害我以为是网银插件不兼容了。另外,我自己些的Chrome扩展MyVocab,用了Safari后就没法用了。
  2. 对Google Drive支持不好。不支持Offline。在Google Drive里面用系统自带中文输入法输入中文标点的时候,需要按两次键。不过今天发现这个问题在Safari 10.0.1里面已经没有了。鉴于离线模式我也很少用,以后再也不用Chrome打开Google Drive了。所以我用Chrome来打开Google Drive。
综上,对我的需求和爱好来讲,Safari完胜Chrome。

2016年6月2日星期四

诡异的文件sum不符问题

一个代码文件,我想用sha256sum对比下线上的文件和Git仓库的是否一致。结果发现它们的sum不同。可是如果我把线上的代码复制粘贴到本地计算,或者把本地的代码复制粘贴到服务器上去计算,结果却是一样的。

开始我还以为Mac和Linux的shasum和sha256sum的计算方法不一样,但并没有这样的问题。后来我怀疑是不是换行的问题。在服务器上用Vim打开代码文件,底下的状态栏显示[dos]。之后用cat -ev file就可以让回车换行等无形的字符原形毕露了。

2016年3月19日星期六

Python中.的意义

记得三年前前有同事一起讨论过一个问题,为什么在Python里import boto后不能访问boto.ec2,但是却可以import boto.ec2,或者from boto.ec2 import xxx

其实这个问题的本质是:Python语法里面点操作符"."在不同语境下的不同含义。访问boto.ec2的时候,是从boto获取ec2属性;而在import语句里面,boto.ec2只是一个module或者package的名字,只不过Python碰巧用和前述语境下同样的操作符.来分割package和sub-package。而在文件系统上,package和sub-package是用/来区分的。如果Python也用/,那么文章开头的语句就变成了import boto/ec2,和from boto/ec2 import xxx。这样也就不会有开头的困惑了。

另外,import ec2只是执行了ec2/__init__.py文件,因为这个文件里面没有引入或者定义ec2这个名字,所以访问boto.ec2会出错。

2016年2月25日星期四

一个诡异的HTTP错误

最近一个Django项目,在通过内部一个代理设备访问后,某个表单提交后,就出现了如下的错误:
Bad Request
Your browser sent a request that this server could not understand. Error code: 63
后续的访问也一直出错。通过浏览器调试工具,发现是400错误。把站点的cookie清了就好了。进一步看是一个叫message的cookie项引起的问题,只需删掉这个cookie就好了。

排除了服务后端的故障,然后通过Nginx作反向代理,并为出线上述错误。于是让我们的运维检查这台设备。

这是Array Networks的一个负载均衡设备。开始时候认为是cookie太长,后来发现并不是。这条cookie当我用curl请求时,把这条叫message的cookie内容改成普通字符后,错误消失了。对了,原来的内容是:
messages="835c9e7a8999c8d105885625317e3ffeda5cca89$[[\"__json_message\"\0540\05425\054\"The user \\\"tux\\\" was changed successfully. You may edit it again below.\"]]"
所以我把问题定位为这个设备的bug。

在这之前我都没听过这个公司,原来大家说的"Arrary"不是什么阵列,而是一个网络设备商的名字。考虑到用Google全文搜索开头的出错,只有两条结果且都在国内;考虑到Array Networks市场份额的43%在中国,我更加确定是这个设备的问题了。

根据StackOverflow上这个帖子,得知RFC 6265里面推荐了cookie的值只能是某些普通的ASCII字符,要填这个坑的话就需要去给Django提交建议了。

PS:这个问题解决过程,搜出了“复员军人不接受强拆就是网上通缉犯吗”的帖子,真是醉了……在这个帖子后面有这样的回帖:
昨天早晨,我点击凤凰网论坛、博客、微博,就跳出以下提示:
Bad Request
Your browser sent a request that this server could not understand. Error code: 63 Parser Error: [Cookie: ALLYESID4=0498B7D443AD806F; userid=1344328900625_6468; samemappingcookie=m; _plst[_plid_]=3072171655; py_map=1; vjuids=7d7548b9c.138233b91db.0.3f080ee819d02c; vjlast=1340620903.1345658526.11; ua_map=adchina; pgv_pvi=6917995520; pgv_si=s5491098624; Q37_cookietime=0; prov=cn0851; city=0851; weather_city=gz_gy; olyput=1344836990481%7C1345737966421; if_play_u=bjflGMzpVfSI9V9oT3waAJR4kF4; __gads=ID=fb631e879772a279=1344995081:S=ALNI_Mb4jCw0mDn_bkcI1AY8Mx1giTljlg; reborn=A%2BQLyQi6VeoFsFfOBeoFqlHK; sid=3B0D495188FDFE2858508FF9ECFC3322%E7%99%BD%E4%B9%9F%E8%AF%97; Q37_auth=1jFM%2Bm%2FG0coIROhfIQJMjrX7h2ZRfily6XYD; Q37_sid=iUIeZf; IfengArp_2725=1; IfengArp_2726=0; ifengRotator_ArpAdPro_2013=1; b_his="[{\"b]
我用360度急救后,才又能进入。我请求懂軟件的朋友看看,这提示是否表示我的电脑受到了来自贵州某地的木马攻击!
这位仁兄也遇到了和我一样的错误,不过他的出错信息更详细,给出的错误原因是cookie解析出错,这里显示的cookie也包含某些特殊字符,例如冒号。

PS2:一开始上面这个回帖,我说这哥们是迫害妄想症吧,一看他的ID正好是paranoia,逗坏我了: