Dubbo框架微服务开发

更新时间:

从编程开发的角度来说,Dubbo首先是一款RPC服务框架,它最大的优势在于提供了面向接口代理的服务编程模型,对开发者屏蔽了底层的远程通信细节。同时Dubbo也是一款服务治理框架,它为分布式部署的微服务提供了服务发现、流量调度等服务治理解决方案。

最佳实践概述

本次最佳实践主要基于Apache Dubbo框架开发微服务,及描述Apache Dubbo开发微服务的优势,指导传统服务开发到微服务的改造变得必要。最后将详细描述微服务开发过程,对不同的层面进行字面和代码示例方式,指导基于Apache Dubbo微服务开发。同时选择Nacos为注册中心并融入Nacos的配置管理功能,使微服务功能适应多样化的需求。

最佳实践价值

本次最佳实践基于Nacos为注册中心开发的Dubbo微服务,可以无代码修改的迁移至EDAS。微服务托管至EDAS后,您只需要关注Dubbo应用自身的逻辑,无需关注注册中心、配置中心和元数据中心的搭建和维护。托管后还可以使用EDAS提供的弹性伸缩、限流降级、监控及微服务治理能力,而且整个托管过程对您来说是完全透明的,不会增加理解和开发成本。

Apache Dubbo框架来源

在大规模服务化之前,应用可能只是通过RMI或Hessian等工具,简单的暴露和引用远程服务,通过配置服务的URL地址进行调用,通过F5等硬件进行负载均衡。

当服务越来越多时,服务URL配置管理变得非常困难,F5硬件负载均衡器的单点压力也越来越大。此时需要一个服务注册中心,动态地注册和发现服务,使服务的位置透明。并通过在消费方获取服务提供方地址列表,实现软负载均衡和Failover,降低对F5硬件负载均衡器的依赖,也能减少部分成本。

接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器?为了解决这些问题,第一步,要将服务现在每天的调用量,响应时间,都统计出来,作为容量规划的参考指标。其次,要可以动态调整权重,在线上,将某台机器的权重一直加大,并在加大的过程中记录响应时间的变化,直到响应时间到达阈值,记录此时的访问量,再以此访问量乘以机器数反推总容量。

Apache Dubbo是一款高性能的RPC框架。简单来说服务提供者向注册中心注册自己所提供的服务,服务消费者向注册中心订阅自己所需的服务,基于软负载均衡算法向其中一个服务提供者发起服务调用。以上的问题,正是Dubbo设计的源泉,并很好的解决了上述问题。

Apache Dubbo介绍及准备

产品介绍产品介绍节点角色说明

节点

角色说明

Provider

暴露服务的服务提供方

Consumer

调用远程服务的服务消费方

Registry

服务注册与发现的注册中心

Monitor

统计服务的调用次数和调用时间的监控中心

Container

服务运行容器

调用关系说明

  • 服务容器负责启动,加载,运行服务提供者。

  • 服务提供者在启动时,向注册中心注册自己提供的服务。

  • 服务消费者在启动时,向注册中心订阅自己所需的服务。

  • 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

  • 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

  • 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

环境准备流程

在进行开发前,需要准备一下基本内容:

  1. JDK基础运行环境:正确安装JDK 7+,正确配置JAVA_HOME环境变量。

  2. Maven环境及构建Apache Dubbo Maven工程;添加打Jar包与Dubbo开发编译依赖。

  3. 开发IDE:推荐Eclipse或IDEA。

  4. Eclipse配置:Tomcat插件。

  5. IDEA:配置Tomcat。

  6. 注册中心:Apache Dubbo服务的发布与订阅。

微服务开发选用SpringBoot

Spring Boot 是一个真正的游戏改变者。Spring Boot是一个构建在Spring 框架顶部的项目,它提供了一种更简单、更快捷的方式来设置、配置和运行简单的基于Web的应用程序。

在过去Spring框架中,我们需要为应用配置所有的内容,会有许多配置文件,例如XML或元注释,这是Spring Boot解决的主要问题之一,基本无需XML配置了,都使用@注释。

Spring boot巧妙地根据我们选择的依赖配置,可以自动启动我们想要的所有功能,并且只需单击一下即可启动应用程序。此外,它还简化了应用程序的部署过程。

Spring Boot还有很多功能特点:

  • 自动配置:在启动时检测到框架将自动配置,如JDBC。

  • Starter:帮助项目启动,自动添加启动项目依赖项。

  • 实现微服务:提供REST风格API暴露微服务与客户端交互。

  • 自定义配置:通过配置文件来实现各个组件的基本配置。

  • 模块化:一个Spring Boot应用是一个微服务,相当于一个模块,多模块开发后使用Spring Cloud实现动态访问与监控再使用分布式运行,累计扩大规模。

  • 独立打包:一个Spring Boot应用独立设计,生产级质量的应用,通过简单的配置和部署嵌入式Web服务器。

  • 内嵌服务器:默认是Tomcat,可支持Jetty、undertow。

面向接口代理的透明服务开发框架

我们从Dubbo是一个微服务开发框架这个大家熟知的概念开始。就像 Spring是开发Java应用的基础框架一样,我们经常会选用Dubbo作为开发微服务业的基础框架。

Dubbo 框架的最大优势就在于其面向接口的编程模型,使得开发远程服务调用就像开发本地服务一样。这次示例代码使用Spring Boot开发Dubbo微服务应用。

融入Nacos成为注册中心

Dubbo融合Nacos成为注册中心的操作步骤非常简单,大致步骤可分为“增加Maven依赖”以及“配置注册中心”。

  1. 增加Maven依赖,导下面依赖包即可,不需要导dubbo-registry-nacos包。

    <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
            <version>1.1.1</version>
    </dependency>
    
  2. 配置注册中心。

    dubbo.application.name=dubbo-consumer
    dubbo.registry.address=nacos://127.0.0.1:8848
    

创建服务提供者

  1. 在创建好的Maven文件中添加所需要的依赖。

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.0.6.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
            <version>1.1.1</version>
        </dependency>
    </dependencies>
    
  2. 开发Dubbo服务提供者。

    Dubbo中服务都是以接口的形式提供的。

    定义服务接口:

    public interface EchoService {
        String echo(String string);
    
        String echoDubboMix(int id);
    
        String echoMQConsumer(String str);
    }
    

    编写接口实现类:

    import com.alibaba.dubbo.config.annotation.Service;
    import com.alibaba.edas.boot.dao.EchoDao;
    import com.alibaba.edas.boot.rocketmq.SimpleMQConsumer;
    import com.alibaba.edas.boot.rocketmq.SimpleMQProduce;
    import com.alibaba.edas.boot.service.EchoService;
    import org.springframework.beans.factory.annotation.Autowired;
    
    @Service
    public class EchoServiceImpl implements EchoService {
    
        @Autowired
        private EchoDao echoDao;
        @Autowired
        private SimpleMQConsumer simpleMQConsumer;
        @Autowired
        private SimpleMQProduce simpleMQProduce;
    
        public String echo(String str) {
            return "welcome --" + str;
        }
    
        public String echoDubboMix(int id) {
            //写消息
            simpleMQProduce.sendMsg(id+"");
            return echoDao.findById(id).getUserName();
        }
    
        public String echoMQConsumer(String str) {
            //订阅消息
            simpleMQConsumer.receive();
            return str;
        }
    }
    
  3. 配置Dubbo服务。

    dubbo.scan.basePackages=com.alibaba.edas.boot
    dubbo.application.name=dubbo-provider-demo
    dubbo.registry.address=nacos://127.0.0.1:8848
    dubbo.protocol.name=dubbo
    dubbo.protocol.port=-1
    
  4. 开发Spring Boot入口类。

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class DubboProviderApplication {
        public static void main(String[] args) throws InterruptedException {
            SpringApplication.run(DubboProviderApplication.class, args);
        }
    }
    

创建服务消费者

  1. 在创建好的Maven文件中添加所需要的依赖。

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.0.6.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
            <version>1.1.1</version>
        </dependency>
    </dependencies>
    
  2. 开发Dubbo服务消费者。

    Dubbo中服务都是以接口的形式提供的。

    定义服务接口:

    public interface EchoService {
        String echo(String string);
    
        String echoDubboMix(int id);
    
        String echoMQConsumer(String str);
    }
    
  3. 开发Dubbo服务调用。

    import com.alibaba.dubbo.config.annotation.Reference;
    
    import com.alibaba.edas.boot.service.EchoService;
    import com.alibaba.edas.boot.service.MiddleService;
    import com.alibaba.nacos.api.config.annotation.NacosValue;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    import org.springframework.web.bind.annotation.*;
    
    @RestController
    @RequestMapping(value = "/poc")
    @Api(description = "DUBBO-POC功能测试接口")
    public class ConsumerController {
    
        @Reference
        private EchoService echoService;
        @Reference
    private MiddleService middleService;
    
        @ApiOperation(value = "获取服务者返回信息 A->C")
        @RequestMapping(value = "/dubbo-echo-mid", method = RequestMethod.GET)
        public String echo(@RequestParam("str") String str) {
            return echoService.echo(str) + "\r\n";
        }
    
        @ApiOperation(value = "通过ID查询数据库获取返回信息、RocketMQ写信息 A->C")
        @RequestMapping(value = "/dubbo-echo-mix", method = RequestMethod.GET)
        public String echoDubboMix(@RequestParam("id") int id) {
            return echoService.echoDubboMix(id) + "\r\n";
        }
    
        @ApiOperation(value = "RocketMQ订阅消息 A->C")
        @RequestMapping(value = "/dubbo-echo-mq", method = RequestMethod.GET)
        public String echoMQConsumer(@RequestParam("str") String str) {
            return echoService.echoMQConsumer(str) + "\r\n";
        }
    
        @ApiOperation(value = "获取版本信息")
        @RequestMapping(value = "/echo-version", method = RequestMethod.GET)
        public String echoVersion() {
            return "This is dubbo spring boot version old" + "\r\n";
        }
    }
    
  4. 在application.properties配置文件中新增一下配置。

    #spring.application.name=spring-boot-consumer
    dubbo.application.name=dubbo-consumer-demo
    dubbo.registry.address=nacos://127.0.0.1:8848
    
  5. 开发Spring Boot入口类。

    import com.alibaba.nacos.spring.context.annotation.config.NacosPropertySource;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class DubboConsumerApplication {
        public static void main(String[] args) {
            SpringApplication.run(DubboConsumerApplication.class, args);
        }
    }
    

融入Nacos配置管理功能

  1. 在上述consumer工程中的pom.xml添加依赖。

    <!-- 导入Nacos配置管理依赖包 -->
    <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>nacos-config-spring-boot-starter</artifactId>
            <version>0.2.1</version>
    </dependency>
    <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>nacos-config-spring-boot-actuator</artifactId>
            <version>0.2.1</version>
    </dependency>
    
  2. 在application.properties中配置Nacos server的地址。

    nacos.config.server-addr=127.0.0.1:8848
  3. 使用@NacosPropertySource加载dataId为example的配置源,并开启自动更新。

    import com.alibaba.nacos.spring.context.annotation.config.NacosPropertySource;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    @NacosPropertySource(dataId = "nacos", autoRefreshed = true)
    public class DubboConsumerApplication {
        public static void main(String[] args) {
            SpringApplication.run(DubboConsumerApplication.class, args);
        }
    }
    
  4. 通过Nacos的@NacosValue注解设置属性值。

    @RestController
    @RequestMapping(value = "/poc")
    @Api(description = "DUBBO-POC功能测试接口")
    public class ConsumerController {
            
            @NacosValue(value = "${useLocalCache:false}", autoRefreshed = true)
        private String useLocalCache;
            
            @ApiOperation(value = "全局参数配置")
        @RequestMapping(value = "/echo-acm", method = RequestMethod.GET)
        public String echoAcm() {
            return "配置文件中的value值:" + useLocalCache + "\r\n";
        }
    }