Dubbo-入门到精通(一)

为了个人的技术提升,所以今天开始自学dubbo(当然,肯定要参考官方文档和其他各位大神的文章,,标题中的入门到精通,现在才是入门的开始),以此来记录遇到的问题和大家分享,在这里我参考了(https://segmentfault.com/a/1190000019896723)他的文章,在他的文章里讲了几种开发方式,xml, api和基于注解。既然如今 springboot 盛行,大家都倾向于 java config的方式,所以我这里只写一下 java config方式的启动。

一、首先引入maven(可能导致 log4j 冲突,所以我把它给移除了),这里引用了 dubbo git上的推荐 (dubbo 官方地址:http://dubbo.apache.org/en-us/ ,dubbo git地址:https://github.com/apache/dubbo)。 

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.yqn.herman</groupId>
    <artifactId>study.dubbo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <dubbo.version>2.7.5</dubbo.version>
        <java.compiler.version>1.8</java.compiler.version>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
            <version>${dubbo.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-dependencies-zookeeper</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-log4j12</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
            <version>${dubbo.version}</version>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

</project>
View Code

二、本地搭一套 zookeeper 环境

从步骤一中的引入我们可以知道,dubbo是需要zk共同协作的,至于为什么需要zk,这里依然引用 dubbo git的图,从图中可以看到dubbo需要有一个东西作为服务注册和发现的中间件,作用和 spring cloud里的 Eureka等同,那么dubbo优先选择的就是zk。

由于我是在windows写项目,因此如果是windonws的同学,可以直接去 zk 官网下载(https://www.apache.org/dyn/closer.cgi/zookeeper/ ,注意,windows一定要下载 bin.tar.gz 结尾的镜像文件,然后参考 https://www.cnblogs.com/xiohao/p/9717364.html 启动

一个单机节点就可以使用了)

三、编写服务,这里我们简单的进行示例,接收服务调用方的参数并打印,然后返回服务调用方(注意,代码里边有些包名是我自己的,需要你根据你自己的项目改写):

  定义一个接口:

public interface ServiceProvider {
    String getMyName(String name);
}

  实现接口,这里接口的实现需要加入 @Service 注解(注意,这个注解不要引 spring的,而是需要引 dubbo的):

@Service
public class ServiceProviderImpl implements ServiceProvider {
    
    @Override
    public String getMyName(String name) {
        System.out.println("接收到服务调用者的名字:" + name);
        return "hello, " + name;
    }
}

  java config形式注入dubbo启动需要的环境(此处有一个大坑,在设置 RegistryConfig 的时候我也写在了注释里边,就是虽然在代码里设置了port,但是没有生效,导致我一致连不上zk, 原因是 dubbo在启动过程中会检测你是否有自定义的 RegistryConfig,从而

       帮你把这个类给转化成 ConfigCenterConfig, 但是在转化的过程中,只赋值了 protocol, address等,port却被拿去用来 设置id了,参考类 DubboBootstrap.useRegistryAsConfigCenterIfNecessary()):

package com.yqn.herman.demo;

import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author Lu, Hui
 * @since 2020/1/11
 **/
@Configuration
public class ServiceCustomerConfig {
    @Bean // #1 服务提供者信息配置,这里我们直接采用默认的
    public ProviderConfig providerConfig() {
        ProviderConfig providerConfig = new ProviderConfig();
        providerConfig.setTimeout(1000);
        return providerConfig;
    }

    @Bean // #2 分布式应用信息配置
    public ApplicationConfig applicationConfig() {
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("dubbo-annotation-provider"); //设置服务的名字,分布式环境下必须保证唯一性,和spring cloud下的 application name一样
        return applicationConfig;
    }

    @Bean // #3 注册中心信息配置
    public RegistryConfig registryConfig() {
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setProtocol("zookeeper");
        registryConfig.setAddress("localhost:2181"); // zk server 地址,一定要在这里把port加上
        //registryConfig.setPort(2181); // zk client 监听端口, 设置了也没有任何效果
        return registryConfig;
    }

    @Bean // #4 使用协议配置,这里使用 dubbo
    public ProtocolConfig protocolConfig() {
        ProtocolConfig protocolConfig = new ProtocolConfig();
        protocolConfig.setName("dubbo");
        protocolConfig.setPort(20880);
        return protocolConfig;
    }
}
View Code

启动并发布我们的服务(注意,这个时候需要我们先启动 zk, 不然会报错,我的zk是下载下来后的默认端口):

package com.yqn.herman.demo;


import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


import java.util.concurrent.CountDownLatch;

/**
 * @author Lu, Hui
 * @since 2020/1/11
 **/
@SpringBootApplication
@EnableDubbo(scanBasePackages = "com.yqn.herman.demo") //参考其注释可以知道,这里是所有 @Service 注解标注的服务的包,也就是我们要对外发布的所有服务
public class ServiceStarter {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(ServiceStarter.class);
        new CountDownLatch(1).await(); //
    }

}
View Code

到这里基本没有意外了,启动成功:

接下来,我们需要写服务消费者了:

首先定义我们的消费者:

package com.yqn.herman.demo.com.yqn.herman.client;

import com.yqn.herman.demo.provider.ServiceProvider;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Component;

/**
 * @author Lu, Hui
 * @since 2020/1/11
 **/
@Component // 在这里,我的消费者和服务提供者在同一个项目,所以我直接引用了,如果你分开写了,需要在你的客户端引入服务者的jar包
public class ServiceConsumer {

    @Reference //该注解类似于 spring cloud 的 feign, 通过对这个注解的处理来找到需要的服务
    private ServiceProvider serviceProvider;

    public void call(String name) {
        serviceProvider.getMyName(name);
    }
}
View Code

接着,和服务端一样,我们需要配置dubbo客户端的环境:

package com.yqn.herman.demo.com.yqn.herman.client;

import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConsumerConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Lu, Hui
 * @since 2020/1/11
 **/
@Configuration
public class ClientConfig {
    @Bean // 应用配置
    public ApplicationConfig applicationConfig() {
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("dubbo-annotation-consumer");
        Map<String, String> stringStringMap = new HashMap<String, String>();
        stringStringMap.put("qos.enable","true");
        stringStringMap.put("qos.accept.foreign.ip","false");
        stringStringMap.put("qos.port","33333");
        applicationConfig.setParameters(stringStringMap);
        return applicationConfig;
    }

    @Bean // 服务消费者配置
    public ConsumerConfig consumerConfig() {
        ConsumerConfig consumerConfig = new ConsumerConfig();
        consumerConfig.setTimeout(3000);
        return consumerConfig;
    }

    @Bean // 配置注册中心
    public RegistryConfig registryConfig() {
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setProtocol("zookeeper");
        registryConfig.setAddress("localhost:2181");
        return registryConfig;
    }
}
View Code

最后,启动客户端,调用一次服务:

package com.yqn.herman.demo.com.yqn.herman.client;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author Lu, Hui
 * @since 2020/1/11
 **/
@SpringBootApplication
@EnableDubbo(scanBasePackages = "com.yqn.herman.demo.com.yqn.herman.client") //需要服务注入的包,也就是consumer在的包
public class ClientStarter implements CommandLineRunner {

    private ServiceConsumer serviceConsumer;

    public static void main(String[] args) {
        SpringApplication.run(ClientStarter.class);
    }

    public ClientStarter(ServiceConsumer serviceConsumer) {
        this.serviceConsumer = serviceConsumer;
    }

    @Override //这里我实现了 CommandLineRunner 接口,用于在程序启动结束执行一次该方法
    public void run(String... args) throws Exception {
        serviceConsumer.call("小甜甜");
    }
}
View Code

可以看到,服务端接收到了请求:

到这里,我们就算是入门了,可以自己写一个 Hello Word 级别的dubbo例子了。如果有任何问题,写在评论区,我们一起讨论。

猜你喜欢

转载自www.cnblogs.com/hermanlife/p/12180344.html