作者kentyeh (kent)
看板java
标题[应用]北市疫喵接种预约系统一点看法
时间Thu Jul 1 11:37:25 2021
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://webptt.com/cn.aspx?n=bbs/java/M.1625110647.A.4AC.html