专栏名称: 京东成都研究院
京东商城成都研究院信息平台
目录
相关文章推荐
成都本地宝  ·  2025成都消费券最新领取时间+入口! ·  昨天  
清廉蓉城  ·  十四届市委第五轮巡察完成首批进驻 ·  2 天前  
成都本地宝  ·  成都新生儿怎么线上申领社保卡? ·  4 天前  
51好读  ›  专栏  ›  京东成都研究院

CDRD TALK | JSHOP海外版组件化之路

京东成都研究院  · 公众号  · 成都  · 2018-03-05 17:00

正文

01

什么是组件化

“组件化”现在没有一个官方的定义,在京东去年提出的“积木战略”里,可以把“组件”理解成一个一个的积木, 通过灵活使用多个“组件”就可以组合成一个新的产品。


根据这个描述我们可以简单理解什么是组件:对一个特定的业务场景的封装,可以被其他系统直接使用或者作为整套系统的一部分。 所谓“组件化”就是以面向组件的开发方式进行架构设计。

其实大部分公司,在日积月累的研发过程中,已经形成了自己的“组件池”,比如我们京东:

从上可以看到这些组件其实在我们现有系统中已经存在,只是有些子系统还不是足够的灵活,还不能直接像堆积木一样直接堆积出另一个京东商城,这时就需要进行组件化改造。


02

如何做服务化拆分

实现“组件化”的第一步:服务化(或者微服务化)。


公司要求所有前端应用不能直连数据库的用意:1、 安全 ; 2、强制进行服务化拆分,为组件化提供必要的前提。

所以第一步就是把所有直连数据库的部分独立部署为单独的jsf服务:

拆分前:

  1. 多个应用直连同一个数据库,默认会占用更多连接数。

  2. 每个应用都需要开发相同的DAO,新增表每个应用都新增相应的DAO层代码。

  3. 如需对外提供jsf接口,每次都需要做相应的开发。

  4. 安全问题等。

拆分后:

  1. 只有一个单独的db-jsf工程直连数据库,默认连接数为数据库连接池的初始值。

  2. 只需要做一次开发,其他多个应用通过jsf接口调用,复用性高。

  3. 很方便的对外提供jsf接口,无需再次开发。可以独立形成一个“组件”。

  4. 安全方面:可以使用jsf框架自带的权限控制,也可以在jsf filter中自定义权限控制。

随着业务发展,单数据库可能无法承受更大的业务量,此时可以对db-jsf工程再进行“垂直拆分”(或者称谓微服务化改造):

“垂直拆分”的要点就是:尽量根据不同的业务来拆分,再说得直白点就是最终拆分出的两个数据库之间尽量没有关联,否则就会出现“分布式事务”问题。

有“垂直拆分”就有“水平拆分”, 水平拆分其实就是把同一张表拆分为多张表,为了缓解单数据库的压力,这些表有可能会分配到不同的数据库,此时同样会有“分布式事务”问题。此时可以可以考虑使用一些mysql中间件进行支撑,但我们也可以采用一些nosql数据库来解决,这里就不展开了。

如果在整个公司层面,按照上述流程进行服务化拆分,就会在“中台系统”中形成一系列的“微服务化”组件。再结合“前台系统”中的业务组件、前端组件,就可以形成整个公司级的“组件池”:

为了方面组件更好的被发现和使用,公司后续应该会开发一些组件管理工具来管理 “组件池”,类似手机上的app市场一样。


03

服务化拆分技巧

1

技巧一:jsf filter的使用

现在主流的RPC框架都提供了自定义filter功能来实现对框架的扩展,jsf框架也不例外。


灵活使用jsf filter,往往都可以到达事半功倍的效果。比如:使用jsf filter,我们可以很容易的做到:统一监控埋点处理、统一日志打印、统一异常处理、限流、熔断、安全等等。

实现起来也很简单,就是在真正进入jsf业务接口之前,自定义一系列的jsf filter,这里其实就是一个“责任链模式”:

这里以如何实现限流为列,展示如果自定义jsf filter:

简单的理解就是使用AtomicInteger 做一个全局的并发计数器,在执行下一个filter或具体的业务方法之前(没有下一个filter,就执行真实的业务方法),对并发计数器+1 在返回之前对并发计数器-1。代码前半部分是对并发计数器进行判断,如果当前的并发数已经超过一个阀值(这里是100),就进行限流,直接返回 从而到达降低服务器压力的目的。

这里的阀值可以通过压力测试拿到,并且最好不要超过mysql数据库连接池的上限。

只要实现了自己的第一个filter,要实现诸如“熔断”、“监控埋点”、“权限控制”等filter是件非常容易的时,并且你会发现它就像spring aop一样能帮助我们做很多事。


2

技巧二:多个应用之间的redis隔离

服务化拆分后,每个子系统都有自己的redis实例,涉及到读另一个系统的缓存时,是直连另一个redis?还是通过jsf接口获取?

全部走jsf接口方式:

  • 优点:这种方法系统边界划分清晰

  • 缺点:如果数据已在redis1中,此时会多一次jsf调用的网络开销

直连多个redis:先查redis中是否存在,如果不存在再走jsf调用:

  • 优点:性能较前一种好些

  • 缺点:存在一个系统直连其他系统的redis实例,使用时容易混淆

这两种方式可以根据具体的业务情况进行选择,如果数据隔离更重要就选择第一种,如果性能更重要就选择第二种。

这里我们选择的第二种,同时使用一些隔离手动来防止一个应用连接多个redis实例出现的混乱:







请到「今天看啥」查看全文