什么是微服务?

  • 每个模块都有自己独立的业务;
  • 每个模块都是服务的应用,可以独立运行并提供接口服务;
  • 开发新的业务只需要新增模块,提供自己的接口服务即可;
  • 原生支持高可用、集群;

什么是单体应用?

  • 单体应用就是传统的应用,前端与后端做了分离;
  • 所有业务都在同一个应用中运行并提供接口服务;
  • 新开发的业务也放在同一个应用中运行;
  • 高可用、集群方案需要另外处理;

微服务与单体应用的区别?

  • 微服务需要部署N个应用,还需要其它外部应用支撑(注册中心、网关等),部署、运维成本较高。集群、高可用方案无需额外处理;
  • 单体应用只需要部署一个应用即可,相对于微服务部署、运维成本较低。高可用、集群方案需要另外处理;

版本对比说明

对比项 微服务版本 单体版本 备注
功能是否一致 一致 一致
前端代码是否一致 一致 一致
后端底层代码是否一致 一致 一致
后端上层应用架构是否一致 不一致 不一致
后端数据库数量 2 1
是否依赖注册中心组件 依赖 不依赖
是否依赖FeignClient组件 依赖 不依赖
是否依赖Ribbon组件 依赖 不依赖
是否修改配置即可切换 两个版本主要差异是上层应用架构设计区别很大;经过本团队多年的技术积累经验在应用设计阶段做了重要设计,从而达到两个版本同时维护且相互不影响的状态。本质是两套应用代码
最终交付物是否一致 不一致 不一致

如何设计微服务与单体应用兼容的架构?

代码架构设计

IBPS-V3微服务代码层次

  1. 接口设计方式,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);

}
  1. 所有服务间调用都通过接口方式调用。
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;
}
  1. 产品开发以微服务形态开发,以保证架构的完整性、兼容性。

数据库设计

  1. 根据微服务划分,进行完整的数据库设计。
  2. 微服务形态下,数据库按照拆库方式创建、部署。
  3. 单体形态下,将数据库合并到一个库创建、部署。

依赖设计

  1. 将微服务依赖组件独立维护,方便后续微服务形态使用。
    <modules>
        <module>modules/basic-feign</module>
        <module>modules/basic-client</module>
        <module>modules/basic-nacos</module>
        <module>modules/basic-discovery</module>
    </modules>
  1. 微服务依赖设计

    微服务形态服务间依赖皆以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>
  1. 单体应用依赖设计

    单体形态模块间依赖皆以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>

切换说明

微服务切换到单体形态无需修改代码,只需在上层应用处理依赖即可。
单体切换到微服务形态亦如此。
产品设计阶段已经将依赖规范设计好,并维护好两种形态的应用,开发只需关注业务即可,如何部署由现场部署要求执行即可。
内部开发时会同时部署微服务形态、单体形态应用,测试部门会对不同形态应用进行测试,以保证兼容性。

文档更新时间: 2023-04-23 09:48   作者:Eddy