Archive for July, 2011
MySQL的Connection自动断开问题
MySQL缺省配置下,会自动断开那些idle超过8小时的Connection,如果应用程序保持这个连接,8个小时(wait_timeout=28800秒)后,用JDBC,再次访问数据库,会有异常抛出,据说用autoReconnect=true可以避免这个问题,不管你信不信,反正我信了,而且好多年前,我就这么做的。
直到最近,在一个鲜有人访问的应用中发现,问题依旧,8小时候后的第一次访问,总是失败,刷新一下页面,就正常了。Google了一下,才知道MySQL不推荐使用autoReconnect=true来解决此问题,http://bugs.mysql.com/bug.php?id=5020,如下:
Note: Autoreconnect functionality will be depcreated and eventually removed in future releases. The reason this isn't working for your particular case is that the methodolgy for autoreconnect was changed to be safer after 3.0.11, and is related to autoCommit state, which will also cause the current 'in-flight' transaction to fail (if you attempt your transaction again _after_ the failure, the driver will reconnect). Please see the docs for the explanation on how to correctly use this feature in the 'Troubleshooting' section. In any case, there is no 100% safe way that a JDBC driver can re-connect automatically if a TCP/IP connection dies without risking corruption of the database 'state' (even _with_ transactional semantics), which is why this feature will eventually be removed. The JDBC spec does not specify that a connection is alive no matter what happens to the underlying network for this very reason. Clients of JDBC drivers are responsible for dealing with network failures, as only the application itself (really the developer of the application) 'knows' what the 'correct' response to a transaction failing due to the network going down is. 'Wait_timeout' expiring on the server is basically a 'forced' network failure by the server. You can correct this in a non-robust way by setting 'wait_timeout' higher, however, you as a developer should be handling SQL exceptions in your code and taking appropriate recovery actions, not just passing them up the call stack.
解决也很简单,记录最近一次的Connection访问时间,如果超过了8小时,就重新建立这个连接,经验证是可行的。另外也可以在建立Connection的同时,创建一个线程定时的去执行一个SELECT 1语句,前面的方法比较简单。
这里要指出的是,用Connection的isValid()方法去检测Connection是否有效是不行的,程序会死在那里(未调查原因),试图用isClosed()去判断Connection是否断开也是行不通的,因为只有明确的调用了Connection的close()方法后,你才能用isClosed()去判断,也就是说Connection在idle超过8小时候后,这个时候你如果去打印它的isClosed()的值,它还是显示false,但实际上却不能使用。
iPhone流量偷跑探秘
换了部iPhone,用的是联通的3G卡,96的套餐,一个月才340M数据,如果要每月1G以上的流量,就得办386的套餐,有些不划算,并且我的移动卡还继续用,算起来就更不划算了。于是先用起来再说。
前3个月,联通每月额外赠送500M的流量,三个月后就恢复到正常的340M每月,所以我得在前几个月把自己的使用方式和习惯建立起来,以便达到套餐使用的最大利用率。第一件事情就是分析自己的每日数据使用量。
于是乎,安装了几个流量监控软件,比如QQ手机管家,Data Usage等。几天监控下来,发现日平均流量很大,至少有几十兆,这样一个月下来,肯定远远超过340M的上限。这些流量监控软件都无法具体看到是哪个程序耗费了流量,所以很难对症下药。我猜测大概是邮件占了绝大多数流量,我设置了2个邮箱,一个Google Apps Gmail,一个是公司的Exchange,还有一个MobleMe的Find My iPhone,都是Push的方式。Push虽然很方便,但是对于这个套餐,太让人纠结了,只能关闭了。
关闭Push后,只开一个Data Usage软件,每隔10多秒观察一下,发现还有流量产生,小的几十、几百B,大的20、30KB。这个就让人纳闷了,难怪网上很多关于iPhone流量偷跑的帖子。Google了一下,发现一个Paros的软件可以嗅探到HTTP访问(我没有去找更好的软件,比如Sniffer Pro,基于HTTP的分析就可以大概了解情况了)。用Paros设置好代理,将iPhone的Cellular Data和3G都关闭,只是使用Wifi,将代理指向Paros。结果很有意思:
需要上网的软件,使用网络无可厚非。那些看似无需网络的软件,很多也会偷偷的访问网络。举几个例子:
- iPhone自带的相册,如果以位置方式查看,会访问: POST http://www.google.cn/glm/mmap HTTP/1.1 …
- iPhone自带的Calendar,每次打开会访问: POST https://m.google.com/Microsoft-Server-ActiveSync?User=hi[at]tcharry.org&DeviceId=Appl8S&DeviceType=iPhone&Cmd=Sync HTTP/1.1 …
- iPhone自带的AppStore,每次打开会访问: GET http://ax.init.itunes.apple.com/bag.xml?ix=2 HTTP/1.1 …
- Google Map,这个是毋庸置疑的,每次都会访问: POST http://www.google.cn/glm/mmap HTTP/1.1 …
- YouDao词典,每次打开访问: GET http://dict.youdao.com/dp/ad?type=pro HTTP/1.1 …
- iBooks:每次打开时访问: GET http://ax.init.itunes.apple.com/bag.xml?ix=2 HTTP/1.1 …
- 穿越小说2011,每次打开时访问: GET http://mob.adwhirl.com/getInfo.php?appid=249a80c9dfab417893156859479944c1&appver=300&client=1 HTTP/1.1 …
- 卫斯理全集,每次打开时访问: GET http://r.admob.com/ad_source.php?isu=666E7E24B1AFD0807B62E0D9DCD9550B&pub_data%5Bdisplay_name%5D=%E5%8D%AB%E6%96%AF%E7%90%86%E5%85%A8%E9%9B%86&ex=1&audio=0&f=jsonp&ad_type=bar&l=en&pub_data%5Bidentifier%5D=com.qq.ireading-wslj&s=a14d720395114b6&client_sdk=1&pub_data%5Bname%5D=aiBooks_glscV1.55&so=p&v=20101108-iSDK-5096df531ccfaf53 HTTP/1.1 …
- iWorks (包括Keynote、Pages、Numbers) ,每次打开时访问: GET http://help.apple.com/config/mobileframework/com.apple.Keynote.plist HTTP/1.1 …
- Adobe iDeas打开时访问: GET http://ax.init.itunes.apple.com/bag.xml?ix=2 HTTP/1.1 …
- 愤怒的小鸟,AngryBird: POST http://data.flurry.com/aap.do HTTP/1.1 …
- Tom猫,Talking Tom2: POST http://i.w.inmobi.com/showad.asm HTTP/1.1 …
- Line Jumper : GET http://SVRSecure-G2-aia.verisign.com/SVRSecureG2.cer HTTP/1.1 …
- Data Usage: GET http://quotaxml.southfreo.com/prod_updates/v12_8/Data%20Usage/version.txt HTTP/1.1 …
注:这些程序并非只访问一个地址,很多程序会访问很多地址,很多次,我只是列出了一个而已。
很多游戏需要连接到Apple的Game Center,即使是非网络游戏,启动的时候也要联网。让人受不了的是,那个我用来检测流量的软件Data Usage也在不停的消耗流量,它每隔一段时间会从去访问一下它的服务器上的Version.txt,估计是为了提示更新。
我还发现有的软件,每次打开都去访问一下新浪博客的注册页面,URL后面跟着它的邀请码,不知道这样会不会给它带来收益,没有仔细的分析,不做论断。综上所述,结论如下:
- iPhone自带的单机软件,也可能访问网络
- 第三方的单机软件,更是扑朔迷离,有的为了广告,有的为了了解自己软件的使用情况,有的为了别的目的
- 单机版的游戏可能会在和Game Center通信的时候消耗流量
- 有的软件,没有做好优化,访问时,发送大量的数据,比如,下图中的‘我查查’,每次请求一个非常长的请求,浪费了用户的流量。
- 最后,如果你的套餐流量有限,不用时就关闭Cellular Data,否则联通就笑开了花。
下图为‘我查查’的请求URL之一:
上面的分析,不一定全面和准确,请自行验证,并且这里只有HTTP的嗅探,如果程序用别的方式访问网络(比如QQ),还是会消耗你的流量。但是管中窥豹,其他协议也不用具体分析了,分析了也不好解决。总之一句话:在天朝用3G,就得认这个蛋疼的命,如果资费便宜了,谁会在乎这点流量。
