12306余票高效查询--clojure实现

时间:2021-07-12 01:52:52

写在前面

参考 https://www.cnblogs.com/guozili/p/6144561.html
由于各地CDN节点Cache更新存在时差,所以批量查询全国12306 CDN节点,找到最快的节点获取购票的必要信息。
该文章主要用户学习使用clojure并发获取网络资源,仅限用于学习。
本篇不涉及具体源码,只记录工具、方法。

主要方法

获取CDN节点

根据摸索,大约有两种方式:

  1. 直接使用站长工具->ping测试获取各个地方ping域名,该方式简单粗暴,但是可能不同时间ping获取的IP不一致。
  2. 利用DNS协议,直接向全国各地DNS服务请求获取指定域名的A记录,该方式可以获取较全面的CDN节点,实现较为复杂。

请求指定CDN节点

参考文章中作者使用.NET语言,其中细节可能不适用。
找到类似问题:
https://*.com/questions/7648872/can-i-override-the-host-header-where-using-javas-httpurlconnection-class
其中提到可以使用apache http client实现,而clj-http就是封装的apache http client。
所以只需将访问的url中域名替换为具体的CDN节点IP,然后在请求的Header中带上Host: xxx.com即可。

批量获取

多线程并发获取,目标只是获取最快成功的。
使用clojure.core.async中的channelalts!!可以满足我们的需求。
参考示例:
https://github.com/clojure/core.async/blob/master/examples/walkthrough.clj

;; Since go blocks are lightweight processes not bound to threads, we
;; can have LOTS of them! Here we create 1000 go blocks that say hi on
;; 1000 channels. We use alts!! to read them as they're ready.

(let [n 1000
      cs (repeatedly n chan)
      begin (System/currentTimeMillis)]
  (doseq [c cs] (go (>! c "hi")))
  (dotimes [i n]
    (let [[v c] (alts!! cs)]
      (assert (= "hi" v))))
  (println "Read" n "msgs in" (- (System/currentTimeMillis) begin) "ms"))

使用工具

clojure相关库可以在 https://www.clojure-toolbox.com/ 查询。

http client

网上查找,发现两个比较受欢迎的库:clj-httphttp-kit。后者PR较好,于是先尝试其。
当涉及cookie相关发现支持并不是很好,于是查看clj-http,发现其是包装了org.apache.http.client.CookieStore

clj-http地址:https://github.com/dakrone/clj-http

core.async

参考资料:
https://morrxy.github.io/2016/08/02/brave-clojure-core-async/
http://clojuredocs.org/clojure.core.async/alts!!
https://segmentfault.com/a/1190000004314890

总结

通过对core.async的简单学习,学以致用,实现并发访问网络资源。