作者:Eddy 历史版本:1 最后编辑:龚清 更新时间:2024-05-27 11:07
微服务与单体应用的区别
什么是微服务?
- 每个模块都有自己独立的业务;
- 每个模块都是服务的应用,可以独立运行并提供接口服务;
- 开发新的业务只需要新增模块,提供自己的接口服务即可;
- 原生支持高可用、集群;
什么是单体应用?
- 单体应用就是传统的应用,前端与后端做了分离;
- 所有业务都在同一个应用中运行并提供接口服务;
- 新开发的业务也放在同一个应用中运行;
- 高可用、集群方案需要另外处理;
微服务与单体应用的区别?
- 微服务需要部署N个应用,还需要其它外部应用支撑(注册中心、网关等),部署、运维成本较高。集群、高可用方案无需额外处理;
- 单体应用只需要部署一个应用即可,相对于微服务部署、运维成本较低。高可用、集群方案需要另外处理;
版本对比说明
对比项 | 微服务版本 | 单体版本 | 备注 |
---|---|---|---|
功能是否一致 | 一致 | 一致 | |
前端代码是否一致 | 一致 | 一致 | |
后端底层代码是否一致 | 一致 | 一致 | |
后端上层应用架构是否一致 | 不一致 | 不一致 | |
后端数据库数量 | 2 | 1 | |
是否依赖注册中心组件 | 依赖 | 不依赖 | |
是否依赖FeignClient组件 | 依赖 | 不依赖 | |
是否依赖Ribbon组件 | 依赖 | 不依赖 | |
是否修改配置即可切换 | 否 | 否 | 两个版本主要差异是上层应用架构设计区别很大;经过本团队多年的技术积累经验在应用设计阶段做了重要设计,从而达到两个版本同时维护且相互不影响的状态。本质是两套应用代码 。 |
最终交付物是否一致 | 不一致 | 不一致 |
如何设计微服务与单体应用兼容的架构?
代码架构设计
- 接口设计方式controller层使用接口方式设计。
package com.lc.ibps.org.api;
@Validated
@RequestMapping(value = "/entity")
@RestController
public interface IPartyEntityService {
/**
*
* 通过ID转换为名称
*
* @param transVo
* @return
*/
@RequestMapping(value = "/trans", method = RequestMethod.POST)
public APIResult<PartyEntityTransResultVo> trans(@RequestBody(required = true) PartyEntityTransVo transVo);
@RequestMapping(value = "/transfer", method = {RequestMethod.POST})
public APIResult<Map<String, Map<String, String>>> transfer(@RequestBody(required = true) IdKeyVo idKeyVo);
/**
*
* 根据类型和值查询用户
*
* @param List<ExtractUserVo>
* @return
*/
@RequestMapping(value = "/extraUser", method = RequestMethod.POST)
APIResult<List<String>> extraUser(@RequestBody(required = true) List<ExtractUserVo> voList);
/**
*
* 根据别名类型转换成Id
*
* @param List<ExtractUserVo>
* @return
*/
@RequestMapping(value = "/transAliasToID", method = RequestMethod.POST)
APIResult<List<String>> transAlias2Id(@RequestBody(required = true) List<ExtractUserVo> voList);
}
- 所有服务间调用都通过接口方式调用。
package com.lc.ibps.bpmn.domain;
import com.lc.ibps.org.api.IPartyEntityService;
@Service
public class BpmDefine extends AbstractDomain<String, BpmDefinePo> {
@Autowired
@Lazy
private IPartyEntityService partyEntityService;
}
- 产品开发以微服务形态开发,以保证架构的完整性、兼容性。
数据库设计
- 根据微服务划分,进行完整的数据库设计。
- 微服务形态下,数据库按照拆库方式创建、部署。
- 单体形态下,将数据库合并到一个库创建、部署。
依赖设计
- 将微服务依赖组件独立维护,方便后续微服务形态使用。
<modules>
<module>modules/basic-feign</module>
<module>modules/basic-client</module>
<module>modules/basic-nacos</module>
<module>modules/basic-discovery</module>
</modules>
- 微服务依赖设计
微服务形态服务间依赖皆以feign接口方式依赖从而调用到其他服务的接口。
<dependencies>
<dependency>
<groupId>com.lc.ibps.cloud</groupId>
<artifactId>ibps-basic-i18n</artifactId>
</dependency>
<dependency>
<groupId>com.lc.ibps.cloud</groupId>
<artifactId>ibps-basic-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>${jboss-logging.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.lc.ibps.provider</groupId>
<artifactId>ibps-provider-platform-default</artifactId>
</dependency>
<dependency>
<groupId>com.lc.ibps.cloud</groupId>
<artifactId>ibps-oauth-client-feignclient</artifactId>
</dependency>
<dependency>
<groupId>com.lc.ibps.provider.base</groupId>
<artifactId>ibps-provider-form-client</artifactId>
</dependency>
<dependency>
<groupId>com.lc.ibps.provider.base</groupId>
<artifactId>ibps-provider-bpmn-client</artifactId>
</dependency>
<dependency>
<groupId>com.lc.ibps.socket</groupId>
<artifactId>ibps-socket-cloud</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>oracledriver</artifactId>
</dependency>
<dependency>
<groupId>fakepath</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>dm.jdbc</groupId>
<artifactId>DmJdbcDriver</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
- 单体应用依赖设计
单体形态模块间依赖皆以java implement实现类方式依赖从而调用到其他模块的接口。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
<exclusion>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- TODO 外部tomcat部署时需要去掉内置容器依赖 -->
<!--
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
-->
<!--
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
<exclusions>
<exclusion>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>${jboss-logging.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
</dependency>
<dependency>
<groupId>com.lc.ibps.cloud</groupId>
<artifactId>ibps-basic-provider</artifactId>
</dependency>
<dependency>
<groupId>com.lc.ibps.cloud</groupId>
<artifactId>ibps-basic-monitor</artifactId>
</dependency>
<dependency>
<groupId>com.lc.ibps.cloud</groupId>
<artifactId>ibps-basic-validator</artifactId>
</dependency>
<dependency>
<groupId>com.lc.ibps.cloud</groupId>
<artifactId>ibps-basic-swagger</artifactId>
</dependency>
<dependency>
<groupId>com.lc.ibps.cloud</groupId>
<artifactId>ibps-basic-i18n</artifactId>
</dependency>
<dependency>
<groupId>com.lc.ibps.cloud</groupId>
<artifactId>ibps-basic-response</artifactId>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.lc.ibps.cloud</groupId>
<artifactId>ibps-oauth-client-local</artifactId>
<exclusions>
<exclusion>
<groupId>net.oschina.j2cache</groupId>
<artifactId>j2cache-mybatis</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.lc.ibps.base</groupId>
<artifactId>ibps-base-web</artifactId>
</dependency>
<dependency>
<groupId>com.lc.ibps.message</groupId>
<artifactId>ibps-message-producer</artifactId>
</dependency>
<dependency>
<groupId>com.lc.ibps.excessive</groupId>
<artifactId>ibps-excessive-platform</artifactId>
</dependency>
<dependency>
<groupId>com.lc.ibps.socket</groupId>
<artifactId>ibps-socket-local</artifactId>
</dependency>
<!-- oauth2server -->
<dependency>
<groupId>com.lc.ibps.cloud</groupId>
<artifactId>ibps-oauth-base</artifactId>
</dependency>
<dependency>
<groupId>com.lc.ibps.cloud</groupId>
<artifactId>ibps-oauth-server2-default</artifactId>
</dependency>
<!-- platform -->
<dependency>
<groupId>com.lc.ibps.provider</groupId>
<artifactId>ibps-provider-platform-default</artifactId>
</dependency>
<!-- business -->
<dependency>
<groupId>com.lc.ibps.provider</groupId>
<artifactId>ibps-provider-form</artifactId>
</dependency>
<dependency>
<groupId>com.lc.ibps.provider</groupId>
<artifactId>ibps-provider-bpmn</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>oracledriver</artifactId>
</dependency>
<dependency>
<groupId>fakepath</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>dm.jdbc</groupId>
<artifactId>DmJdbcDriver</artifactId>
</dependency>
<dependency>
<groupId>fakepath</groupId>
<artifactId>sqlite-jdbc</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
切换说明
微服务切换到单体形态无需修改代码,只需在上层应用处理依赖即可。
单体切换到微服务形态亦如此。
产品设计阶段已经将依赖规范设计好,并维护好两种形态的应用,开发只需关注业务即可,如何部署由现场部署要求执行即可。
内部开发时会同时部署微服务形态、单体形态应用,测试部门会对不同形态应用进行测试,以保证兼容性。