【大型网站技术架构笔记】(四)伸缩性、可扩展性与安全

网站架构的伸缩性设计

一般手段有两种。一类是根据功能进行物理分离,一类是对单一功能进行集群化来实现。比如将缓存、静态文件、数据库服务从服务器中拆分进行单独部署,比如对业务逻辑进行横向纵向切分等,都属于通过物理分离来达成整个系统处理能力的伸缩。对服务进行集群化这个应用场景非常广泛。此处无需再多说。

应用服务器进行伸缩的方法

网站进行伸缩过程中,由于采用了集群技术,所以不可避免的要面对服务集群化后的负载均衡问题。以下有集中比较主要的服务器端负载均衡手段。

HTTP重定向负载均衡

用户发请求给重定向服务器,通过负载均衡算法算出实际物理服务器地址,然后封装在响应头中返给客户端,同时将状态设置为302(redirect)。客户端收取请求后,再访问实际地址。该方法需要和客户端交互两次,且采用了302重定向状态码,有可能会被判断为SEO作弊。所以使用的案例并不多。

DNS域名解析负载均衡

在DNS服务器中配置多个A记录即可。比如www.baidu.com A 111.18.82.21,www.baidu.com A 111.28.82.21,www.baidu.com A 111.38.82.21.当服务器收到客户端的域名请求时,会通过负载均衡算法(一般是rr)来找到对应的IP并返回给客户端,客户端根据IP地址进行请求。其优点在于将负载均衡交给了DNS,省去了网站自己维护的成本。同时DNS也区分了地域,如此可以较为便捷地就近实现负载均衡。但其缺点在于由于DNS是多级向上查询的机制,所以各级DNS服务器都需要缓存对应的信息。其可能造成短暂时间内的域名解析数据的不一致。比如ip更新、删除等。

反向代理负载均衡

其即为七层负载均衡。对请求进行转发。同时具备缓存功能。可以对静态资源进行缓存。同时可防止集群被攻击。比较主流的有nginx。

IP负载均衡

Load Balancer通过修改报头的源/目的ip地址和端口号,来达到“欺骗”真实服务器的目的。将源ip地址修改为当前BL(或者直接将BL设置为网关服务器),将目的ip地址修改为真实服务器(RS)。当RS处理后返回给LB时,LB再将ip修改还原后返回。由于IP负载均衡过程中往往需要修改端口号。端口属于传输层内容。所以虽然原书认为其属于网络层,但我认为更应该属于四层负载均衡,LVS的NAT模式即是如此。LVS还加入了IP隧道模式(TUN),其不再“欺骗”RS,而采取将原报文封装到新包中,通过IP隧道技术发给RS,其相对于DR模式的优势在于不要求网段相同,但缺点在于由于采用了隧道技术而使得运维变得比较麻烦。

LVS的NAT(网络地址转换)模式:

【大型网站技术架构笔记】(四)伸缩性、可扩展性与安全

LVS的TUN(IP隧道)模式:

【大型网站技术架构笔记】(四)伸缩性、可扩展性与安全

数据链路层负载均衡

原理简单来说即:LB和RS具备相同虚拟IP地址。通过LB来修改客户端发来的请求的目的mac地址。从而不需修改任何端口和IP地址,即可将请求转发至RS服务器,RS计算后直接将响应返送回客户端。LVS的DR(直接路由)模式即是通过改手段实现的。

LVS的DR(直接路由)模式:

【大型网站技术架构笔记】(四)伸缩性、可扩展性与安全

负载均衡算法

一般有轮询(RR)、加权轮询(WRR)、随机、最少请求、源ip散列等手段。

分布式缓存的伸缩性设计

一般考虑引入一致性哈希来进行负载均衡。同时能够达成水平扩展,所以一般采用虚拟化一致性哈希来达成这一目的。具体参考之前博客。按照经验,一台物理服务器一般虚拟出150个左右的虚拟节点较为合适,但也需要case by case。

数据存储的伸缩性设计

分布式关系型数据库的伸缩一般采用的是分库分表,其就需要一个中间层来实现分库分表逻辑的透明化;尽量避免使用分布式事务,或者采用事务补偿机制。比如一个请求会对A数据库和B数据库进行跨库操作。那么当A执行成功后,执行B失败时,则将A也进行回滚。以此实现事务补偿。所谓的事务补偿即在事务链中,有一个正向操作必然也带有一个回滚的负向操作。除了关系型数据库外,NOSQL数据库非常适合进行系统的伸缩,比如hbase和mongo等。

网站的可扩展设计

从系统架构层面来说,一般采用的是分布式消息队列和分布式服务。来达成较大程度的解耦和微服务化。分布式服务化之后就需要考虑如何进行通讯,比如可以采用WebService、Thrift、Dubbo等技术。从代码层面上,则需要在进行设计的时候遵循开闭原则,单一职责原则等其他基础设计思想。

网站的安全性考虑

常见的攻击方式

这里主要有三种XSS、SQL注入以及CSRF。除此之外还有文件上传漏洞、路径遍历等方式。

XSS即跨站点攻击,通过嵌入代码来获取用户cookie,并以此进行恶意操作。CSRF即在用户已经登陆信任站点的前提下,用户又登陆了一个钓鱼网站,构造请求攻击受信任站点。此时cookie与session与真实访问一样无法识别出来。而SQL注入则是在请求参数中,注入SQL语句,从而来达到恶意攻击的目的。比如请求wwww.baidu.com?username=”surlymo;drop userinfo”。文件上传的话,则可能被上传恶意执行文件从而攻击服务器;路径遍历是攻击者通过url来尝试遍历站点的文件内容。

应对措施

  1. 应对XSS攻击,对cookie采用http-only标识,声明其禁止被脚本访问。其直接解决了XSS的问题;其次,对用户输入的特殊字符进行消毒。比如识别用户输入的<IMG src="">时,就进行自动转义。
  2. 应对CSRF共计,采用随机数token,验证码,以及验证HTTP请求头中的referer里的请求来源信息来进行检验。
  3. 针对SQL注入,可以采用语义消毒,对drop等危险操作进行消毒;其次,进行参数绑定,强行指定输入参数只能作为参数,而无法作为SQL语义进行翻译。
  4. 针对文件上传问题,设置文件类型白名单。
  5. 针对路径遍历问题,进行资源的动静分离。url仅能访问静态资源。或者进行权限校验。

相关推荐