一、Java服务端架构演进
我们知道,Java服务端开发不是一开始就是微服务的。多数情况下,一开始大家都是写的单体,先把基本的功能做出来。而后随着用户量的提升,发现原先的单体架构难以应对,就逐渐拆分。
1.1 单体架构
最早的单体是把应用服务器与数据库服务器放在一起,适用于1千以下日活的产品,也就是1万左右用户。而后的版本把应用服务与数据库服务分开,这种架构,大概可以应对5千日活。
其实大部分国企的管理小项目,其实都可以用这种架构。毕竟,使用系统的可能只有个几百人。
该架构的有点是,易于集成、开发和部署。
1.2 集群架构
从1.1的右边的架构可以天然的想到,通常数据库服务的承载能力是大于应用服务的,那么我们把应用服务做水平扩展,多个应用服务器对应一个数据库,从而进一步提升服务器的处理能力。再加上缓存服务器,把一些常用的结果缓存在热数据中,进一步提升查询的速度。当然,这也避免了应用程序的单点故障。
小编认为,在开发新项目时,可以默认先使用1.2右边的架构。而应用服务根据行为类型划分成微服务(类似1.4),方便未来的水平扩展。
1.3 读写分离架构
我们发现,1.2的主要问题是,数据库不能水平拓展。那么,我们增加一个水平拓展即可。
通常的数据库水平拓展思路是做读写分离的主从设计。主数据库负责写入,写入后把数据自动复制到从数据库中,而从数据库则负责读取。
1.4 服务化-分库分表架构
我们之前的架构都是单体架构,服务端所有功能写道一个应用下(当然,可以分多个模块)。所谓服务的水平拓展,是服务的全量拷贝。但实际上,同一服务的不同接口的访问量可能是数量级的差异。把不同数量级的接口放在一个应用下,或造成资源争抢;在做水平拓展时也无法做到有的放矢。拿传统的电商服务来说,商家上架商品其实是个低频操作,但用户查询商品却是高频操作。如果把这两种接口放在一个服务中,就会导致特定高流量时段,商家上架商品变得卡卡的。
在数据库中,单表数据量超过百万后,会显著降低查询效率。这时通常我们会采取分库分表来解决。
这基本上是互联网项目的通用架构。
二、服务端架构的取舍
本攻略面向初学者,以讲解知识点为主,故采用1.4的架构。但为了方便开发讲解,一开始仅仅做微服务。而后逐步去做分库分表。
当然在现实开发中,我们应当首先分析需求,预估我的的系统用户大概在什么数量级,峰值的并发量大致在什么数量级,管理和查找的数据大致需要支持到什么数量级,再去决定用什么架构。毕竟开发项目的最终目标是为了赚钱,并且做什么事情也都是有风险的。所以我们在满足基本性能需求的前提下,尽可能的去选用简单的架构,先把功能做出来。而不是先去考虑项目多年后的事情。
一种无脑的方法论是,数据以用户为主的管理系统,无脑采用1.1的架构。面向资源的管理系统,无脑采用1.2架构;遇到性能瓶颈后升级到1.3架构。面向C端的互联网项目,第一版采用1.3架构,但做的时候考虑向1.4的升级。
三、微服务架构的常见需求与解决方案
3.1 服务的负载均衡
其实负载均衡,没有太多好说的。nginx的负载均衡和springcloud-gateway+nacos,正常接入都自带负载均衡功能。
一般说来,默认的负载均衡采用轮询,但也可以通过配置来修改。
具体介绍见后面的文章
3.2 服务间的通信
常见的服务间同步通信策略有openfeign和Dubbo。openfeign是一种短连接的实现,Dubbo是一种长连接的实现。
如果想要异步通信,可以使用异步调用,也可以使用消息队列。
如果需要通信的服务都是自己公司(或团队)的内部服务,可以沟通使他们配合接入的话,无疑使用消息队列是更优的。
但如果需要通信的服务是别人的(或别团队),不太好干预他们的行为,则更推荐使用异步调用。
对于消息队列,如果项目比较小,可以直接使用redis。如果项目较大,可以使用kafka或rocketMQ等。
异步调用推荐使用webclient。
具体介绍见后面的文章
3.3 分布式锁
可以使用redison,自己开发一个AOP注解。
具体介绍见后面的文章
3.4 分布式事务
可以接入阿里的Seata
具体介绍见后面的文章
3.5 读写分离的数据库配置与mybatis-plus接入
在mybatis-plus中可以使用DS注解做多数据源配置
具体介绍见后面的文章
3.6 mysql的分库分表
具体介绍见后面的文章
3.7 redis的读写分离与哨兵模式
具体介绍见后面的文章
四、设计一个适合微服务架构的需求
我打算构思一个电商项目,以方便我们讲解这一部分内容。
4.1 简单画个架构图
4.2 大致想下做的功能
4.3 用户相关
4.3.1 用户管理
用户打算做3种角色,普通用户,商家,超级管理员。
普通用户和商家的注册分别做,商家的注册需要超级管理员通过才能生效。
用户可以管理收获地址,修改用户信息。
超级管理员可以重置用户密码,可以禁用用户。
4.3.2 登陆服务
登陆,获得JWT。由于该服务可能有较大的访问量。故把该功能与用户管理分离开来
4.4 商品相关
商品管理分2个服务,1个是面向商家的商品管理,1个是面向普通用户的商品查找服务。
商家可以创建修改商品,上架商品、修改库存。也可以查看自家商店的商品。
普通用户则需要根据商品类型、关键字等做商品查找。
4.5 订单相关
4.5.1 购物车
用户可以添加商品进入购物车,并选择优惠券。
4.5.2 下单与支付
用户选择购物车中商品并选择优惠券,创建订单。
向支付服务发送支付信息,成功后把订单改为完成(由于本篇是攻略,就不那么讲究了)。
4.5.3 订单查询
支持订单按时间查询
4.6 优惠券
4.6.1 优惠券的发放
优惠券的发放模式有以下几种:
运营平台方面,会定期向所有用户发放优惠券。
商家方面,用户可以在商家特定页面领取优惠券,领取优惠券数量有限制,可能是优惠券有个总量,每人限领1张;也可能没有总量限制,每个用户都可以在活动期间领一张。
4.6.1 优惠券的类型
我们做2种,满减和买够多少件打个折扣。
4.7 支付模拟
为使项目完整,做个简单的充值扣费系统,就不接入付费API了。