开发者学堂课程【高校精品课-上海交通大学-企业级应用体系架构:Arch. Components 1】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/75/detail/15819
Arch. Components 1(二)
内容介绍:
一、企业应用的基本特征
二、一台机器的优缺点
三、拆分后的数据结构
四、建立分布式缓存
五、主、从服务器
六、统一数据访问模块
七、Nosql 数据库
八、异步通信
九、总结
六、统一数据访问模块
可是对于应用程序来说,其实并不希望把数据搞得很割裂,它更希望有一种统一的访问接口,去 GET 一个数据,不管数据在数据库里,还是在文件系统里或者在缓存里,就帮助应用程序拿出来即可。所以这时候就需要设计统一数据访问模块,它在平地底下存储差异。之前 user 分了两部分数据,一部分包括它的用户名、密码、性别等等信息,是把它存到了 mysql 里面,然后当时有一些 ican 图像类的内容,是把它放到了 mongDB 里面。但是 user 在访问的时候,会有 userDAO 在专门负责组装 user,然后 userdao 的上面就是 controller。对于 controller 是不知道 user 是存在两方面的,它只是在调用 userdao 里面的内容,比如 getuser 方法去打包。
USERDAO 实际上既访问了数据库又访问了 mongdb,然后组装出一个完整的 user 给了 controller,所以 userdao就是统一数据访问模块,当时小的系统里面都这样设计很显然在大的系统里面也要进行这样的设计。上层的程序仍然是比如调用一个 getuser,它就能得到一个组装好的 user,而 user 一部分的数据在关系型数据库里面,另一部分在分布式文件系统里比如 ican。还可能数据加载之后一次之后就把它放到了分布式缓存里面,每一次都是先到分布式缓存里面去看是否存在,不在就再到硬盘里面去寻找,一旦找到就把它放到缓存里,那整个复杂的访问逻辑全部被统计数据访问模块屏蔽掉,上层不用再去关注细节。这样既实现了数据优化存储,又实现了数据的访问的封装,这样上层的应用才比较容易去访问各种各样的数据。
再往下就会发现其实有很多数据它不太适合放到关系型数据库里面,于是可能会去采用 nosql 数据库去进行存储,比如一些日志数据的结构化并不是很好,再比如之前提到过书评或者书的简介,它不是一种结构化数据而是大段的纯文本。这种数据可能给放到 Nosql 数据库里面会更好。
七、Nosql 数据库
此时可能会有一个疑问,为什么不放到分布式文件系统里面?因为文件系统它只是存文件,它有文件分区表允许用户去读写文件,但是它没有更复杂的操作。比如当一个纯文本放到了 nosql 里面,数据库不太支持搜索,它的搜索可以做的比较复杂,比如说可以去搜它具备不具备哪个键,或者说它某一个键对应的值是什么,这些内容在文件系统里面就是不可能提供了,所以当对这一类的数据有这种搜索要求的时候,就可以把它放到 nosql 数据库里面。
不把所有的数据都放到 nosql 数据库里面的原因是没有必要,比如一个很大的视频文件,为什么要放到nosql数据库里,直接把它存成文件就可以了。因为对于视频来说它只是播放,可以对视频生成视频的描述文件,比如说是谁演的什么视频、什么类型的电影等等。把这份数据可以放到关系型数据库或者 nosql 数据库里,然后在存储的时候同时有一个链接会链接到文件即可,所以这是一方面会有 nosql 数据库的介入。
另外一方面需要搜索引擎,搜索引擎通常是指的要做一个全文搜索,比如说现在已经有很多的东西在 nosql的数据库、SQL 数据库、文件系统里。现在突然有个请求过来以后是想做这样一件事情,能否找出凡是在存储的数据里面带有“肺炎”两个字的内容,因为现在新冠肺炎比较流行,这是肯定现在是个热搜词,比如是为了拿来做研究,想知道治疗肺炎有哪些方法。于是会想一个问题,以关系型数据库为例,假设关系型数据库里有一个表叫做病历,那么肺炎可能会出现在哪里?可能出现在病的名字上,也有可能出现在开的药上,也有可能会出现医生的诊断上,也就是说在多个字段里面都可能有。第二个它可能存在 nosql 数据库里面,它在某一个 key 上面会出现,也有可能在某一个value上面会出现,甚至有可能出现在某一个文件里很长的文本。这是想要搜索就需要关系型数据库要对每一个字段都去搜,sql写起来就会非常麻烦,对于 key 和 value 也是一样,可能要做一种类似于扫描的动作。所以用一些像搜索引擎的工具来做优化,比如说它可以建立一种反向索引,它把所有的文件拿过来之后,根据它们里面的内容去建立一个反向索引。反向索引的含义后面会提到,总的来说就是会优化搜索的过程,因为存储的方式发生了很大的变化,所以它会去优化搜索的过程。在大量的异构的数据源里面以快速的方式去搜索出来,所以需要一个搜索引擎。
八、异步通信
当系统大到一定程度之后难免当大量的用户请求过来的时候可能来不及处理,比如说有很多的服务器,但是当双11到来的时候,可能还是不够用。那可能会想先把所有的订单全收掉,然后会告诉用户订单已接收,处理结果会后续通知等等。当前端来了请求要求下订单,就把订单写入到数据库,写入成功之后返回一个结果给客户端,这是一个正常情况。但是如果这样的话,比如说现在大量的请求过来去写入数据库,它是需要加锁的,也就是说现在系统当中可能会频繁的出现加锁这样的操作,就会导致大量的数据在这里写的时候,一旦加锁都是串行的,不会有并行,无论多少服务器也是无法进行创建的。如果出现大量的 session 出现了 timeout 就会给用户体验非常的差,就会提示超时稍后再试。正常的情况可以想象一下,屏蔽是处于数据库一端加锁,如果没有加锁动作就会好很多。
于是应该当数据来了之后,不要马上放到数据库里面去写,因为数据库会加锁写。应该把它存到某一种东西里面,不写数据库,在存的时候只是把来的请求原封不动的写进去,将其保留下来。然后比如现在是零点大家在抢商品,抢了过了10分钟之后压力明显下降,现在的应用服务器可以来处理更多的请求,数据库服务器的压力也不会那么大的时候,再把服务器里面的东西取出来,逐个处理写入到数据库里,这就是所谓的异步通信。
举个例子同步通信是想要打电话,数据库接收用户的请求,打电话来进行通信,由于打电话只能同时只能跟一个人说,所以其他用户会进行排队。但还有一种方法可以来处理问题,比如说大家通过电话来交作业,拨通电话以后告诉几个题的答案是什么,跟完给出分数之后下一个人继续打进来继续做,但是这样的话大家等待时间非常长。还有一种方法是门口放置一个信箱,作业内容写好放到信箱里,等有空了慢慢看,比如到了晚上有空一份一份拿过来看,但是这时候是早上10点的时候把作业放进信箱,然而晚上8点的时候才有空去看,很显然处理的时间和提交给的时间不在同一个时间点,这就是所谓的异步。
用异步通信的方式要解决的问题是压力非常大的时候,怎么把请求全部接收下来后面慢慢去处理。如果打电话现在没有人排队,那直接给通就可以,所以现在要考虑到这种有可能处理不过来的情况,所以用异步通信的方式来处理,异步通信就要用到消息、队列的机制。所以要有消息队列,所以支持同步的处理,当请求来了之后直接写入数据库。也支持异步的处理,请求来了以后在消息队列里面缓存,等不忙的时候把它处理掉,这样的话就是即便大量的用户突然间在同一时刻发起请求以后也可以进行应对。只不过不是马上告诉用户处理的结果,是告诉用户系统已经接受请稍等片刻。有了消息队列用术语来说就是在系统当中,现在同步的处理,异步的处理之后就可以应对负载有剧烈变化的场景。
其实这种消息队列分布式的缓存、分布式文件系统、分布式数据库、反向代理、内容分发网络以及负载均衡器、搜索引擎和 nosql 数据库。它们都和应用程序的业务逻辑是无关的,换另外一个应用,比如说 B 应用也要用到这些内容,那所以这些东西就被剥离出来做成单独的中间线或者是单独的模块。于是看到有 redis 或者是 memory cash 的分布式的缓存以及有 dfs 就是 hdfs 的分布式的文件系统以及有 Hbase 的分布式数据库,搜索引擎比如 solr、lurence。负载均衡器比如 linux。,息队列有 activemq 还有销售策略。后面都会一个一个专门去探讨,其实多了一个业务逻辑之后,这些东西都是通用的,任何一个应用可能都会用到,所以这些东西被剥离出来,作为专门的产品或者是框架出现。
现在再来看外围应用,需要用到上面提到的内容把应用支撑起来,而这些内容和应用的业务逻辑没有任何关系,它只是体现在用户体验上,比如速度快、可靠、安全。而为了响应更多的用户请求还要做集群,到了这层程度才是一个真正的企业级的应用系统应该有的体系架构。
回想一下刚才看到第一张图,所有的应用程序文件是全部放到一台机器上面,而到最后一张图已经发生了天翻地覆的变化。实际上就是要告诉大家在这样一个架构之下,每一块都应该怎么去把它用好,以及本身的应用程序又有一些什么需要注意的地方,这就是本次内容的核心。
九、总结
其实刚才说的一些内容全部都是因为数量发生了变化,数量包括两方面,一方面是后台的数据的数量,一方面是因为前台的并发的用户数的数量也就是 request 的数量。它们俩发生了很大的变化,量变达到质变就导致原来的在一台机上跑所有东西的这种方式是不适应于企业级应用。企业级应用最主要就这两个东西。这两个东西再往深处去引申一下,数据是要做持久化的,也就是数据在脱离的应用之后它还存在,当把 tomcat 关掉,数据还存在,指的是 sql 数据库里面的内容。
请求就是在内存里面的状态,要有分布式的缓存,应用程序的构建怎么样尽量节省使用内存,这就是要讨论的问题。其实整个在企业级应用里面,最终实际上是量变导致质变,质变体现的是持久化的状态和瞬时的状态的管理发生了很大的变化,这两个变化导致需要有一圈些服务器和软件架构来做支撑。
否则就没有办法去应对企业级应用它的两个变化。后面的内容一部分是集中在持久化数据处理,一部分是在内存数据瞬时状态的处理,所以这就是架构的演化。在这里面它们内存里的状态和区域化状态管理是不一样的,以内存状态为入口先来讲,接下来还有一个问题就是所谓的有状态和无状态的服务各自的含义分别是什么。