标签:选择 java 上线 项目 性能 sch 新特性 使用 直接
什么是微服务?什么时候适合微服务改造?微服务架构到底是什么样的?
wiki定义介绍:微服务的概念最早是在 2014 年由 Martin Fowler 和 James Lewis 共同提出,他们定义了微服务是由单一应用程序构成的小服务,拥有自己的进程与轻量化处理,服务依业务功能设计,以全自动的方式部署,与其他服务使用 HTTP API 通讯。同时,服务会使用最小规模的集中管理 (例如 Docker)技术,服务可以用不同的编程语言与数据库等。
单体应用
? 早些年,各大互联网公司的应用技术栈大致可分为 LAMP(Linux + Apache + MySQL + PHP)和 MVC(Spring +
iBatis/Hibernate + Tomcat)两大流派。无论是 LAMP 还是 MVC,都是为单体应用架构设计的,其优点是学习成本低,开发上手快,测试、部署、运维也比较方便,甚至一个人就可以完成一个网站的开发与部署。
? 以 MVC 架构为例,业务通常是通过部署一个 WAR 包到 Tomcat 中,然后启动 Tomcat,监听某个端口即可对外提供服务。早期在业务规模不大、开发团队人员规模较小的时候,采用单体应用架构,团队的开发和运维成本都可控。然而随着业务规模的不断扩大,团队开发人员的不断扩张,单体应用架构就会开始出现问题。
? 部署效率低下。以我实际参与的项目为例,当单体应用的代码越来越多,依赖的资源越来越多时,应用编译打包、部署测试一次,甚至需要 10 分钟以上。
? 团队协作开发成本高。以我的经验,早期在团队开发人员只有两三个人的时候,协作修改代码,最后合并到同一个 master 分支,然后打包部署,尚且可控。但是一旦团队人员扩张,超过 5 人修改代码,然后一起打包部署,测试阶段只要有一块功能有问题,就得重新编译打包部署,然后重新预览测试,所有相关的开发人员又都得参与其中,效率低下,开发成本极高。
? 系统高可用性差。因为所有的功能开发最后都部署到同一个 WAR 包里,运行在同一个 Tomcat 进程之中,一旦某一功能涉及的代码或者资源有问题,那就会影响整个 WAR 包中部署的功能。比如我经常遇到的一个问题,某段代码不断在内存中创建大对象,并且没有回收,部署到线上运行一段时间后,就会造成 JVM 内存泄露,异常退出,那么部署在同一个 JVM 进程中的所有服务都不可用,后果十分严重。
? 线上发布变慢。特别是对于 Java 应用来说,一旦代码膨胀,服务启动的时间就会变长,有些甚至超过 10 分钟以上,如果机器规模超过 100 台以上,假设每次发布的步长为 10%,单次发布需要就需要 100 分钟之久。因此,急需一种方法能够将应用的不同模块的解耦,降低开发和部署成本。
以微博系统为例,微博既包含了内容模块,也包含了消息模块和用户模块等。其中消息模块依赖内容模块,消息模块和内容模块又都依赖用户模块。当这三个模块的代码耦合在一起,应用启动时,需要同时去加载每个模块的代码并连接对应的资源。一旦任何模块的代码出现bug,或者依赖的资源出现问题,整个单体应用都会受到影响。首先可以把用户模块从单体应用中拆分出来,独立成一个服务部署,以 RPC 接口的形式对外提供服务。微博和消息模块调用用户接口,就从进程内的调用变成远程 RPC 调用。这样,用户模块就可以独立开发、测试、上线和运维,可以交由专门的团队来做,与主模块不耦合。进一步的可以再把消息模块也拆分出来作为独立的模块,交由专门的团队来开发和维护。
微服务特点:
继续以前面举的微博系统为例,可以进一步对内容模块的功能进行拆分,比如内容模块又包含了 feed 模块、评论模块和个人页模块。通过微服务化,将这三个模块变成三个独立的服务,每个服务依赖各自的资源,并独立部署在不同的服务池中,可以由不同的开发人员进行维护。当评论服务需求变更时,只需要修改评论业务相关的代码,并独立上线发布;而feed 服务和个人页服务不需要变更,也不会受到发布可能带来的变更影响。
存在的问题:
服务化最难的是在数据库层,因为数据库中很多数据都是相互关联的,比如用户用户跟订单,订单和商品等等这些数据之间都是有关联的,服务拆分之后会面临以下问题:1当需要读取关联数据时,如果采用表连接的方式查询数据会出现跨数据库查询的可能,2如果是通过RPC的方式多次调用(比如要查订单,就需要查询商品及订单详细信息),也会出现多次调用导致的频繁多次的数据库连接,而如果使用缓存,也会面临数据库与缓存之间的数据同步问题,特别是数据库与缓存服务器都存在集群的情况下,会更难处理,这也是在做微服务之前必须要考虑的问题。
微服务划分的粒度?
\1. 数据库是否拆分?从数据架构的角度看,可能有三个选择:1) 一个db实例,所有微服务在一个schema中,2) 一个db实例,每个微服务有自己的schema,3) 每个微服务有自己的db实例。我们在实际项目中应该如何取舍?
\2. DAO层是否拆分?可能有两个选择: 1) DAO层保持不变或者单独部署成微服务,所有业务微服务通过引用jar包或者HTTP的方式和DAO进行交互。2) 把DAO进行拆分,每个业务微服务内部管理自己会用到的db数据。在所有微服务采用的技术栈相同的情况下,上面哪种方式更可取?
作者回复: 第一个问题:数据库拆分其实不是微服务拆分的关键,如果会引入分布式事务的话,最好不要拆分。
第二个问题:长远来看,建议方案2,这样会减少每个微服务同db的连接,在集群规模上千台的情况下,db的连接数不会成为瓶颈,服务启动也会变快,因为初始化连接也会变少。
比如做一个社交 App,初期为了快速上线,验证可行性,可以只开发首页信息流、评论等基本功能。产品上线后,经过一段时间的运营,用户开始逐步增多,可行性验证通过,下一阶段就需要进一步增加更多的新特性来吸引更多的目标用户,比如再给这个社交 App 添加个人主页显示、消息通知等功能。
一般情况下,这个时候就需要大规模地扩张开发人员,以支撑多个功能的开发。如果这个时候继续采用单体应用架构,多个功能模块混杂在一起开发、测试和部署的话,就会导致不同功能之间相互影响,一次打包部署需要所有的功能都测试 OK 才能上线。
根据我的实际项目经验,一旦单体应用同时进行开发的人员超过 10 人,就会遇到上面的问题,这个时候就该考虑进行服务化拆分了。
服务化拆分的两种姿势
以前面提到的社交 App 为例,你可以认为首页信息流是一个服务,评论是一个服务,消息通知是一个服务,个人主页也是一个服务。
这种服务化拆分方式是纵向拆分,是从业务维度进行拆分。标准是按照业务的关联程度来决定,关联比较密切的业务适合拆分为一个微服务,而功能相对比较独立的业务适合单独拆分为一个微服务。
还有一种服务化拆分方式是横向拆分,是从公共且独立功能维度拆分。标准是按照是否有公共的被多个其他服务调用,且依赖的资源独立不与其他业务耦合。
继续以前面提到的社交 App 举例,无论是首页信息流、评论、消息箱还是个人主页,都需要显示用户的昵称。假如用户的昵称功能有产品需求的变更,你需要上线几乎所有的服务,这个成本就有点高了。显而易见,如果我把用户的昵称功能单独部署成一个独立的服务,那么有什么变更我只需要上线这个服务即可
服务化拆分的前置条件
从单体应用迁移到微服务架构时必将面临也必须解决的。
针对上述问题,你必须有可行的解决方案之后,才能进一步进行服务化拆分。建议的标准是按照每个开发人员负责不超过 3 个大的服务为标准
标签:选择 java 上线 项目 性能 sch 新特性 使用 直接
原文地址:https://www.cnblogs.com/xubeiping0930/p/10421324.html