写在前面
参考 https://www.cnblogs.com/guozili/p/6144561.html
由于各地CDN节点Cache更新存在时差,所以批量查询全国12306 CDN节点,找到最快的节点获取购票的必要信息。
该文章主要用户学习使用clojure并发获取网络资源,仅限用于学习。
本篇不涉及具体源码,只记录工具、方法。
主要方法
获取CDN节点
根据摸索,大约有两种方式:
- 直接使用
站长工具
->ping测试
获取各个地方ping
域名,该方式简单粗暴,但是可能不同时间ping获取的IP
不一致。 - 利用DNS协议,直接向全国各地DNS服务请求获取指定域名的A记录,该方式可以获取较全面的CDN节点,实现较为复杂。
请求指定CDN节点
参考文章中作者使用.NET语言,其中细节可能不适用。
找到类似问题:
https://stackoverflow.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
中的channel
和alts!!
可以满足我们的需求。
参考示例:
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-http
和 http-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的简单学习,学以致用,实现并发访问网络资源。