单体应用模拟微服务 - Maven

方案关键词:maven -> scope -> runtime

一、标准微服务化实现

微服务概念、特性啥的网上很多,这里略过,有兴趣的可以Google。 微服务架构的优势与不足 什么是微服务架构?
但是其中最基本的一个特性就是 服务接口API对服务调用方Consumer可见,但是服务实现Provider对Consumer不可见
这样服务双方解耦后,方便快速迭代。

dubbo为例:

服务调用方配置如下:
pom.xml

<dependency>
    <groupId>com.goobai.aics</groupId>
    <artifactId>aics-data-api</artifactId>
    <version>1.0.0</version>
</dependency>

applicationContext.xml

<dubbo:reference version="1.0" id="productService" interface="com.goobai.aics.data.api.service.ProductService"/>

可以看出调用方是只能引用aics-data-api中的服务接口ProductService,该服务的实现是不可见的。

HTTP协议的RPC

如果接口是HTTP协议的话,服务调用方和提供方的耦合甚至更低,provider连api的jar包都不需要提供,只需要提供api接口说明文档即可。当然,provider的实现也对Consumer不可见。

二、使用Maven模拟微服务化

新项目在开始阶段的时候,开发人员少、代码量也不多,标准微服务带来的好处并不明显,反而容易增加代码管理成本,比如调试、排错等(打开的IDE也多)。但是使用单体应用模式,又担心项目增长后,迁移到微服务的代价太大。 面对这种情况,我们团队在开发过程中逐步摸索了一个简单的办法,在单体应用中使用maven实现对微服务的模拟,既可以在前期实现快速开发,又大大降低了微服务化的成本。

下面实例中以aics-data-api为服务接口,aics-data-provider为服务实现者,aics-server为服务调用方

  • 效果:只有服务API对Consumer可见,其实现对Consumer不可见,但却能为单体应用中的调用方提供服务

  • 方法简述:Consumer以compile(maven默认)的方式引入api(如aics-data-api),但是以runtime的方式引入实现(如aics-data-provider)

Maven项目架构如下图所示: aics-data-api是服务api,aics-data-provider是服务实现,aics-server是服务调用方


具体实现如下:

2.1 服务api(如aics-data-api)

public class ProductSevice {
    Optional<Product> queryById(int id)
}

2.2 服务实现provider(如aics-data-provider)

Provider中的Spring配置文件,叫做data-applicationContext.xml(名字其实都可以,但是不能跟consumer一样,方便在consumer的spring引用)

@Service
public class ProductServiceImpl implements ProductService {
    @Resource
    private ProductMapper productMapper;
    
    @Override
    Optional<Product> queryById(int id) {
        return Optional.ofNullable(productMapper.selectByPrimaryKey(id));
    }
}

2.3 服务调用方consumer

服务调用方(aics-server)的pom.xml

<dependency>
    <groupId>com.goobai.aics</groupId>
    <artifactId>aics-data-api</artifactId>
    <version>1.0.0</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>com.goobai.aics</groupId>
    <artifactId>aics-data-provider</artifactId>
    <version>1.0.0</version>
    <scope>runtime</scope>
</dependency>

重点!!!: 注意看上面两个jar的scope,其中api的是compile,provider的是runtime

applicationContext.xml

<import resource="classpath*:data-applicationContext.xml" />
@RequestMapping("api/products")
@RestController
public class ProductController {
    @Resource
    private ProductService productService;
    
    @RequestMapping(value = "{id:\\d+}", method = RequestMethod.GET)
    public WebResult getOne(@PathVariable(name = "id") int id) {
        final Optional<Product> productOpt = productService.queryById(id);
        return productOpt.map(WebResult::new)
                .orElseGet(() -> new WebResult(404, "product does not exists"));
    }
}

2.4 其他

  1. aics-data-provider不能配置PropertySourcesPlaceholderConfigurerPropertyPlaceholderConfigurer。因为一个Spring上下文中只能有一个。所以最好配置在服务调用方(如:aics-server)

结语

使用Maven模拟微服务后,降低了项目中各模块间的耦合度;而且一般不同的功能模块主要是由一人负责,这样在开发过程中虽然在同一个git仓库,但也极少有代码冲突,提供了并发开发的效率。

PS: 这个方案是团队逐步摸索出来的,肯定存在很多的问题,欢迎各位大神批评指正,不胜感激!

参考文献

  1. 微服务架构的优势与不足
  2. 什么是微服务架构?

如果对你有一点帮助,麻烦为我点一个赞,如果没有帮助,也非常期待你的反馈

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容