内容整理自网络:
下面说下B2C电商系统架构,B2C电商系统功能列表如下图所示。
传统项目的架构图如下所示,这种架构在并发量小的情况下是没有什么问题的,但是当并发量大的时候,这种架构瞬间就会崩溃。
先来说下当并发达到1000时的场景,我们知道,对于一个tomcat来讲,理论上能处理500的并发量,但实际它能应付的并发量有个三四百就不错了,那么当有1000人同时访问系统时,怎么解决问题呢?答案是加tomcat数量(搭建tomcat集群)并使用nginx反向代理来做负载均衡处理,如下图所示,一个tomcat处理400并发,3个tomcat便可以处理1000的并发。需要注意的是sessioin共享的问题,原理是tomcat之间每隔一段时间便会广播自己的session信息,别的tomcat看到自己有些信息跟人家不一致就向人家同步,同理该tomcat也会跟别的tomcat进行同步数据,从而达到数据一致的目的。
那么当并发量达到10000时怎么办呢?理论上说,可以部署25个tomcat来解决并发问题,但是实际上这时tomcat的集群处理并发的能力便很低了,原因是什么呢?上面我们说了,不同的tomcat之间要保持数据同步,配置了session复制,会定时广播session,而且每个tomcat都既是广播者又是接收者,当tomcat较多时,网络带宽都被用来进行广播了,留给集群来处理并发的带宽就很少了,效率很低下,由此可以看到,我们不能通过增加tomcat数量来解决高并发的问题。
上面既然说了通过增加tomcat数量来解决高并发不可行,那么应该怎么解决呢?要解决这个问题,需要按照功能点把系统拆分,拆分成独立的功能。单独为某一个节点添加服务器。需要系统之间配合才能完成整个业务逻辑,这就叫做分布式。其中很核心的一点就是,这种架构把所有的session都放到单点登录系统中了,这样就解决了单纯增加tomcat数量而引起的session广播风暴的问题,我们把一个完整的系统拆分成多个模块这样做的原因是,高并发处理可能仅仅涉及一小块,比如下图的前台系统,其它模块的并发量就小很多了,复制整个tomcat的做法显然浪费了很多资源,我们把项目模块化,这样我们便可以集中处理高并发的模块(采用集群来处理,由于这时已经没有广播风暴的问题了,因此理论上讲,可以处理非常高的并发量),那些并发量低的模块可能一个tomcat便可以搞定,哪个模块并发量高了便可以配置集群来解决。项目的运行需要各个模块协调合作。
概念:
分布式架构:多个子系统相互协作才能完成业务流程。系统之间需要通信。
集群: 同一个工程部署到多台服务器上。
分布式架构的优点:
1.把模块拆分,使用接口通信,降低模块之间的耦合度。
2.把项目拆分成若干个子项目,不同的团队负责不同的子项目。
3.增加功能时只需要再增加一个子项目,调用其它系统的接口就可以。
4.可以灵活的进行分布式部署。
有优点就有缺点,缺点如下:
1.系统之间交互需要使用远程通信,接口开发增加工作量。
2.各个模块有一些通用的业务逻辑无法共用。
为了解决上面分布式架构的缺点,我们引入了soa架构,SOA:Service Oriented Architecture面向服务的架构。也就是把工程拆分成服务层、表现层两个工程。服务层中包含业务逻辑,只需要对外提供服务即可。表现层只需要处理和页面的交互,业务逻辑都是调用服务层的服务来实现。SOA架构如下图所示,我们把接口和业务逻辑做成一个个的服务。比如订单系统需要查询商品服务,前台系统也需要查询商品服务,由于我们把商品服务独立出来了,做到了代码复用,它们调用即可。表现层只是用来展示数据而已。
我们商城的技术架构如下图所示,可以看到表现层与服务层之间加了一个服务中间件Dubbo,这样做的目的是加快表现层与服务层之间的交互速度,服务层与数据库之间加redis,可以大大提高重复性查询的效率,持久层是一个mysql集群,由MyCat数据库中间件来管理,MyCat相当于这么多mysql数据库的一个抽象,我们操作数据库直接面向的将是MyCat而不是具体的某个mysql,是由MyCat来替我们完成相关操作的。Solr服务是专门用来处理查询的,主要是通过建立索引库来实现的。消息队列则是专门处理各个模块之间的消息的。
搭好架子后,
用tomcat插件来启动web工程
为何用插件方式?因为在互联网项目中,动辄十几个甚至好几十个web工程,如果按照传统的添加tomcat服务器的方式来启动为了避免端口冲突,每增加一个web工程都要修改三个端口,非常麻烦。而tomcat插件启动则只需改一个端口即可,显然简单了很多。
用tomcat插件启动聚合工程。
我们的工程是个聚合工程,它下面有xxx-manager-dao、xxx-manager-pojo、xxx-manager-interface、xxx-manager-service等多个子工程。其中service是个web工程,其它都是jar工程。
既然service是个web工程,那么为什么我们不用它来启动呢?因为service与其它子工程是平级关系,而且它依赖于这些子工程,如果子工程变动,那么需要先把它们打包到本地maven仓库才能正常启动ervice,这样做比较麻烦。
为什么我们选择启动聚合工程?这是因为它本身是父工程,它知道它下面有哪几个模块,而且它可以将所有模块打包成war包运行。我们不用打包子模块,这样省事很多。