Dubbo1.简单上手

181 阅读5分钟

Dubbo

Apache Dubbo 是一款高性能、轻量级的开源 Java 服务框架。

官方中文文档地址

特点:

  • 面向接口代理的高性能RPC调用。提供高性能的基于代理的远程调用能力,服务以接口为粒度,为开发者屏蔽远程调用底层细节。
  • 智能负载均衡。内置多种负载均衡策略,智能感知下游节点健康状况,显著减少调用延迟,提高系统吞吐量。
  • 服务自动注册与发现。支持多种注册中心服务,服务实例上下线实时感知。
  • 高度可扩展能力。遵循微内核+插件的设计原则,所有核心能力如Protocol、Transport、Serialization被设计为扩展点,平等对待内置实现和第三方实现。
  • 运行期流量调度。内置条件、脚本等路由策略,通过配置不同的路由规则,轻松实现灰度发布,同机房优先等功能。
  • 可视化的服务治理与运维。提供丰富服务治理、运维工具:随时查询服务元数据、服务健康状态及调用统计,实时下发路由策略、调整配置参数。

架构

Dubbo架构

节点角色说明

节点角色说明
Provider暴露服务的服务提供方
Consumer调用远程服务的服务消费方
Registry服务注册与发现的注册中心
Monitor统计服务的调用次数和调用时间的监控中心
Container服务运行容器

调用关系说明

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

Zookeeper

ZooKeeper 是一个面向分布式应用程序的高性能协调服务。它在一个简单的接口中公开了一些常见的服务,比如命名、组态管理、同步和组服务,这样你就不必从头开始编写它们了。您可以使用它来实现共识、组管理、领导者选举和存在协议。你可以根据自己的特殊需要,在此基础上进行构建。

疑点

zk的ZAB协议决定了不能无限扩容,选主复制恢复决定了这是一个中心化的思想

安装

  1. 下载Tar包。
  2. 解压。
  3. 配置。
  4. 启动。

下载Tar包

下载地址

选择对应的版本即可

解压

tar -zxvf turnserver-4.5.2.tar.gz

配置文件

cd apache-zookeeper-3.5.9-bin/conf/
cp zoo_sample.cfg zoo.cfg

配置文件如下

# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/tmp/zookeeper
# the port at which the clients will connect
clientPort=2181
admin.serverPort=8888
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1

相对于默认配置仅添加了admin.serverPort=8888,因为默认的8080和我本地的apollo冲突了

参数说明
tickTimezookeeper中使用的基本时间单位, 毫秒值这个时间是作为Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个tickTime 时间就会发送一个心跳。
dataDir数据目录. 可以是任意目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。
clientPort这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。

启动

./zkServer.sh start /user-data/apache-zookeeper-3.5.9-bin/conf/zoo.cfg

访问adminServer的url:

http://localhost:8888/commands

有内容就启动成功了

docker安装

当我用wsl启动zookeeper发现了一个问题,Java连接特别慢,超过了 10s,我试着用了一下docker安装,连接就正常。(其实用windows启动应该也不会慢,瞎折腾)

打开kitematic,搜索zookeeper,认准带official,点create就行了。将setting->port中2181端口的映射记录下来,这是dubbo中配置的zookeeper地址。

快速开始(Hello World)

环境说明:Windows、JDK8、SpringBoot

文档中心

common部分

依赖

 <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <dubbo.version>2.7.8</dubbo.version>
        <curator.version>2.13.0</curator.version>
        <common.version>1.0-SNAPSHOT</common.version>
        <curator-framework.version>5.1.0</curator-framework.version>
        <zookeeper.version>3.5.9</zookeeper.version>
        <logback.version>1.2.3</logback.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-spring-boot-starter</artifactId>
                <version>${dubbo.version}</version>
            </dependency>
            <dependency>
                <groupId>org.example</groupId>
                <artifactId>common</artifactId>
                <version>${common.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.curator</groupId>
                <artifactId>curator-framework</artifactId>
                <version>${curator-framework.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
                <version>${zookeeper.version}</version>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
                <version>${logback.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.curator</groupId>
                <artifactId>curator-recipes</artifactId>
                <version>${curator-framework.version}</version>
                <exclusions>
                    <exclusion>
                        <groupId>org.apache.zookeeper</groupId>
                        <artifactId>zookeeper</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    </dependencyManagement>

接口

接口定义在common模块

import java.util.concurrent.CompletableFuture;

public interface DemoService {

    String sayHello(String name);

    default CompletableFuture<String> sayHelloAsync(String name) {
        return CompletableFuture.completedFuture(sayHello(name));
    }

}

provider

依赖

    <dependencies>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
        </dependency>
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>common</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
        </dependency>
    </dependencies>

接口实现

在提供者中实现接口

@DubboService
public class DemoServiceImpl implements DemoService {

    @Override
    public String sayHello(String name) {
        return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
    }

    @Override
    public CompletableFuture<String> sayHelloAsync(String name) {
        return null;
    }

}

启动类

public class DubboProviderApplication {
    public static void main(String[] args) throws Exception {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class);
        context.start();
        System.in.read();
    }

    @Configuration
    @EnableDubbo(scanBasePackages = "com.xiayu.service_discovery.dubbo.provider")
    @PropertySource("classpath:/spring/dubbo-provider.properties")
    static class ProviderConfiguration {
        @Bean
        public RegistryConfig registryConfig() {
            RegistryConfig registryConfig = new RegistryConfig();
            registryConfig.setAddress("zookeeper://127.0.0.1:49156");
            registryConfig.setTimeout(20000);
            return registryConfig;
        }
    }
}

配置文件

resources/spring/dubbo-provider.properties的配置文件

dubbo.application.name=dubbo-demo-annotation-provider
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880

consumer

定义引用

像使用Spring一样,只不过注解不同

@Component("demoServiceComponent")
public class DemoServiceComponent implements DemoService {
    @DubboReference
    private DemoService demoService;

    @Override
    public String sayHello(String name) {
        return demoService.sayHello(name);
    }

    @Override
    public CompletableFuture<String> sayHelloAsync(String name) {
        return null;
    }
}

启动类

public class Application {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class);
        context.start();
        DemoService service = context.getBean("demoServiceComponent", DemoServiceComponent.class);
        String hello = service.sayHello("world");
        System.out.println("result :" + hello);
    }

    @Configuration
    @EnableDubbo(scanBasePackages = "com.xiayu.service_discovery.dubbo.consumer.comp")
    @PropertySource("classpath:/spring/dubbo-consumer.properties")
    @ComponentScan(value = {"com.xiayu.service_discovery.dubbo.consumer"})
    static class ConsumerConfiguration {

    }
}

配置文件

resources/spring/dubbo-provider.properties的配置文件

dubbo.application.name=dubbo-demo-annotation-consumer
dubbo.registry.address=zookeeper://127.0.0.1:49156?timeout=20000

duboo-admin

1.clone代码

git clone https://github.com/apache/dubbo-admin.git

2.更改配置文件 更改dubbo-admin-server/src/main/resources/application.properties

我就改了zookeeper的地址

admin.registry.address=zookeeper://127.0.0.1:2181
admin.config-center=zookeeper://127.0.0.1:2181
admin.metadata-report.address=zookeeper://127.0.0.1:2181

3.打包

mvn clean package -Dmaven.test.skip=true

打好的包在dubbo-admin-distribution

4.运行

java -jar dubbo-admin-0.1.jar

5.访问

默认链接

默认账号和密码都是root

总结

重点在于定义和实现Service接口:

  1. common中定义了DemoService接口
  2. provider中实现DemoService接口并添加@DubboService表示这是一个RPC接口实现
  3. consumer中定义DemoService的变量并添加@DubboReference

具体的RPC过程就交由Dubbo和Zookeeper去实现。