aaaa007cn
千年狐狸
千年狐狸
  • UID23968
  • 注册日期2008-05-03
  • 最后登录2022-03-07
  • 发帖数1924
  • 经验1138枚
  • 威望1点
  • 贡献值232点
  • 好评度164点
阅读:2738回复:13

12306 车票预订 XHR 请求超时

楼主#
更多 发布于:2017-03-29 22:11
https://kyfw.12306.cn/otn/leftTicket/init
选择出发地、目的地后点击查询
显示 10 秒的“加载中”动画后
结果没有查到任何车次
这几天白天几乎一直这样
晚上高峰期也经常这样
新建 profile、隐身模式、换其他浏览器都一样症状

F12 开 devtools 看了下日志
https://kyfw.12306.cn/otn/leftTicket/queryX?leftTicketDTO.train_date=日期&leftTicketDTO.from_station=出发地&leftTicketDTO.to_station=目的地&purpose_codes=ADULT

这个 XHR 请求经常是 9 秒多快 10 秒的样子(新窗打开的话,最长有出现过需要 2x 秒才能加载完毕),此时必然没有车次显示
如果哪次能在 2、3 秒完成,那么结果车次就能正常显示

合理猜测这是因为某些原因导致 XHR 请求超时而被掐掉了
切到 debugger 搜索 timeout
马上就能发现 queryLeftTicket_end_js.js 中有处“timeout: 10000”位于 $.ajax 的参数中
下断点并点击查询即可证实(记得先 prettify 下源码

解决方法么
最简单的无疑是直接替换掉 queryLeftTicket_end_js.js 中的 timeout 设置
任意 MITM 代理都可以实现
或者写个简单的 WebExt 扩展也不难

不过目前的情况可以通过劫持 $.ajax 函数来设置我们想要的 timeout 时间
// ==UserScript==
// @name        fuck 12306 xhr timeout
// @namespace   *
// @match       https://kyfw.12306.cn/otn/leftTicket/init
// @version     1
// @grant       none
// ==/UserScript==

(function () {
  $._ajax_orig = $.ajax;
  $.ajax = (...args) => {
    switch (args.length) {
      case 1:
        console.log(`$.ajax => ${args[0].url}`);
        console.log(args[0]);
        if (args[0].url === '/otn/leftTicket/queryX') {
          args[0].timeout = 30000;
        }
        break;
      case 2:
        console.log(`$.ajax => ${args[0]}`);
        console.log(args[1]);
        break;
      default:
        console.log(args);
        break;
    }
    return $._ajax_orig(...args);
  };
}())
alanfly
千年狐狸
千年狐狸
  • UID31035
  • 注册日期2009-11-10
  • 最后登录2024-05-19
  • 发帖数2769
  • 经验580枚
  • 威望1点
  • 贡献值128点
  • 好评度102点
  • 社区居民
  • 最爱沙发
  • 忠实会员
1楼#
发布于:2017-03-29 22:17
本地网络问题吧,我试了几次查询秒出。
aaaa007cn
千年狐狸
千年狐狸
  • UID23968
  • 注册日期2008-05-03
  • 最后登录2022-03-07
  • 发帖数1924
  • 经验1138枚
  • 威望1点
  • 贡献值232点
  • 好评度164点
2楼#
发布于:2017-03-29 22:28
顺便
12306 的自签证书因为仅设置了 common name 而未设置 subjectAltName 即将在 chrome 58 中失效
https://bugs.chromium.org/p/chromium/issues/detail?id=308330
虽然 chrome 团队把 firefox 拖出来帮它们背书
https://bugzilla.mozilla.org/show_bug.cgi?id=1245280
不过目前 firefox 并没有完全禁止未设置 subjectAltName 的证书
比如 12306 这种用户自行导入的根证书签发的证书就不受影响

chrome 58 预计将于一个月后发布 stable
12306 会如何改动、什么时候改动
让我们拭目以待
jiagm
小狐狸
小狐狸
  • UID33074
  • 注册日期2010-06-15
  • 最后登录2018-10-10
  • 发帖数30
  • 经验36枚
  • 威望0点
  • 贡献值4点
  • 好评度2点
3楼#
发布于:2017-03-29 22:39
12306就赶紧把那自签名证书换一下嘛,这么大的网站非得让人自己下载根证书,真是搞不明白怎么想的。
aaaa007cn
千年狐狸
千年狐狸
  • UID23968
  • 注册日期2008-05-03
  • 最后登录2022-03-07
  • 发帖数1924
  • 经验1138枚
  • 威望1点
  • 贡献值232点
  • 好评度164点
4楼#
发布于:2017-03-29 22:56
本地网络问题吧

提醒我了
有可能和分配到的 CDN 节点有关
ping kyfw.12306.cn 在 5、6 毫秒
tcping kyfw.12306.cn 443 在 6、7 毫秒
至少这数据还正常
大概我这里解析出来的几个节点回源的线路有问题?
现在连 405 Method Not Allowed 都出来了

我试试其他省份的节点
myhead
火狐狸
火狐狸
  • UID46565
  • 注册日期2014-07-04
  • 最后登录2020-04-14
  • 发帖数107
  • 经验92枚
  • 威望0点
  • 贡献值20点
  • 好评度8点
5楼#
发布于:2017-03-30 14:35
猜测你是被DNS污染了,再远的国内cdn也不会造成10秒的延迟差距吧。
访问国内站点的连接通常不会用时超过十秒的(如果没卡数据库查询的话),所以我觉得12306这个timeout时间设置应该是没啥问题的。不知道你修改了timeout时间后,有没执行查询超过十秒仍然成功获得正确车次的?
如果没有的话,极有可能说明这个查询的api被解析到了虚假的ip地址(概率性发生,所以有时候ping得到正确ip,有时候得到错误的ip,你多ping几次看看是不是这种情况)。
前一段时间我这边(浙江移动)就发生过大规模的DNS污染现象,对一些热门网站的DNS查询都有几率得到同一网段的虚假ip,导致淘宝、微博等网站根域名被污染间歇性上不去,去哪儿等网站部分api域名被污染导致信息显示不全。
aaaa007cn
千年狐狸
千年狐狸
  • UID23968
  • 注册日期2008-05-03
  • 最后登录2022-03-07
  • 发帖数1924
  • 经验1138枚
  • 威望1点
  • 贡献值232点
  • 好评度164点
6楼#
发布于:2017-03-30 16:46
@myhead
在本坛控制台提示 TypeError: RegExp exec method should return object or null
导致无法直接回复

DNS 解析被投毒了是有可能的
但是 kyfw.12306.cn 是全程 https 的(虽然是使用自签根证书签的网站证书
目前我还没遇上 firefox 提示证书错误的
所以这次应该和 DNS 污染无关

看 4 楼
ping 和 tcping(与 443 成功建立 tcp 连接)的时间都是少于 10 毫秒,非常好了
但是完成请求需要多久就不一定了
还得取决于实际传输的负载大小

每次查询其实会生成 2 个 XHR 请求
除去之前我说的 kyfw.12306.cn/otn/leftTicket/queryX 外
还有个设置了超时 15 秒 kyfw.12306.cn/otn/leftTicket/log

但和 queryX 不同
log 一般都是两位数的毫秒级别就可以完成请求

而 queryX 炸了的时候
请求一般要 10~20 秒才能完成(新窗打开,devtools 看 log
改了 timeout 为 30000 毫秒后一般都可以成功显示结果(当然也遇过这样还超时的,还有之前提到的 405 Method Not Allowed

之前有遇过因为设置了 XHR 超时导致功能异常的例子
https://www.firefox.net.cn/read-50229
不过 12306 这次并无显式提示 XHR 超时
好几天都这样实在无法忍了我才去开 debugger 的
白左
千年狐狸
千年狐狸
  • UID34985
  • 注册日期2010-12-29
  • 最后登录2023-11-13
  • 发帖数2039
  • 经验655枚
  • 威望0点
  • 贡献值364点
  • 好评度69点
  • 社区居民
  • 忠实会员
7楼#
发布于:2017-03-30 17:35

图片:2.png




>>ping kyfw.12306.cn
正在 Ping 12306https.xdwscache.ourglb0.com [101.227.66.207] 具有 32 字节的数据:
来自 101.227.66.207 的回复: 字节=32 时间=3ms TTL=57
来自 101.227.66.207 的回复: 字节=32 时间=4ms TTL=57
来自 101.227.66.207 的回复: 字节=32 时间=3ms TTL=57
来自 101.227.66.207 的回复: 字节=32 时间=3ms TTL=57
-いたんですか? -ええ、ずっと
myhead
火狐狸
火狐狸
  • UID46565
  • 注册日期2014-07-04
  • 最后登录2020-04-14
  • 发帖数107
  • 经验92枚
  • 威望0点
  • 贡献值20点
  • 好评度8点
8楼#
发布于:2017-03-30 19:43
aaaa007cn:@myhead
在本坛控制台提示 TypeError: RegExp exec method should return object or null
导致无法直接回复

DNS 解析被投毒了是有可能的
但是 kyfw.12306.cn 是...
回到原帖
http://www.17ce.com/site/cdn/201703_c1ed9e03ed71ae6f2827cffa0a2f4831.html
http://www.17ce.com/site/cdn/201703_fb3016c9b1ba44ca7a77aee73aecfc46.html
http://www.17ce.com/site/cdn/201703_b0f509f20f31f33727bd64dc1c033e03.html

看起来偶尔有几个节点会延迟爆炸,但常态应该都是在10秒内完成。
你可以看看在请求超过十秒时那个远程主机的ip地址在不在上面的列表里。
还有就是看看网络请求里的详细时间信息,连接超过10秒的情况下时间主要花在哪一步上。最有可能的两个估计是dns resolution和 waiting。
aaaa007cn
千年狐狸
千年狐狸
  • UID23968
  • 注册日期2008-05-03
  • 最后登录2022-03-07
  • 发帖数1924
  • 经验1138枚
  • 威望1点
  • 贡献值232点
  • 好评度164点
9楼#
发布于:2017-03-30 22:10
@alanfly @myhead

curl 请求
南京到苏州 3.31
使用 12306 根证书 srca.crt 验证对端证书
开启压缩
伪造 firefox UA
If-Modified-Since、Cache-Control、X-Requested-With 照搬
curl --cacert srca.crt "https://kyfw.12306.cn/otn/leftTicket/queryX?leftTicketDTO.train_date=2017-03-31&leftTicketDTO.from_station=NJH&leftTicketDTO.to_station=SZH&purpose_codes=ADULT" --compressed -H "If-Modified-Since: 0" -H "Cache-Control: no-cache" -H "X-Requested-With: XMLHttpRequest" -A "Mozilla/5.0 (Windows NT 6.4; rv:52.0) Gecko/20100101 Firefox/52.0" -o NUL



正常水平
size_download:  86961 bytes
      speed_download:  265125.000 B/s
     time_namelookup:  0.000
        time_connect:  0.015
     time_appconnect:  0.078
  time_starttransfer:  0.203
          time_total:  0.328

同一个 ip(使用 --resolve HOST:PORT:ADDRESS 设置
炸了
size_download:  87871 bytes
      speed_download:  9917.000 B/s
     time_namelookup:  0.000
        time_connect:  0.016
     time_appconnect:  0.078
  time_starttransfer:  0.297
          time_total:  8.860

经常超过 10 秒
size_download:  87889 bytes
      speed_download:  5321.000 B/s
     time_namelookup:  0.000
        time_connect:  0.016
     time_appconnect:  0.078
  time_starttransfer:  0.313
          time_total:  16.516

size_download:  87805 bytes
      speed_download:  3704.000 B/s
     time_namelookup:  0.000
        time_connect:  0.015
     time_appconnect:  0.078
  time_starttransfer:  0.281
          time_total:  23.703




使用 --resolve HOST:PORT:ADDRESS 手动解析到其他电信节点
解析结果来自 17ce


14.18.201.48 广州电信
size_download:  86948 bytes
      speed_download:  214157.000 B/s
     time_namelookup:  0.000
        time_connect:  0.031
     time_appconnect:  0.156
  time_starttransfer:  0.265
          time_total:  0.406



61.155.162.122 苏州电信
size_download:  87050 bytes
      speed_download:  278115.000 B/s
     time_namelookup:  0.000
        time_connect:  0.016
     time_appconnect:  0.094
  time_starttransfer:  0.219
          time_total:  0.313



42.81.28.74 天津电信
size_download:  87112 bytes
      speed_download:  253970.000 B/s
     time_namelookup:  0.000
        time_connect:  0.031
     time_appconnect:  0.140
  time_starttransfer:  0.297
          time_total:  0.343

偶尔也炸
size_download:  87317 bytes
      speed_download:  5327.000 B/s
     time_namelookup:  0.000
        time_connect:  0.031
     time_appconnect:  0.140
  time_starttransfer:  0.625
          time_total:  16.390



182.140.147.106 成都电信
size_download:  87004 bytes
      speed_download:  174008.000 B/s
     time_namelookup:  0.000
        time_connect:  0.047
     time_appconnect:  0.187
  time_starttransfer:  0.343
          time_total:  0.500

比天津炸得次数多
size_download:  87313 bytes
      speed_download:  4167.000 B/s
     time_namelookup:  0.000
        time_connect:  0.047
     time_appconnect:  0.187
  time_starttransfer:  0.328
          time_total:  20.953
myhead
火狐狸
火狐狸
  • UID46565
  • 注册日期2014-07-04
  • 最后登录2020-04-14
  • 发帖数107
  • 经验92枚
  • 威望0点
  • 贡献值20点
  • 好评度8点
10楼#
发布于:2017-03-30 23:24
aaaa007cn:@alanfly @myhead

curl 请求
南京到苏州 3.31
使用 12306 根证书 srca.crt 验证对端证书
开启压缩
伪造 firefox UA
If-Modified-Since、Cache-Control、X-R...
回到原帖
感觉是你本地网络的问题……从数据开始传输到结束用时这么久。
我自己本地主机也用curl测试了十次,九次time_total 不到一秒,只有一次time_total 四秒多,而且这一次的time_starttransfer 也是四秒多,也就是说数据传输都是很快完成的。
也用自己的几台海外主机测试了一下,基本没有time_total 和 time_starttransfer 相差超过一秒的。

用mtr看看是不是哪里丢包特别严重?

但是本地网络问题的话无法解释为什么会出现 405 Method Not Allowed……
aaaa007cn
千年狐狸
千年狐狸
  • UID23968
  • 注册日期2008-05-03
  • 最后登录2022-03-07
  • 发帖数1924
  • 经验1138枚
  • 威望1点
  • 贡献值232点
  • 好评度164点
11楼#
发布于:2017-03-31 23:59
防火墙设置有问题导致 traceroute、mtr 不可用
暂时无法测试

至少目前可以确认这样的超时只发生在部分时段的某些节点
而且还不是始终超时,几率不定
虽然有些节点比其他节点更容易超时
myhead
火狐狸
火狐狸
  • UID46565
  • 注册日期2014-07-04
  • 最后登录2020-04-14
  • 发帖数107
  • 经验92枚
  • 威望0点
  • 贡献值20点
  • 好评度8点
12楼#
发布于:2017-04-01 01:09
aaaa007cn:防火墙设置有问题导致 traceroute、mtr 不可用
暂时无法测试

至少目前可以确认这样的超时只发生在部分时段的某些节点
而且还不是始终超时,几率不定
虽然有些节点比其他节点更容易超时
回到原帖
看症状很像是线路拥堵。建议打ISP电话投诉,用不了mtr也没关系,反正运营商的那些人通常连mtr是什么都没听过,投诉理由只需要一条打不开12306或者载入缓慢就足够。
aaaa007cn
千年狐狸
千年狐狸
  • UID23968
  • 注册日期2008-05-03
  • 最后登录2022-03-07
  • 发帖数1924
  • 经验1138枚
  • 威望1点
  • 贡献值232点
  • 好评度164点
13楼#
发布于:2017-04-13 15:31
假期倒是没再遇上这个超时问题
现在又出现了

虽然 traceroute/mtr 不可用
但 ping 和 tcping 的数据都完全正常
没有丢包

此外
多次 curl 测速 https://kyfw.12306.cn/otn/resources/images/pic/new-ad3.jpg 这张 374,302 字节的图片完全没问题
都是 100~200 毫秒完成
只有类似 https://kyfw.12306.cn/otn/leftTicket/query? 这种必须回源的请求才有可能炸
返回的 JSON 越大越容易炸(不论是否开启 gzip)

所以我还是认为问题不在于我这里到那个 CDN 节点的线路
也不在于源服务器查询数据库(部分 CDN 节点表现正常)
仅在于部分 CDN 回源的线路
报障应该找 12306 或它家的 CDN 提供商(网宿?)而不是 ISP

顺便
12306 似乎有改动?
queryX 变成 query 了
游客

返回顶部