目录

大型网站系统与Java中间件实践-笔记-02

第2章 大型网站及其架构演进过程

2.1 什么是大型网站

要满足一个网站是大型网站,需要很多因素。大型网站除了要支撑海量的数据和非常高的并发访问量,本身业务和系统的复杂度也是考察的方面。

2.2 大型网站的架构演进

2.2.1 用Java技术和单机来构建的网站

  • 选择一个开源的Server作为容器
  • 直接使用JSP/Servlet等技术或者使用一些开源框架来构建应用
  • 选择一个数据库管理系统来存储数据
  • 通过JDBC进行数据库的连接和操作

2.2.2 从一个单机的交易网站说起

作为一个交易网站,需要具备的最基本功能:

  • 用户
    • 用户注册
    • 用户管理
    • 信息维护
    • ……
  • 商品
    • 商品展示
    • 商品管理
    • ……
  • 交易
    • 创建交易
    • 交易管理
    • ……

2.2.3 单机负载告警,数据库与应用分离

网站访问量增大,服务器的负载持续升高。 解决方案:应用与数据库从一台机器分到两台机器。

2.2.4 应用服务器负载告警,如何让应用服务器走向集群

应用服务器压力变大,将应用服务器从一台变成两台,但是有两个问题需要解决:

  • 最终用户对两个应用服务器访问的选择问题
  • Session的问题
2.2.4.1 引入负载均衡设备

负载均衡来解决应用服务器访问的选择问题。

2.2.4.2 解决应用服务器变为集群后的Session问题
2.2.4.2.1 Session Sticky

Web服务器变成多台以后,如果保证同一个会话的请求都在同一个Web服务器上处理,那么对这个会话的个体来说,与之前单机的情况是一样的。如果要做到这样,就需要负载均衡器能够根据每次请求的绘画标识来进行请求转发,这称为Session Sticky方式。

不过也带来了如下几个问题:

  • 如果有一台Web服务器宕机或者重启,那么这台机器上的会话数据就会丢失。
  • 会话标识是应用层的信息,那么负载均衡器要将同一个会话的请求都保存到同一个Web服务器上的话,就需要进行应用层(第7层)的解析,这个开销比第4层的交换要大。
  • 负载均衡器变为了一个有状态的节点,要将会话保存到具体Web服务器的映射。和无状态的节点相比,内存消耗会更大,容灾方面会更麻烦。
2.2.4.2.2 Session Replication

在Session Replication方式中,不再要求负载均衡器来保证同一个会话的多次请求必须到同一个Web服务器上了。而我们的Web服务器之间则增加了会话数据的同步。通过同步就保证了不同Web服务器之间的Session数据的一致。

不过这个方案本身也有问题:

  • 同步Session数据造成了网络带宽的开销。只要Session数据有变化,就需要将数据同步到所有其它机器上,机器数越多,同步带来的网络带宽开销就越大。
  • 每台Web服务器都要保存所有的Session数据,如果整个集群的Session数很多(很多人在同时访问网站)的话,每台机器用于保存Session数据的内容占用会很严重。

这个方案不适合集群机器数多的场景,如果只有几台机器,用这个方案是可以的。

2.2.4.2.3 Session数据集中存储

将Session数据放在了一个集中存储的地方,统一从这里读写。

该方案存在的问题:

  • 读写Session数据引入了网络操作,这相对于本机的数据读取来说,问题就在于存在延时和不稳定性,不过我们的通信基本都是发生在内网,问题不大。
  • 如果集中存储Session的机器或者集群有问题,就会影响我们的应用。

相对于Session Replication,当Web服务器数量比较大、Session数比较多的时候,这个集中存储方案的优势是非常明显的。

通过Cookie来传递Session数据。

该方案存在的问题:

  • Cookie长度的限制。
  • 安全性。
  • 带宽消耗。
  • 性能影响。

2.2.5 数据读写压力变大,读写分离吧

2.2.5.1 采用数据库作为读库

对于大型网站来说,有不少业务是读多写少的,这个状况也会直接反应到数据库上。所以在结构上增加了一个读库,这个库不承担写的工作,只提供读服务。

这个结构的变化会到来两个问题:

  • 数据复制问题
  • 应用对于数据源的选择问题
2.2.5.2 搜索引擎其实是一个读库

搜索引擎的技术解决了站内搜索时某些场景下读的问题,提供了更好的查询效率。并且我们看到的站内搜索的结构和使用读库是非常类似的,我们可以把搜索引擎当成一个读库。

2.2.5.3 加速数据读取的利器——缓存
2.2.5.3.1 数据缓存
  • “热”数据缓存,即应用访问缓存,如果数据不存在,则从数据库读出数据后放入缓存;
  • 全数据缓存,在数据变化时能够及时更新缓存中的数据,不会造成读取失败。
2.2.5.3.2 页面缓存
  • Nginx
  • Tomcat

2.2.6 弥补关系型数据库的不足,引入分布式存储系统

常见的分布式存储系统有分布式文件系统、分布式Key—Value系统和分布式数据库。 分布式存储系统自身起到了存储的作用,也就是提供数据的读写支持。 分布式存储系统通过集群提供了一个高容量、高并发访问、数据冗余容灾的支持。

2.2.7 读写分离后,数据库又遇到瓶颈

2.2.7.1 专库专用,数据垂直拆分

垂直拆分的意思是把数据库中不同的业务数据拆分到不同的数据库中。

带来的问题:

  • 应用需要配置多个数据源,不过带来了数据库连接池的隔离;
  • 事物处理,一种办法是分布式事务,性能低,另一种办法是去掉事务或者不去追求强事务支持。
2.2.7.2 垂直拆分后的单机遇到瓶颈,数据水平拆分

数据水平拆分就是把同一个表的数据拆到两个数据库中。

带来的影响:

  • 应用系统需要解决SQL路由的问题;
  • 主键的处理
  • 一些查询需要从两个数据库中取数据,如果数据了太大而需要分页,就会比较难处理。

2.2.8 数据库问题解决后,应用面对的新挑战

2.2.8.1 拆分应用

根据业务的特性把应用拆开。 影响:

  • 这样拆分后在不同系统中会有一些相似的代码。如果能够保证这部分代码的一致以及如何对其复用是需要解决的问题;
  • 按这样的方式拆分出来的新系统之间一般没有直接的相互调用;
  • 新拆出来的应用可能会连接同样的数据库。
2.2.8.2 走服务化的路

把应用分为了三层:

  • 处于最上端的是Web系统,用于完成不同的业务功能;
  • 处于中间的一些服务中心,不同的服务中心提供不同的业务服务;
  • 处于下层的则是业务的数据库。

与之前相比有几个很重要的变化:

  • 业务功能之间的访问不仅是单机内部的方法调用,还引入了远程的服务调用;
  • 共享的代码不再是散落在不同的应用中,这些实现被放在了各个服务中心;
  • 把与数据库的交互工作放到了服务中心,让前端的Web应用更加注重与浏览器交互的工作;
  • 通过服务化,能够更好的保持稳定性。

2.2.9 初识消息中间件

面向消息的系统是在分布式系统中完成消息的发送和接受不了的基础软件。