Dubbo 一篇文章就够了:从入门到实战

1、Dubbo 处理流程

节点说明:

节点

角色名称

Provider

暴露服务的服务提供方

Consumer

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

Registry

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

Monitor

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

Container

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

调用关系说明:

  • 虚线:代表异步调用
  • 实线:代表同步访问
  • 蓝色虚线:是在启动时完成的功能
  • 红色虚线:是程序运行中执行的功能

调用流程:

  1. 服务提供者在服务容器启动时,向注册中心注册自己提供的服务。
  2. 服务消费者在启动时,向注册中心订阅自己所需的服务。
  3. 注册中心返回服务提供者地址列表给消费者,如果有变更注册中心会基于长连接推送变更数据给消费者。
  4. 服务消费者从提供者地址列表中,基于软负载均衡算法选一台提供者进行调用;如果调用失败,则重新选择一台。
  5. 服务提供者和消费者,在内存中的调用次数和调用时间、定时每分钟发送给监控中心。

2、入门案例介绍

在Dubbo中所有的的服务调用都是基于接口去进行双方交互的。双方协定好Dubbo调用中的接口,提供者来提供实现类并且注册到注册中心上。调用方则只需要引入该接口,并且同样注册到相同的注册中心上(消费者)。即可利用注册中心来实现集群感知功能,之后消费者即可对提供者进行调用。

我们所有的项目都是基于Maven去进行创建,这样相互在引用的时候只需要以依赖的形式进行展现就可以了。

并且这里我们会通过maven的父工程来统一依赖的版本。

程序实现分为以下几步骤:

  1. 建立maven工程 并且 创建API模块: 用于规范双方接口协定
  2. 提供provider模块,引入API模块,并且对其中的服务进行实现。将其注册到注册中心上,对外来统一提供服务。
  3. 提供consumer模块,引入API模块,并且引入与提供者相同的注册中心。再进行服务调用。

3、开发过程

项目结构如下

定义了一个父模块demo-base,然后再下面创建了三个子模块。父工程的pom.xml中主要是对Duboo相关jar进行版本控制,这样子模块导入依赖时,就不需要指定版本了。

<?xml version="1.0" encoding="UTF-8"?>    4.0.0        com.lagou    demo-base    pom    1.0-SNAPSHOT            service-api        service-provider        service-consumer                    2.7.3                                                org.apache.dubbo                dubbo                ${dubbo.version}                                        org.apache.dubbo                dubbo-common                ${dubbo.version}                                        org.apache.dubbo                dubbo-registry-zookeeper                ${dubbo.version}                                        org.apache.dubbo                dubbo-registry-nacos                ${dubbo.version}                                        org.apache.dubbo                dubbo-rpc-dubbo                ${dubbo.version}                                        org.apache.dubbo                dubbo-remoting-netty4                ${dubbo.version}                                        org.apache.dubbo                dubbo-serialization-hessian2                ${dubbo.version}                                                            log4j            log4j            1.2.16                            org.slf4j            slf4j-api            1.7.5                            org.slf4j            slf4j-log4j12            1.7.5                                            com.alibaba            fastjson            1.2.62                                                        org.apache.maven.plugins                maven-compiler-plugin                3.5.1                                    11                    11                                        

3.1、创建service-api模块

这个模块的作用提供一个接口,供生产者使用。(pom.xm中没有导入依赖,故省略)

package com.lagou.service;public interface HelloService {    String sayHello(String name);}

3.2、创建service-provider模块

这个模块作用是实现上面中的接口,然后借助于zookeeper暴露服务,供其消费者远程调用

注:这个模块必须导入service-api模块,不然无法实现其接口

(1)pom.xml

<?xml version="1.0" encoding="UTF-8"?>            demo-base        com.lagou        1.0-SNAPSHOT        4.0.0        service-provider                            com.lagou            service-api            1.0-SNAPSHOT                                    org.apache.dubbo            dubbo                            org.apache.dubbo            dubbo-registry-zookeeper                            org.apache.dubbo            dubbo-rpc-dubbo                            org.apache.dubbo            dubbo-remoting-netty4                            org.apache.dubbo            dubbo-serialization-hessian2                                                        org.apache.maven.plugins                maven-compiler-plugin                3.5.1                                    11                    11                                        

(2)编写实现类。注意这里也使用了Dubbo中的@Service 注解来声明他是一个服务的提供者。

package com.lagou.service.impl;import com.lagou.service.HelloService;import org.apache.dubbo.config.annotation.Service;@Service // 使用Duboo中的service注解声明服务提供者public class HelloServiceImpl implements HelloService {    @Override    public String sayHello(String name) {        return "hello:"+name;    }}

(3)编写配置文件,用于配置dubbo。比如这里我就叫dubbo-provider.properties ,放入到resources 目录下。

dubbo.application.name=dubbo-providerdubbo.protocol.name=dubbodubbo.protocol.port=20880
  • dubbo.application.name: 当前提供者的名称
  • dubbo.protocol.name : 对外提供的时候使用的协议
  • dubbo.protocol.port : 该服务对外暴露的端口是什么,在消费者使用时,则会使用这个端口并且使用指定的协议与提供者建立连接。

(4)编写启动的main 函数。这里面做得比较简单,主要要注意注解方式中的注册中心这里是使用的本机2181端口来作为注册中心。

package com.lagou;import org.apache.dubbo.config.RegistryConfig;import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.PropertySource;import java.io.IOException;public class DubboPureMain {    public static void main(String[] args) throws IOException {        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class);        context.start();        System.in.read();    }    @Configuration    @EnableDubbo(scanBasePackages = "com.lagou.service.impl")    @PropertySource("classpath:/dubbo-provider.properties")    static class ProviderConfiguration {        @Bean        public RegistryConfig registryConfig() {            RegistryConfig config = new RegistryConfig();            config.setAddress("zookeeper://127.0.0.1:2181");            return config;        }    }}

注意:在运行代码前,一定要确保,zookeeper服务已经启动了。还有如果运行时,报错提示zookeeper not connected ,可能会是zookeeper的超时时间设置过短,需要在配置文件去设置。还有可能是各个jar版本的问题,反正这个版本,我尝试过没有问题。控制台出现 log4j的爆红提示,是因为没有添加 log4j.properties 配置文件,添加上就可以了。

log4j.rootCategory=INFO,CONSOLElog4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayoutlog4j.appender.CONSOLE.layout.ConversionPattern=%d{HH:mm:ss.SSS} [%t] %-5p %c.%M\(%F:%L\) - %m%n

3.3、创建service-consumer模块

此模块作用是消费生产者暴露的服务,说人话就是,调用生产者暴露出来的的方法。

(1)pom.xml

<?xml version="1.0" encoding="UTF-8"?>            demo-base        com.lagou        1.0-SNAPSHOT        4.0.0        service-consumer                            com.lagou            service-api            1.0-SNAPSHOT                                    org.apache.dubbo            dubbo                            org.apache.dubbo            dubbo-registry-zookeeper                            org.apache.dubbo            dubbo-rpc-dubbo                            org.apache.dubbo            dubbo-remoting-netty4                            org.apache.dubbo            dubbo-serialization-hessian2                                                            org.apache.maven.plugins                maven-compiler-plugin                3.5.1                                    11                    11                                        

(2)编写服务,用于真实的引用dubbo接口并使用。因为这里是示例,所以比较简单一些。这里面 @Reference 中所指向的就是真实的第三方服务接口。

package com.lagou.bean;import com.lagou.service.HelloService;import org.apache.dubbo.config.annotation.Reference;import org.springframework.stereotype.Component;@Componentpublic class ConsumerComponent {    @Reference    // 引用dubbo,远程调用方法    private HelloService helloService;    public String sayHello(String name) {        return  helloService.sayHello(name);    }}

(3)编写消费者的配置文件。这里比较简单,主要就是指定了当前消费者的名称和注册中心的位置。通过这个注册中心地址,消费者就会注册到这里并且也可以根据这个注册中心找到真正的提供者列表。

dubbo.application.name=service-consumerdubbo.registry.address=zookeeper://127.0.0.1:2181dubbo.application.qosEnable=truedubbo.application.qosPort=33333dubbo.application.qosAcceptForeignIp=false

(4)编写启动类,这其中就会当用户在控制台输入了一次换行后,则会发起一次请求。

package com.lagou;import com.lagou.bean.ConsumerComponent;import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.PropertySource;import java.io.IOException;public class AnnotationConsumerMain {    public static void main(String[] args) throws IOException {        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class);        context.start();        // 获取消费者组件        ConsumerComponent service = context.getBean(ConsumerComponent.class);        while (true) {            System.in.read();            String result = service.sayHello("张三");            System.out.println("result:"+result);        }    }    @Configuration    @PropertySource("classpath:/dubbo-consumer.properties")    @ComponentScan(basePackages = "com.lagou.bean")    @EnableDubbo    static class ConsumerConfiguration {    }}

至此,配置远程调用服务完成。

4、配置方式介绍

下面我们来使用不同的方式来对Dubbo进行配置。每种配置方式各有不同,一般可以分为以下几个

  • 注解 : 基于注解可以快速地将程序配置,无需多余的配置信息,包含提供者和消费者。但是这种方式有一个弊端,有些时候配置信息并不是特别好找,无法快速定位。(上面案例就是注解方式)
  • XML : 一般这种方式我们会和Spring做结合,相关的Service和Reference均使用Spring集成后的。通过这样的方式可以很方便地通过几个文件进行管理整个集群配置。可以快速定位也可以快速更改。
  • 基于代码方式 : 基于代码方式的对上述配置进行配置。这个使用的比较少,这种方式更适用于自己公司对其框架与Dubbo做深度集成时才会使用。

5、XML方式

我们一般XML会结合Spring应用去进行使用,将Service的注册和引用方式都交给Spring去管理。下面我们还是针对于上面的demo进行实现。

这里我们针对于api模块不做处理,还是使用原先的接口。从提供者和消费者做讲解。这了我们直接通过spring的方式去做讲解。

5.1、provider模块

(1)pom.xml

<?xml version="1.0" encoding="UTF-8"?>            demo-base-xml        com.lagou        1.0-SNAPSHOT        4.0.0        service-provider                            com.lagou            service-api            1.0-SNAPSHOT                                    org.apache.dubbo            dubbo                            org.apache.dubbo            dubbo-registry-zookeeper                            org.apache.dubbo            dubbo-registry-nacos                            org.apache.dubbo            dubbo-rpc-dubbo                            org.apache.dubbo            dubbo-remoting-netty4                            org.apache.dubbo            dubbo-serialization-hessian2                            org.apache.dubbo            dubbo-config-spring            2.7.3                            11        11    

注意这个xml中比使用注解方式的方式,要多导入一个依赖:

    org.apache.dubbo    dubbo-config-spring    2.7.3

(2)编写实现类,不需要引入任何的注解配置。

package com.lagou.service.impl;import com.lagou.service.HelloService;public class HelloServiceImpl implements HelloService {    @Override    public String sayHello(String name) {        return "hello: " + name;    }}

(3)编写dubbo-provider.xml 文件,用于对dubbo进行文件统一配置。并且对刚才的配置进行引入。

<?xml version="1.0" encoding="UTF-8"?>                                            

(4)编写模块启动类。

package com.lagou;import org.springframework.context.support.ClassPathXmlApplicationContext;public class ProviderApplication {    public static void main(String[] args) throws Exception {        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:dubbo-provider.xml");        applicationContext.start();        System.in.read();    }}

5.2、consumer模块

(1)pom.xml

<?xml version="1.0" encoding="UTF-8"?>            demo-base-xml        com.lagou        1.0-SNAPSHOT        4.0.0        service-consumer                            com.lagou            service-api            1.0-SNAPSHOT                            org.apache.dubbo            dubbo                            org.apache.dubbo            dubbo-registry-zookeeper                            org.apache.dubbo            dubbo-registry-nacos                            org.apache.dubbo            dubbo-rpc-dubbo                            org.apache.dubbo            dubbo-remoting-netty4                            org.apache.dubbo            dubbo-serialization-hessian2                            org.apache.dubbo            dubbo-config-spring            2.7.3                            11        11    

(2)定义spring的配置xml

<?xml version="1.0" encoding="UTF-8"?>                            

(3)引入启动模块。因为引用了Spring框架,所以再上一步的helloService会被当做一个bean注入到真实的环境中。在我们生产级别使用的时候,我们可以通过Spring中的包扫描机制,通过@Autowired 这种机制来进行依赖注入。

package com.lagou;import com.lagou.service.HelloService;import org.springframework.context.support.ClassPathXmlApplicationContext;public class ConsumerApplication {    public static void main(String[] args) throws Exception {        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:dubbo-comsumer.xml");        // applicationContext.start(); 可以不启动,也能获取bean        HelloService helloService = applicationContext.getBean("helloService", HelloService.class);        System.in.read();        String result = helloService.sayHello("world");        System.out.println("result=" + result);    }}
发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章