《大型网站技术架构:核心原理与案例分析》读书笔记(三)
8. 固若金汤:网站的安全架构
8.1 道高一尺魔高一丈的网站应用攻击与防御
XSS攻击
XSS攻击即跨站点脚本攻击(Cross Site Script),指黑客通过篡改网页,注入恶意HTML脚本,在用户浏览网页时,控制用户浏览器进行恶意操作的一种攻击方式。
反射型:攻击者诱使用户点击一个嵌入恶意脚本的链接,达到攻击的目的。偷取用户cookie、密码等重要数据,进行伪造交易、盗窃用户财产、窃取情报。
持久型:黑客提交含有恶意脚本的请求,保存在被攻击的Web站点的数据库中,用户浏览页时,恶意脚本被包含在正常页面中,达到攻击目的。
XSS防攻击主要手段:
(1)消毒:XSS攻击者一般都是通过在请求中嵌入恶意脚本达到攻击的目的,这些脚本是一般用户输入中不使用的,如果进行过滤和消毒处理,即对某些html危险字符转移,就可以防止大部分攻击。
(2)HttpOnly:最早由微软提出,即浏览器禁止页面JavaScript范文带有HttpOnly属性的Cookie。HTTPOnly并不是直接对抗XSS攻击的,而是防止XSS攻击者窃取Cookie。对于存放敏感信息的Cookie,可通过对该Cookie添加HTTPOnly属性,避免被攻击脚本窃取。
注入攻击
主要有两种形式:SQL注入攻击和OS注入攻击。
攻击者在HTTP请求中注入恶意SQL命令,服务器用请求参数构造数据库SQL命令时,恶意SQL被一起构造,并在数据库中执行。
攻击者获取数据库表结构信息的手段:
(1)开源:如果网站采用开源软件搭建,那么网站数据结构就是公开的,攻击者可以直接获取。
(2)错误回显:如果网站开启错误回显,即服务器内部500错误会显示到浏览器上。攻击者通过故意构造非法参数,使服务端异常信息输出到浏览器端,为攻击猜测数据库表提供了便利。
(3)盲注:攻击者根据页面变化情况判断SQL语句执行情况,猜测数据库表结构
防御SQL注入攻击首先要避免被攻击者猜测到表名等数据库表结构信息:
(1)消毒:请求参数消毒,通过正则匹配
(2)参数绑定:使用预编译手段,绑定参数是最好的防SQL注入方法。攻击者的恶意SQL会被当做SQL参数,而不是SQL命令被执行。
8.2 信息加密技术及秘钥安全管理
为保护网站的敏感数据,应用需要对这些信息进行加密处理,信息加密技术可分为三类:单向散列加密、对称加密和非对称加密。
单向散列加密
单向散列加密指通过对不同输入长度的信息进行散列计算,得到固定长度的输出,散列计算过程是单向的,即不能对固定长度的输出进行计算从而获得输入信息。常用单向散列算法:MD5、SHA等。该加密算法特点是输入的任何微小变化都会导致输出的完全不同,有时会被用来生成信息摘要、计算具有高离散程度的随机数等用途。
对称加密
对称加密指加密和解密使用的密钥是同一秘钥(或者可以互相推算),通常在信息需要安全交换或存储的场合,如Cookie加密、通信加密等。优点:算法简单,加密效率高,系统开销小,适合对大量数据加密。缺点:加密解密使用同一个密钥。常用算法:DES算法,RC算法。
非对称加密
非对称加密和解密使用的密钥不是同一密钥,其中一个对外公开的公钥,另一个是只有所有者的知道的私钥,该信息不可抵赖,具有签名性质。用公钥加密的信息必须用私钥才能解开,私钥加密的信息只能用公钥才能解开。不能通过公钥计算获得私钥。通常用在信息安全传输,数字签名等场合。实际应用中,常混合使用对称加密和非对称加密。HTTPS传输中浏览器使用的数字证书实质上是经过权威机构认证的费对称加密的公钥。常用算法RSA算法等。
密钥安全管理
改善密钥安全性的手段:
一种方案是把密钥和算法放在一个独立的服务器上,甚至做成一个专用的硬件设施,对外提供加密和解密服务,应用系统通过调用这服务,实现数据的加密解密。
另一种方案是将加密解密算法放在应用系统中,密钥则放在独立服务器中,为了提高密钥的安全性,实际存储时,密钥被切成数片,加密后分别保存在不同存储介质中,兼顾密钥安全性的同时又改善了性能。
8.3 信息过滤与反垃圾
文本匹配
文本匹配主要解决敏感过滤的问题。Trie算法的本质是确定一个有限状态自动机,根据输入数据进行状态转移。双数组Trie算法优化Trie算法,利用两个稀疏数组存储树结构,base数组存储Trie树的节点,check数组进行状态检查。双数组Trie数需要根据业务场景和经验确定数组大小,避免数组过大或者冲突过多。
通过构造多级Hash表进行文本匹配。构造过滤树,用户提交的信息卒子顺序在过滤树中匹配。过滤树的分支可能会比较多,为了提高匹配速度,减少不必要的查找,同一层中相同父节点的字可放在Hash表中。该方案处理速度较快,稍加变形,即可适应各种过滤场景,缺点是使用Hash表会浪费部分内存空间,如果网站敏感词数量不多,浪费部分内存还是可以接受。
11.海量分布式存储系统Doris的可高可用架构设计分析
11.1 分布式存储系统的高可用架构
在系统架构层面,保持高可用的主要手段是冗余:服务器热备,数据多份存储。使整个集群在部分机器故障的情况下可以进行灵活的失效转移,保证系统整体依然可用,数据持久可靠。
Doris的整个架构:
应用程序服务器:它们是存储系统的客户,对系统发起数据操作请求。
数据存储服务器:它们是存储系统的核心,负责存储数据、响应应用服务器的数据操作请求。
管理中心服务器:这是一个由两台机器组成的主-主热备的小规模服务器集群,主要负责集群管理,对数据存储集群进行健康心跳检测,集群扩容、故障恢复管理;对应用程序服务器提供集群地址配置信息服务等。
应用服务器写入数据时,根据集群配置和应用可用性级别使用路由算法在每个序列中计算得到一台服务器,然后同时并发写入这些服务器中;应用服务器读取数据时,只需要随机选择一个序列,根据相同路由算法计算得到服务器编号和地址,即可读取。通常情况下,系统最少写入的副本份数是两份。
在正常状态下,存储服务器集群中的服务器互不感知,不进行任何通信;应用服务器也只在启动时从管理中心服务器获取服务器集群信息,除非集群信息发生变化(故障,扩容),否则应用服务器不会和管理中心服务器通信。一般而言,服务器之间通信越少,就越少依赖,发生故障时互相影响就越少,集群的可用性就越高。
11.2 不同故障情况下的高可用解决方案
分布式存储系统的故障分类
瞬时故障:引起这类故障的主要原因是网络通信瞬时中断、服务器内存垃圾回收或后台线程繁忙停止数据访问操作响应。特点是故障时间段,在秒级升值毫秒级系统即可自行恢复正常响应。
临时故障:引起这类故障的主要原因是交换机宕机、网卡松动等导致的网络通信终端;系统升级、停机维护等一般运维活动引起的服务关闭;内存损坏、CPU过热等硬件原因导致的服务器宕机;这类故障的主要特点是需要人工干预(更换硬件、重启机器等)才恢复正常。通常持续时间需要几十分钟甚至几小时。故障时间可分为两个阶段:临时故障期间,临时故障恢复期间。
永久故障:引起这类故障的主要原因只有一个:硬盘损坏,数据丢失。虽然损坏硬盘和损坏内存一样,可以通过更换硬盘来重启机器,但丢失的数据却永远找不回来了,因此其处理策略也和前面两种故障完全不同,恢复系统到正常状态也需更长时间。故障时间可分为两个阶段:永久故障期间和永久恢复期间。
正常情况下系统访问结构
应用程序在写数据时,需要路由计算获得两台不同的服务器,同时将数据写入两台服务器;而读数据时,只需要到两台服务器上任意一台服务器读取即可。
瞬时故障的高可用解决方案
瞬时故障是一种严重性较低的故障,一般系统经过较短暂的时间即可自行恢复,遇到瞬时故障只需要多次重试,就可以重新连接到服务器,正常访问。
Doris瞬时故障解决方案:
(1)应用服务器向存储服务器请求服务,
(2)通信超时,不可识别异常,
(3)应用服务器重新请求X次直到成功。
Doris瞬时失效访问模型:
(1)应用程序服务器访问存储服务器失败,
(2)应用程序服务器访问存储服务器重试,
(3)应用程序服务器向管理中心服务器进行失效仲裁
(4)管理中心服务器对存储服务器健康心跳检测、失效仲裁检测。
12.2 秒杀系统的应对策略
(1)秒杀系统独立部署
(2)秒杀商品页面静态化
(3)租借秒杀活动网络宽带
(4)动态生成随机下单页面URL
12.3 秒杀系统架构设计
(1)控制秒杀商品页面购买按钮的点亮
(2)只允许第一个提交的订单被发送到订单子系统
13 大型网站典型故障案例分析
13.1 写日志也会引发故障
故障现象:某应用服务器集群发布后不久就出现多台服务器相继报警,硬盘可用空间低于警戒值,并且很快有服务器宕机,登录到线上的服务器,发现log文件夹里的文件迅速增加,不断消耗磁盘空间。
原因分析:100GB小硬盘,系统,web服务器,Java虚拟机,应用程序等在一个应用服务器,不需存储数据。空闲空间只有几十GB,但开发人员将log输出的level全局配置为Debug,web请求会产生大量的log文件输出,在高并发的用户请求下,很快就消耗完不多的磁盘空间。
13.2 高并发访问数据库引发的故障
故障现象:某应用发布后,数据库Load居高不下,远超过正常水平,持续报警。
原因分析:执行频率非常高的有索引数据查询的SQL,远超正常水平,追查这条SQL,发现该网站首页应用调用,首先是被访问最频繁的网页,这条SQL被首页调用,也被频繁执行。
13.3 高并发情况下锁引发的故障
故障现象:某应用服务器不定时地因为响应超时而报警,但很快又超时解除,恢复正常,如此反复,让运维人员非常苦恼。
原因分析:程序中某个单例对象中多处使用了synchronized(this)由于this对象只有一个,所有的并发请求都要排队获得这唯一的一把锁。一般情况下,一些简单操作获得锁,迅速完成操作,释放锁,不会引起线程排队。但某个需要远程调用的操作也被加了synchronized(this),这个操作知识偶尔会被执行,但每次执行都需要较长的时间才能完成,这段时间锁被占用,所有的用户线程都要等待,响应超时,这个操作执行完后释放锁,其他线程迅速执行,超时解除。
经验教训:使用锁操作要谨慎。
13.4 缓存引发的故障
故障现象:没有新应用发布,但是数据库服务器突然Load飙升,并很快失去响应。DBA将数据库访问切换到备机,Load也很快飙升,并失去响应,最终引发网站全部瘫痪。
原因分析:缓存服务器再网站服务器集群中地位一致比较低,服务器配置和管理级别都比其他服务器要低一些,长期疏于管理缓存服务器,关闭缓存服务器集群的Memcached服务器,导致网站全部瘫痪的重大事故。
经验教训:当缓存已经不仅仅是改善性能,而是成为网站架构不可或缺的一部分时,对缓存的管理就需要提高到和其他服务器一样的级别。
13.5 应用启动不同引发的故障
故障现象:某应用发布后,服务器立即崩溃。
原因分析:应用程序Web环境使用Apache——JBoss的模式,用户请求通过Apache转发JBoss,在发布时,Apache和JBoss同时启动,由于JBoss启动时需要加载很多应用并初始化,话费时间较长,结果JBoss还没完全启动,Apache就已经启动完成开始接受用户请求,大量请求阻塞在JBoss进场中,最终导致JBoss崩溃。除了这种Apache和JBoss启动不同步的情况,网站还有还有很多类似的场景,都需后台服务准备好,前台应用才能启动,否则就会导致故障。
经验教训:在应用程序加入一个特定的动态页面(比如返回OK),启动脚本先启动JBoss,然后在脚本中不断用curl命令访问这个特定页面,直接受到OK,才启动Apache。
13.6 大文件读写独占磁盘引发的故障
故障现象:某应用主要功能时管理用户图片,接到部分用户投诉,表示上传图片非常慢,原来只需一两秒,现在需几十秒,有时等半天结果浏览器显示服务器超时。
原因分析:图片需要使用存储,最可能出错的地方是存储服务器。检查存储服务器,发现大部分文件只有几百KB,而是几个文件非常大,有数百兆,读写这些大文件一次需要几十秒,这段时间,磁盘基本被这文件操作独占,导致其他用户的文件操作缓慢。
经验教训:存储的使用需要根据不同文件类型和用途进行管理,图片都是肖文杰,应该使用专用的存储服务器,不能喝大文件共用存储,批处理用的大文件可以使用其他类型的分布式文件系统。
13.7 滥用生产环境引发的故障
故障现象:监控发现某个时间段,某些应用突然变慢,内部网络访问延迟非常厉害。
原因分析:检查发现,该时段内网卡流量也下降,但没找到原因,工程师在线上生产环境进行性能压力测试,占用率大部分交换机带宽。
经验教训:访问线上生产环境要规范,不小心就会导致大事故。
13.8 不规范的流程引发的故障
故障现象:某应用发布会,数据库Load迅速飙升,超过报警值,回滚发布后报警消除。
原因分析:发现该应用发布后出现大量数据库读操作,而这些数据本来应该从分布式缓存读取。检查缓存,发现数据已经数据已经被缓存了。检查代码,发现访问缓存的那行代码被注释掉了。读取缓存的代码被注释掉了。
经验教训:
(1)代码提交前使用diff命令进行代码比较,确认没有提交不该提交的代码。
(2)加强code review,代码在正式提交前必须被只是一个其他工程师做过code review,并且共同承担因代码引起的故障责任。
13.9 不好的编程习惯引发的故障
故障现象:某应用更新功能后,有少量用户投诉没法正常访问该功能,一点击就显示出错误信息。
原因分析:原因分析,分析这些用户都是第一次使用该功能,检查代码,发现程序历史使用记录构造一个对象,如果该对象为null,导致NullPointException
经验教训:
(1)程序在处理一个输入的对象时,如果不能明确该对象是否为空,必须做空指针判断。
(2)程序在调用其他方法时,输入的对象尽量保证不是null,必要时构造空对象(使用空对象模式)
翻译 朗读 复制 正在查询,请稍候…… 重试 朗读 复制 复制 朗读 复制 via 谷歌翻译(国内) 译
浙公网安备 33010602011771号