大型网站系统与JAVA中间件实践 学习总计 一
前言
首先大致了解一下大型网站的架构演进。一个单机的网站是怎么一步一步演变成一个集群网站。
一、用 JAVA技术和单机来构建的网站
一开始我们基本上会选择一个开源的server作为容器,直接使用JSP/Servlet等技术或者使用一些开源框架来构建我们的应用;然后选择一个数据库管理系统来存储数据,通过JDBC进行数据库的连接和操作。这样一个单机的网站就搭好了。整体结果如下图所示。
二、将单机系统设定为交易网站
为了更好的说明网站从小到大的演进过程,我们举一个交易类网站的例子。
作为一个交易类网站,需要的基本功能有三个部分:
- 用户
- 用户注册
- 用户管理
- 信息维护
- …等等
- 商品
- 商品展示
- 商品管理
- …等等
- 交易
- 创建交易
- 交易管理
- …等等
我们先只设计这三个部分,那么整体结构会如下图所示。
三、单机负载警告,数据库与应用分离
网站得到用户的认可,使用的用户越来越多,访问量不断增大,单机服务器的负载持续升高,导致整个服务器开始卡顿,那么我们必须采取一些办法来应对了。首先我们可以做的就是把数据库操作与应用从 一台机器分到两台机器上,最好两个机器是在同一个内网中的,这样延时比较低。那么我们的网站结构会变成下图的结构了。
四、应用服务器负载告警,如何让应用服务器走向集群
应用服务器的压力不断变大,应该根据监测结果一步一步的优化。我们这里介绍从单机变成集群的优化方式。先看一下结构变化吧。
在这种情况下会有两个问题需要注意。
- 两个应用服务器访问的选择问题。
- session的问题。
访问选择问题—引入负载均衡
对于用户怎么选择应用服务器,就可以引入负载均衡来进行处理,负载均衡中有许多服务器过滤方案,可以配置好用户选择服务器的问题。如下图所示。
解决session问题
如下图所示,如果我们第一次访问网站时请求落到了左边的服务器,那么我的session就创建在左边的服务器上,如果我们不做处理,就不能保证接下来的请求每次都落在同一边服务器上,这就是session问题。
Session Sticky
负载均衡器根据每次请求的绘画标识来进行请求转发,让每次请求都是访问的同一个服务器,如下图所示。
Session Replication
在Session Replication中,不再要求负载均衡器来保证同一个会话的多次请求必须到同一个Web服务器上了,而是我们的Web服务器之间会进行会话诗句的同步,这样就保证了不同Web服务器之间的Session数据一致了。如下图所示。
Session数据集中存储
这个方式是把Session数据集中存储到一起,然后不同Web服务器从同样的地方来获取Session,从而保证Session一致。如下图所示。
Cookie Based
这个方案是通过Cookie来保存session数据,这就好比我每次把自己的筷子带在身上,这样我去哪家饭店吃饭都可以任意选择。如下图所示。
五、数据读压力变大,读写分离
随着业务的发展,我们的数据量和访问量都在增长,所以我们可以在前面的结构上增加一个读库,这个库不承担写的工作,只提供读服务,如下图所示。
搜索引擎其实是一个读库
随着系统越来越大,搜索的东西与方式也越来越多,进而会引进不同的搜索引擎,来提高搜索效率。搜索引擎其实就是一个读库。如下图所示。
加速数据读取的利器—缓存
缓存,也就是我们常说的Cache。常用的缓存分别是数据缓存与页面缓存。
数据缓存
众所周知,每次连接并操作数据库是很耗资源的,而缓存能够将许多热数据保存下来,用户请求热数据时,并不需要通过数据库去查询并直接返回给用户,当用户请求的数据缓存中没有的时候,才会去从数据库拿,大大降低了数据库的开销。当增加了缓存后,结构会变成下图结构。
页面缓存
用户请求页面时,会有许多的js文件,图片或者视频等静态资源,页面缓存就会将这些资源加上标识,用户访问的时候,查看静态资源是否有标识,有标识则表示有缓存资源,直接返回给用户,用户能够更快的渲染页面,没有则再从服务器上取。能够减少带宽的消耗,又能增加用户的响应速度。
六、弥补关系型数据库的不足,引入分布式存储系统
在之前的介绍中用于数据存储的主要是数据库,但是在有些场景下,数据库并不是很合适,比如数据量大,需要进行全文检索的场景,数据库就会查询的很慢并且达不到预期的效果。我们平时使用的多为单机数据库,并且提供了强的单机失误的支持。处理数据库之外,还有其他用于存储的系统,也就是我们常说的分布式存储系统。分布式存储系统在大型网站中有非常广泛的使用。引入分布式存储系统后,结构会是下图的结构。
七、读写分离后,数据库又遇到瓶颈
通过前面的优化后,随着业务的不断发展,我们的主库也会遇到瓶颈。网站演进到现在,交易、商品、用户的数据还都在一个数据库中,尽管采取了增加缓存、读写分离的方式,这个数据库的压力还是在继续增加,因为我们需要去解决这个问题骂我们有数据垂直拆分和水平拆分两种选择。
专库专用,数据垂直拆分
垂直拆分的意思是把数据库中不同的业务数据拆分到不同的数据库中,结合现在的例子,就是把交易、商品、用户的数据分开,如下图所示。
垂直拆分后的单机遇到瓶颈,数据水平拆分
水平拆分就是把同一个表的数据拆到两个数据库中。产生数据水平拆分的原因是某个业务的数据表的数据量或者更新量达到了单个数据库的瓶颈,这时就可以把这个表拆分到两个或者多个数据库中。结构如下图所示。
一旦我们能够完成数据的水平拆分,我们将能够很耗的应对数据库及写入量增长的情况。
八、数据库问题解决后,应用面对的新挑战
随着业务的发展,应用的功能会越来越多,应用也会越来越大,我们需要考虑如何不让应用持续变大,这就需要把应用拆开,从一个应用变成两个或多个应用。
拆分应用
根据功能拆分应用
在我们的例子中,主要的业务功能有交易、商品、用户。由于交易与商品都用的到用户,所以我们可以拆分为交易、商品两个应用,如下图所示。
拆分之后在不同系统中有一些相似的代码,例如用户相关的代码。如何能够保证这部分代码的一致一级如何对其复用是需要解决的问题。此外,这样拆分出来的新系统之间一般没有互相调用,而且新拆出来的应用可能连接同样的数据库。如下图所示。
走服务化的路
我们再来看一下服务化的做法。
从中可以看到我们把应用分为了三层,处于最上端的是Web系统,用于完成不同的业务功能;处于中间的是一些服务中心,不同的服务中心提供不同的业务服务;处于下层的则是业务的数据库。
与之前相比有几个很重要的变化:
- 业务功能之间的访问不仅是单机内部的方法调用了,还引用了远程的服务调用。
- 共享的代码不再是散落在不同的应用中了,这些实现被放在了各个服务中心。
- 数据库的连接也发生了一些变化,我们把与数据库的交互工作放在服务中心,让前端的Web应用更加注重与浏览器交互的工作,不必过多关注业务逻辑的事情,并且可以降低数据库的连接数。
- 服务中心将散落在各个业务的代码集中了起来,能够更好的维护。
- 通过服务化,无论是前端Web应用还是服务中心,都可以由固定小团队来维护系统。
九、初识消息中间件
消息中间件是分布式系统中完成消息的发送和接受的基础软件。为什么要使用消息中间件呢?因为消息中间件有两个常被提及的好处,即异步和解耦。下图是消息中间件的一般结构。
可以从图中看到,应用A和应用B都和消息中间件打交道,而这两个应用之间并不直接联系。这样就完成了解耦,目的是希望收发消息的双发彼此不知道对方的存在,也不受对方影响,所以将消息投递给接收者实际上都采用了异步的方式。
总结
这里讲解了一个单机网站应用怎么变成大型网站应用的大概过程(并不是全部按部就班演进的)。随着业务到不同的阶段都需要不同的手段来优化应用,才能保证应用的稳定性。最后看一下演进之后我们的网站样子吧。
引用《大型网站系统与JAVA中间件实践》