日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Vert.x入坑须知(2)

發布時間:2023/12/15 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Vert.x入坑须知(2) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

當初創建簡書賬號的時候曾立下宏愿,希望保持周更,無奈現實殘酷,整個5月都處于忙忙碌碌的狀態,居然令這個本來并不算太宏偉的目標難以為繼,最終導致5月份交了白卷!【好吧,我承認,是我意志不夠堅定,太懶了,;)】

最終的負罪感導致了本文的誕生,同時也意味著一個新坑的開啟。作為Vert.x的使用者,我會定期更新獲得的經驗,希望為同好提供一些小小的幫助,掃除前進的障礙。同時,作為一個懶人和見異思遷者,事先聲明,我沒有辦法保證我的興趣不會發生轉移,所以,我也不知道這個坑能開多久,望大家注意。

那么,讓我們進入主題。

HTTPS請求

這是在跟某運營商的NB-IOT平臺對接時解決的問題,其實最終的整個代碼并不復雜,類似下面(采用雙向認證方式):

httpClient = vertx.createHttpClient(new HttpClientOptions().setSsl(true).setPfxKeyCertOptions(new PfxOptions().setPath("xxx.pkcs12").setPassword("xxx")).setTrustStoreOptions(new JksOptions().setPath("xx.jks").setPassword("xxx")).setVerifyHost(false));

基本上跟文檔上的例子差不多,值得注意的地方就是最后一行代碼:setVerifyHost(false),當時這個運營商的平臺也處于測試狀態,并沒有域名,是自簽證書,設置為false,客戶端不驗證服務端證書的合法性,則可規避這一點,讓整個開發可以不受影響繼續下去。

JWT的密鑰

隨著微服務的流行,JWT也變得流行起來,但有一點開發經常忽視的是直接將生成JWT要用到的證書包含在源代碼中。這一點其實是非常不妥的,有潛在的安全問題。

一個常識是:開發測試用的證書和產品環境的證書要分開,由不同的人來負責管理!

比如,在dgate中,產品環境的證書由運維通過下面的環境變量指定(例子):

export dgate_key_store=./test1.jceks export dgate_key_type=jceks export dgate_key_password=test123

在生成JWT對象時,從環境變量里直接拿這些值,供未來使用。

HTTP Form/Upload請求

這是在實現dgate遇到的需求,小伙伴們強烈要求支持Form提交和文件上傳,于是就有了RelayHandler的誕生。它的實際作用就是請求的透傳,即將請求內容原封不動的搬到后端服務那里去。

實現很簡單,看代碼就知道,但在編寫測試代碼時就遇到了需要發起Form和Upload的問題。這個需求要是放在現在很簡單,因為Vert.x從3.4開始提供了WebClient模塊,用它可以很輕易的實現這樣的需求。

可在當時,這個模塊還沒有出來咧!那就只能自己動手了,因為并沒有那么麻煩,本質上就是按照HTTP協議的要求,向Request寫入對應格式的內容就行了。這一點可以從RequestUtils的form和upload方法實現里看出來。

UDP的Socket

這是在另一個項目中遇到趣事,其實既不是需求也不是問題,而是錦上添花,方便調試。在這個項目中,我們用Vert.x實現了一個UDP Server,用戶的設備會直接向這個Server發包。在一定的條件下,如時鐘不對,Server會向設備發起一個校時命令。

作為負責任的開發,我們當然不會依賴用戶的硬件設備來進行調試啦!也就是說,我們自己是實現了一個MockClient的,它完全實現了設備和服務器的通信協議。內測沒問題之后就到了聯調階段了,可偏偏我們已經發出了校時命令(終端有輸出),但硬件卻說沒有收到!

要命的是,通過Linux的tcpdump來抓包,居然在UDP Server的地址和端口上沒有抓到對應的包!這真是渾身是嘴也說不清啊!而且,自己寫的Mock與Server總是能夠順暢的通信!

遇到這么個怪問題那就不得不上網絡調試的終極大殺器Wireshark了,看看到底發生了什么。很快,問題定位出來了,下發命令確實已經發出,只不過是從另一個端口發出去的。這是因為寫代碼時,覺得UDP反正就沒有連接的概念,只要有對方的地址信息那就直接發送過去就好了。于是,在發送前重新創建了一個DatagramSocket實例,通過它直接發出去了。

實際的修改也很簡單,用UDP Server對應的那個DatagramSocket實例發送就好了。最后的結果當然是皆大歡喜。

與Ignite的集成

我之前不止一次的表達出對于Ignite的喜愛,覺得它比Redis要好(注:最近有所改變,因為Redis提供了對于HpyerLogLog開箱即用的支持,而Ignite則貌似沒有。)。這次,在項目中終于采用了以它為基礎的Vert.x集群方案。

整個集成和使用并不復雜,這是我們做過的事情:

  • 引入依賴和ignite.xml
  • 在Launcher中強制設置為Cluster模式,簡化命令行啟動:
  • @Override public void beforeStartingVertx(VertxOptions options) {//Force to use cluster modeoptions.setClustered(true); }
  • 為了方便后續獲得配置里的緩存,需要對ignite在啟動時進行初始化,于是我們寫了一個工具類,其主要用處就是在啟動前從Vert.x中獲得Ignite并保存起來,方便后續按名字獲取緩存時直接使用。初始化代碼如下(同樣是在Laucher里面,但由于要獲得Vertx實例,故放在afterStartingVertx里):
  • if (ignite == null) {vertxInstance = vertx;ClusterManager clusterManager = ((VertxInternal) vertx).getClusterManager();String uuid = clusterManager.getNodeID();ignite = Ignition.ignite(UUID.fromString(uuid));... }

    有了Ignite實例之后,其他的功能,如Read/Write Through、Cache事件等等,就是按照Ignite文檔的指示來做了。這部分的內容已經屬于Ignite的領域且文檔也有詳細的闡述,這里就不再贅述。

    壓力測試

    作為服務器應用,怎么能不來一把壓測來對其性能摸底呢?在實際過程中,新手最容易忘記的問題就是:沒有修改操作系統的最大可用句柄數,導致壓力還沒上來就進行不下去了。

    除此之外,用Vert.x自寫壓測代碼時也需要注意:

  • 對于UDP服務器來講,注意設置足夠大小的接收緩存,否則會導致Client的包被丟棄,且沒有任何錯誤提示。表象就仿佛服務器掛了或沒有能力處理一樣,而實際的壓力其實遠遠沒有達到服務器的極限。參見下面的代碼:
  • vertx.createDatagramSocket(new DatagramSocketOptions().setReceiveBufferSize(UDP_RECEIVE_BUFFER_SIZE).setSendBufferSize(UDP_SEND_BUFFER_SIZE)).listen(..., "0.0.0.0", asyncResult -> { ... }
  • 在壓測發起端,避免為每個Client生成一個長時間存在的周期Timer。相反,使用一個周期Timer,但針對每個Client生成一個一次性的Timer,模擬隨機發送。同時,要記得用完之后立即釋放。類似的結構如下:
  • vertx.setPeriodic(20000, tid -> {mockClients.forEach((uid, socket) -> {vertx.setTimer(ThreadLocalRandom.current().nextInt(10, 10000), id -> {logger.info("...", uid);send(...);vertx.cancelTimer(id);});}); });

    自此,這段時間積壓下來,覺得有必要寫寫的內容已經全部傾倒完畢,敬請期待下一期(如果真有的話,;))。

    總結

    以上是生活随笔為你收集整理的Vert.x入坑须知(2)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。