116

[原创]JAVA业务系统之架构升级-上篇 - 知乎专栏

 6 years ago
source link: https://zhuanlan.zhihu.com/p/24577197?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

[原创]JAVA业务系统之架构升级-上篇

专注区块链,供应链,企业数字化转型

摘要

基于JAVA不断的技术演进和丰富的社区支持,在很多业务领域,使用JAVA构建业务系统目前仍为主流。对于我比较熟悉的金融支付系统,在过去几年中,尽管主体开发语言没变,仍旧以JAVA为主进行构建,但其体系架构正在随着新技术的涌现不断更新换代。本文以我比较熟悉的支付交易系统为案例(不限于支付交易系统,所有基于JAVA构建的业务系统都可以参考借鉴),在传统以JAVA构建的支付系统中,已经存在诸多问题或瓶颈,本文重点阐述新的技术架构,尤其是微服务相关架构的实际应用和体会。

说点题外话,在技术方案上我一直崇尚的是“技术即产品”,或者也可以理解成:只有象产品一样能解决问题的技术才是好技术。(在有一段时间,有不少小伙伴为解决简单问题而使用了不实用技术即被我challenge,哈哈)其实,不光只有我是这么认为的,比如李开复老师,他也曾说过,只做有用的创新,道理是一样啦。

在这篇文章里,重点不是讨论如何设计某个系统,所以我不准备画任何系统架构图,况且每个产品、每个团队、甚至产品的不同阶段,需要的架构都是不同的。在这一篇我给出一些主流的技术的理念、方法和我们使用的体验,也许在下一篇中,可以根据实际案例再谈怎么去架构或如何为现在的技术做升级。

微服务架构观

上次跟一个朋友聊到某个银行的业务系统,也是JAVA开发的,所有的业务逻辑写在一个巨大无比的WAR包里,跑在巨重无比的WebLogic下,每次启动需要十分钟以上,不要说快速迭代了,就连每次系统的小变更对开发或运维来说都惶恐无比,因为一旦很小的变动都需要变整个WAR包,且每次变动又需要花费很久时间。

所以,对于很多老的系统架构来说,其实已经到了非拆不可的程度了。使用微服务架构观是解决这一问题的最好思路。在此我需要强调一个观点:我并不是说一定要使用微服务各种工具,而是理解微服务架构观来帮助我们解决实际问题,微服务的一系列工具就看你怎么灵活使用了。

在谈微服务之前,我们不得不先谈到SOA服务,如果一句话来谈SOA和微服务的区别,即微服务不再强调传统SOA架构里面比较重的ESB企业服务总线,同时SOA的思想进入到单个业务系统内部实现真正的组件化。

微服务其思路很简单,就是避免开发一个巨大的单体式的应用,而是将应用分解为小的、互相连接的微服务。这样做的好处很明显,除了能避免以上这个问题以外,还有很多好处:其一、实现部署分离,负载大的应用部署在配置更好的机器,启动更多的实例;其二、每个微服务独立部署,升级和迭代不影响整个系统,所以加快迭代变得可能;其三、每个服务或技术相近的服务有专门团队开发,这点对于技术管理者和开发者来讲也非常不错,比如在金融业务系统中,有些是重业务的开发团队(比如风控系统服务),有些是技术更重的团队(比如安全加密服务),所以这对团队完全是不同的要求,所以放在不同的团队非常合理。除此以外,对于一个注重安全的管理者其实还有一个额外的好处,就是便于代码管控,一个人不会拿到所有代码,除非你的团队就一个人,呵呵。

所以,优化老架构的第一步,我觉得是:拆。

微服务拆分原则

拆分原则,几个点比较关键:

1、单一职责

一个微服务专注做一件事情,这个很好理解,如果一个服务做很多事就不叫微服务了。

2、不同技术领域或业务领域需要拆分

比如,在我们给用户的服务中,包括支付服务,也包括咨询服务业务,两块根本是不同业务领域,技术实现也不一样,果断拆分。

3、拆分粒度

并不是越细越好,没有统一标准,我的经验是:

如果复用性强的服务,比如我们有一些获取市场行情的数据处理模块、支付账务处理模块,这些果断拆出来;

有些业务涉及到事务一致性保证的(涉及多张数据库表记录,通过数据库实现一致性保证),如果拆分出来,一致性保证需要在服务层面实现,又是一个课题。我建议团队资源有限,就先不要拆,如果资源OK,则一劳永逸解决。

微服务的无状态化

本来我准备先谈微服务框架的选择,考虑到我们使用微服务的一个重要目标是平行扩展,所以首先需要让服务无状态化,就是说,服务不要和用户session挂钩。这是一个前提条件。其实不光是微服务,就算是想做到负载均衡Load Balance,也一样需要实现这个前提条件。

传统的JAVA构建的业务系统往往把用户信息和状态存放在服务器内存的Session对象中,当我们使用多节点分布式架构时,Login服务和业务服务可能分散在不同节点实例,这就导致业务不可用(Session找不到用户信息)。

我建议的方案是,采用独立的Sesssion缓存,该方案有两个点需要考虑,一个是存储介质,一个是实现机制。

存储介质目前最成熟和最广泛接受的就是Redis,性能很高,支持持久化,支持集群部署,针对Redis我们还有独立章节阐述。

实现机制上,我觉得有两个方案供选择,方案一是直接使用SpringSession,SpringSession功能很多并但不一定都用的上,而且对开源的产品本来就有一个学习成本,所以还有一个方案就是参考SpringSession的理念自己实现了。具体实现机制为,使用SessionFilter进行用户请求拦截,然后通过Request包装类接管应用服务器的Session管理。在Request包装类中重写getSession方法。让用户在进行Session读写的时候去Redis中进行操作,而且使用Session的方法与过去一样,使得管理方案对用户透明。

以上独立的Sesssion缓存方案就说完了,值得再提一句的是,在系统架构初期,一定要把认证服务、Sesssion缓存服务这样的基础服务和业务服务实例独立出来,这点非常重要,避免做的越多,改的越多。

微服务框架选择

当我们完成了服务的拆分,形成了一个个微小服务的时候,我们自然需要服务注册管理、服务发现、异常机制、服务监控等配套框架,此时需要选择一个靠谱的微服务框架了,目前有两个主流框架选择:Spring Cloud或者Dubbo。

Dubbo,是阿里巴巴服务化治理的核心框架,并被广泛应用于阿里巴巴集团的各成员站点,在国内也非常火。Spring Cloud,是 Spring Source 的产物,Spring 社区的强大背书可以说是 Java 企业界最有影响力的组织,除了 Spring Source 之外,还有 Pivotal 和 Netfix 是其强大的后盾与技术输出。其中 Netflix 开源的整套微服务架构套件是 Spring Cloud 的核心。具体可参考下面这张图:

有关这两个框架更详细的的对比可以看这篇文章:微服务架构的基础框架选择:Spring Cloud还是Dubbo?

在这里需要说明一下Spring Boot,该开源产品是由Pivotal团队提供,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。使用Spring Boot是整个团队都不会后悔的决定,开发迅速、打包和发布及其方便(打包成一个jar便可),所以能帮助团队快速开发一套restful风格的web应用程序。而且对于之前使用Spring框架的团队来说,移植也不算大动干戈。

对我们来说,我们准备选择的是Spring Cloud。原因很简单,因为我们使用了SpringBoot作为主开发框架,SpringBoot和Spring Cloud天然整合良好,SpringBoot项目很容易就能成为SpringCloud的注册服务。

对于大部分开发者来说,不论使用Spring Cloud或者Dubbo,都需要花费时间和学习成本,此时你们要考虑的是你的业务到底有多复杂,或者微服务划分的到底有多细,当然对于很多情况,其实完全可以考虑以下替代方案。

API Gateway + Load Balance方案

一个简单的服务发现的解决方案就是使用 LoadBalancer 。你可以使用NGINX或者使用硬件LB设备,当然如果使用阿里云等云计算服务,使用LB将会是成本最低的选择。当然,缺点也一定会有,因为不是分布式处理模式,会产生性能上的瓶颈或单点故障,同时无法作为精细粒度控制(比如权限管控等),但不管怎样,这是一个不错的阶段性方案,我们很长一段时间也是这么使用的。

对外提供服务的方式不得不提的就是API Gateway。API Gateway作为系统的入口,具有服务转发、授权验证、负载均衡等作用,可以快速对外封装一系列HTTP Rest风格 API。阿里云、AWS等云服务商已经提供了完整的API Gateway服务产品,也可以使用Spring Integration Gateway来构建自己的gateway。

一般来讲,API的调用方来自于自有应用或第三方应用,渠道可能是PC网站、移动客户端等。使用API Gateway是开放业务服务的首选。

总之,如果API Gateway可以作为简单的微服务框架的实现产品,配合负载均衡,完全可以构建一个不错的微服务架构。

高性能的RPC方案

微服务架构确定后,则需要考虑的是内部服务之间的高效的RPC框架,它是架构微服务化的基础组件,它能大大降低架构微服务化的成本,提高调用方与服务提供方的调用效率,屏蔽跨进程调用函数(服务)的各类复杂细节。

RPC框架在逻辑上分为二层,一是传输层,负责网络通信;二是协议层,将数据按照一定协议格式打包和解包。

以下是有几个朋友用过或推荐的跨语言RPC框架,大家做个了解。

thrift是一个facebook开源的高效RPC框架,其主要特点是跨语言及二进制高效传输(当然,除了二进制,也支持json等常用序列化机制),官网地址:Apache Thrift - Home

Hessian是一款基于HTTP协议的RPC框架,采用的是二进制RPC协议,非常轻量级 ,且速度较快。其通讯效率高于WebService和Java自带的序列化

Avro Welcome to Apache Avro! 大名鼎鼎的Hadoop的子项目。它本身即是一个序列化框架,同时也实现RPC的功能。Avro序列化特点:支持跨语言实现,与 Apache Thrift 和Google的Protocol Buffers相比,Avro的优势在于支持动态模式,即可以不生成代码,避免了侵入性,作为POJO的DTO(数据传输对象)是不适合用代码生成的。还有Avro序列化时由于不需要字段标识符来打标签,所以使用它序列化生成的数据小(应该是现有序列化系统中最精简的了),最后它的性能也非常优秀。

除此以外,国内的nfs-rpc 淘宝牛人开源的一个RPC框架,Dubbo 为 阿里开源的一个分布式服务框架,也提供高性能和透明化的RPC远程服务调用方案。大家可以从网上找更多资料了解。

另外介绍一下 Protocol Buffers:谷歌创建的一种基于二进制连接格式的接口描述语言。在解析和网络传输方面Protocol buffers非常高效,并经历了谷歌高负荷环境的考验。

从序列化方式来看,Apache Thrift 、Google的Protocol Buffers和Avro应该是属于同一个级别的框架,都能跨语言,性能优秀,数据精简,但是Avro的动态模式(不用生成代码,而且性能很好)这个特点让人非常喜欢,比较适合RPC的数据交换。

上篇先写这么多吧,后面还有一些话题,通过消息队列构建异步的系统环境、通过Redis实现性能优化、持续集成方案、混合云带来的好处,以及一些实际案例带给大家,供探讨,谢谢!

作者:肖旻

简介:金融/支付IT,持续关注支付/跨境支付/创新金融科技-区块链,曾在银联数据、国内大型支付机构、专注外汇的初创金融科技公司工作。

微信:wx1489968049

知乎:肖旻FINTECH


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK