Dubbo

4 篇文章 0 订阅
1 篇文章 0 订阅

Dubbo知识点

1、概念

Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,以及 SOA 服务治理方案。

通信机制:使用netty通信服务进行通信,netty是基于nio字符缓冲流来实现。

2、架构图

架构图

节点和角色说明

3、工作原理

具体调用流程如下:

(1)服务器负责启动,加载,运行服务提供者。

(2)服务提供者在启动时,向注册中心注册自己所提供的服务。

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

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

(5)服务消费者从提供的服务列表中,基于软负载均衡算法,选一台提供者进行调用,如果失败,则选择另一台调用。

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

4、zookeeper环境搭建

可参照这篇文章进行部署安装:

https://blog.csdn.net/ITWUYI/article/details/109196253

5、Dubbo控制台admin环境搭建

(1) 下载源码打包

去github上下载相关代码,打包成war。

利用maven命令打包:

mvn install -Dmaven.test.skip=true

命令执行成功结束后,在 dubbo-admin 目录下会生成target文件夹,文件夹下会出现一个war包。

若未成功生成war包,可进入dubbo-admin目录,执行命令mvn package -Dmaven.test.skip ,把dubbo-admin打成war包。

(2) 解压

将上面的dubbo的war打包文件复制到centos 7 服务器tomcat下webapps/ROOT目录(注:最好先删除ROOT下已有文件,否则在dubbo管理页面会报错IllegalAccessError)。然后解压,在webapps/ROOT/WEB-INF下,有一个dubbo.properties文件,里面配置指向 Zookeeper server的地址(使用的是Zookeeper 的注册中心),要修改成相应zookeeper的ip地址和端口。

(3)启动tomcat

到tomcat目录的bin目录下

运行tomcat

./startup.sh

关闭tomcat服务

./shutdown.sh

(4)访问dubbo管理控制中心

http://192.168.13.21:8080/dubbo-admin

用户名和密码:root

完毕。

6、代码实现

下面用一个简单的项目讲解dubbo+springboot是如何集成和如何运行协作的?

api是服务提供者的接口API,最普通的maven项目。

dubbo-provider是所谓的服务提供者,springboot项目。

dubbo-consumer是服务消费者,springboot项目。
api

provider

consumer
(1)新建子模块api,groupId为com.itwuyi,artifactId为api。

这个模块用来存放微服务中所有的实体类,以及所有的服务提供者提供的服务接口。它使用普通的maven项目。

(一)pom.xml

<?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.itwuyi</groupId>
    <artifactId>api</artifactId>
    <version>1.0-SNAPSHOT</version>
</project>

(二)新建包model,用于存放所有的model,包下新建实体类User:

package model;

import java.io.Serializable;

public class User implements Serializable {
    private Integer id;
    private String username;
    private String password;
    private String tel;
    private String address;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

(三)新建包service,用于存放所有服务提供者提供的服务接口,包下新建UserService:

package service;

import model.User;

public interface UserService {
    User findUserById(Integer id);
}

(四)使用maven install打包为jar安装到仓库。

(2)新建子模块dubbo-provider,springboot项目,作为服务提供者。groupId为com.itwuyi,artifactId为dubbo-provider。

(一)pom.xml

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.itwuyi</groupId>
    <artifactId>dubbo-provider</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>dubbo-provider</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.itwuyi</groupId>
            <artifactId>api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <!-- dubbo的依赖 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.6</version>
        </dependency>

        <!-- zk的依赖 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-dependencies-zookeeper</artifactId>
            <version>2.7.6</version>
            <type>pom</type>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

使用zk作为注册中心、配置管理中心,这里添加的zk依赖是作为zkCli。

zookeeper的依赖要用去掉slf4j部分,因为spring-boot-strat已经包含了slf4j,如果不去掉会报错:(slf4j绑定了多个jar包中的Logger)。

dubbo可以使用多种注册中心,比如zookeeper、redis等,上面的zookeeper依赖只包含以zookeeper作为注册中心的依赖,服务只能以zookeeper作为注册中心。

(二)新建包service,包下新建类UserServiceImpl实现服务接口UserService。

package com.itwuyi.dubboprovider.service;
import model.User;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.stereotype.Component;
import service.UserService;

//此处的@Service是dubbo下的注解,不是spring的注解
@Service
@Component
public class UserServiceImpl implements UserService {
    @Override
    public User findUserById(Integer id) {
        User user = new User();
        user.setId(id);
        user.setUsername("itwuyi");
        return user;
    }
}

(三)配置文件

连接到zkServer的时间开销大,如果不将注册的超时时间设置大一些,可能会报错:zookeeper not connected,时间不够,还没连上就超时取消了。

另外,注意查看是否搭配了zookeeper集群(如果只启动了一台,也会出现这个现象)。

#如果指定了spring应用名称,可以缺省dubbo的应用名称,这2个至少要配置1个,缺省dubbo的应用名称时默认值是spring的应用名称
#dubbo.application.name=dubbo-service
spring.application.name=dubbo-provider

#注册中心地址
dubbo.registry.address=zookeeper://192.168.13.21:2181
#端口号可以写在address中,也可以单独写。实质是从address中获取的port是null,后面设置的port覆盖了null
#dubbo.registry.port=2181

#指定dubbo使用的协议、端口
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880

#指定注册到zk上超时时间,ms
dubbo.registry.timeout=12000
dubbo.config-center.timeout=12000

#指定实现服务(提供服务)的包
dubbo.scan.base-packages=com.itwuyi.dubboprovider.service

(四)springboot启动类

package com.itwuyi.dubboprovider;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableDubbo  //会扫描所有的包,从中找出dubbo的@Service标注的类
// @DubboComponentScan(basePackages = "com.itwuyi.dubboprovider.service")  //只扫描指定的包
public class DubboProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(DubboProviderApplication.class, args);
    }
}

(3)新建子模块dubbo-consumer,springboot web项目,作为服务消费者。groupId为com.itwuyi,artifactId为dubbo-consumer

(一)pom.xml

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.itwuyi</groupId>
    <artifactId>dubbo-consumer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>dubbo-consumer</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.itwuyi</groupId>
            <artifactId>api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- dubbo的依赖 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.6</version>
        </dependency>

        <!-- zk的依赖 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-dependencies-zookeeper</artifactId>
            <version>2.7.6</version>
            <type>pom</type>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

(二)新建包controller,包下新建类OrderController来调用服务。

package com.itwuyi.dubboconsumer.controller;
import model.User;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import service.UserService;

@Controller
public class OrderController {
    @Reference//dubbo注解
    private UserService userService;
    @RequestMapping("/consumer/{id}")
    @ResponseBody
    public User getUser(@PathVariable Integer id){
        //调用服务
        System.out.println(id);
        User user= userService.findUserById(id);
        return user;
    }
}

这里的@Reference引入的包是org.apache.dubbo.config.annotation.Reference,而不是jdk自带的。

(三)配置文件

spring.application.name=dubbo-consumer
#dubbo.application.name=dubbo-consumer

#注册中心地址
dubbo.registry.address=zookeeper://192.168.13.21:2181
#dubbo.registry.port=2181

#协议、端口
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880

#连接zk的超时时间,ms
dubbo.registry.timeout=12000

#启动应用时是否检查注册中心上有没有依赖的服务,默认true
#dubbo.consumer.check=false

缺省dubbo.consumer.check配置时,默认为true,要检查。

消费者连接注册中心时,会订阅要调用的服务,如果提供该服务的服务器一台都没有,会报错,这个消费者无法启动,这样在消费者启动时就能检查到是否有可用的生产者,提前发现问题。

调试时,如果先启动消费者,后启动|未启动生产者,消费者往往启动不了,报错:创建不了xxx bean,因为 Injection of @Reference dependencies is failed ,没有生产者提供该服务。

设置为false,消费者启动时不检查,就算没有生产者提供该服务,消费者也能正常启动,只是调用该服务时会出错。

4、先启动生产者,再启动消费者

启动生产者的控制台:
启动生产者的控制台
启动消费者的控制台:
启动消费者的控制台

当一切都启动成功,去浏览器访问,结果如下所示:
执行结果

zkServer上,dubbo的根目录是/dubbo,

一个提供的服务对应一个znode,包名.服务接口名的形式,/dubbo/service.providerService

这个节点的子节点providers存储此服务的所有提供者的注册信息,子节点consumers存储订阅此服务的所有消费者的信息。

dubbo @Service标注的类所实现的接口,会自动在zkServer上创建一个对应的znode,包名.接口名的形式。

生产者实现该接口,并使用dubbo @Service标识该类是服务提供者,实现的接口就是它提供的服务;消费者使用@Reference来订阅、引用服务。

5、dubbo配置相关说明

指定注册中心

#协议、ip:port可以写在一起
dubbo.config-center.address=zookeeper://192.168.13.21:2181

#可以分开写
dubbo.registry.protocol=zookeeper

dubbo.registry.address=192.168.13.21:2181
#如果是集群,逗号分隔
dubbo.registry.address=192.168.13.21:2181,192.168.13.22:2181

设置连接到注册中心的超时时间

#这个是提供者、消费者都可以使用的
dubbo.registry.timeout=12000

#可以使用专门的
dubbo.consumer.timeout=12000
dubbo.provider.timeout=12000

7、排查问题

(1)springboot整合dubbo时,消费者调用提供者的方法时出现空指针异常?

1)提供者的实现类的@Service注解要用的是com.alibaba.dubbo.config.annotation(或者org.apache.dubbo.config.annotation)包下的。

2)提供者的实现类不能缺少**@Component**注解,这个类还是要交给spring管理的(这个地方很多人容易犯错,甚至看到有些分享者分享出来的代码都忘了加上这个注解)。

3)主程序要加上@EnableDubbo注解。

4)查看提供者的application.yml或者application.properties里面的dubbo.scan.base-packages=xxx,检查要扫描的包路径正确不正确。

后续如有更优的方法,会继续补充。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值