[應用]北市疫喵接種預約系統一點看法

看板java作者 (kent)時間3年前 (2021/07/01 11:37), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串1/2 (看更多)
https://booking.health.gov.tw/Home/TakeNum 網路上看到台北市疫喵接種預約系統順利運行,也去看了一下, 試用了一下整個過程是: 1.首頁(同意後選莫德納) ->2.選院所(3個同意再Load時段Json) ->3.填資料送出(未真的送出) 發覺這系統沒上雲端,後台居然還是IIS 10,也沒有提升到HTTP/2, dig一下發現也沒有用DNS做RoundRobin, 查了一下北市75歲以上統計人口約19萬多, 表示單一IP可能要同時承受上萬人的毆打(×)點擊(○), 北市府的資訊處真的厲害的打擊手。 想說如果是一般規模不大的公司要如何解決,盤點一下設計思路, 1.不能時間一到就讓所有人一擁而上。 2.毋須登錄。 3.寫入永遠比讀取慢很多,寫入資料庫則是更慢,檔案則好些。 4.太多人選擇同一時段造成的超額處理。 我想大多數解決人多的想法,就是多架幾台(load balancer)來應付就好, 頻寬不是問題,電信商調整一下就好。 首先第一要務是解決"單一IP可能要同時承受上萬人的點擊"這件事, 當然有錢的買一台高級的負載平衡器,用硬體來解決, 規模不大的公司出不起這個錢,所以我的做法是最前線就是 一台稍微好一點的機器架上一個 Linux Virtual Server(LVS)來分散入口流量, LVS後面就接上2~3台Nginx做反向代理(裝在VM上做Load balancer用), 再來就是架上多台Web Server(也是在VM上)。 大概架構如下(我會把實體機接在同一個Hub上,減少網路傳輸時間, 同樣VM也是分散在不同的實體機): (1)×LVS(實機)→(N)×Nginx(VM)→(X×N)×Tomcat(VM) 因為上述所有的機台都是用Linux,所以自然必須重新調整內核參數, 以應付大量Request,(可以用Nginx併發優化找到一堆內核調整的文章)。 1.防止時間一到所有人一擁而上,最好的策略,就是閱讀測驗: 例如閱讀需知,點選同意與先回答一些問題,最後再跳出視窗再確認一下, 造成每人的時間差異,分散一下開局的壓力。 2.毋須登錄,讓Web程式變成Stateless,也就是request資料, 無論送到哪一台Tomcat都一樣,萬一需要用戶登錄,最簡單的方法就是導入 redisson-tomcat,把Session資料在Tomcat間共享,或都非Tomcat系直接導入 Spring-Session,但是就是要額外多架一台redis server 或是使用Hazelcast Library。(我的建議是redis) 3.最終資料總是要寫入資料庫的,不管怎麼Tune,concurrent connections 最多也只是調整到1、2干個,查詢(快且佔大多數)+寫入(慢很多), 我覺得較好的策略就是快取(讀取結果)+JMS(資料庫緩寫入), 當用戶取得資格,最好的方式就是登記資料寫入redis當快取並 拋給JMS慢慢寫入資料庫,完成再發簡訊。 4.最後要說的就是Race condition的問題,舉例多個人同時看到剩一個 名額時,最簡單的方式,就是開sequence,但缺點是每個院所都要開一個, 也有人用trigger避免超過,但人一多都容易引發DB overwhelming。 更好的方式是使用redis的atomic做取號,超過就叫人重選一次院所。 雖然推薦redis,只是因為網路上都說好,我實際上只用Hazelcast實戰過, 這裡不得說一下,Redis雖然本身雖然有Transction,但她沒有ROLLBACK, 如果要達成XA,必須引入redisson做為redis的Client。 另外還有一些改善點,Nginx支援HTTP/2與Etag, 常用的css,js,與圖片,連到首頁時就用同一個連線送出,並且就加ETag, 下次就客戶端就無須重新載入這些Resources。 北市預約系統的jquery-3.3.1.min.js首頁出來時未加ETag, 選醫療院所第2次才有ETag 然後重選醫療院所時ETag沒有發揮效用,又再一次載入。 不知道是不是IIS的問題, -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 59.120.253.7 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/java/M.1625110647.A.4AC.html
文章代碼(AID): #1WtJXtIi (java)
文章代碼(AID): #1WtJXtIi (java)