Dubbo 第一个应用程序

/ 分布式 / 599浏览

构建一个最基础的Dubbo程序,目的是为了快速入门,了解Dubbo的运行机制以及熟悉Dubbo项目工程结构。

准备

  1. 开发环境:JDK8、Eclipse(Idea)、SpringBoot
  2. 开发结构:遵照Dubbo官方建议,服务消费者 + API层 + 服务提供者
  3. 项目工程:dubbo-interface + dubbo-provider + dubbo-web

其中工程结构及说明如下:

工程名称说明
dubbo-interface程序接口层,主要定义:
1.模型对象(即实体类)
2.业务接口
dubbo-provider服务提供者:
需要引用接口层,并实现接口方法,配置为dubbo服务;
然后将服务对外暴露出去(通常将服务注册到注册中心),供服务消费者使用。
dubbo-web服务消费者:
需要引用接口层,配置注册中心,通过注册中心来使用接口的服务来实现业务逻辑。

创建接口层工程

接口层主要定义了对象模型、服务接口,所以可以使用Maven直接创建一个普通的Jar工程。这里使用的Idea来创建:
首先定义工程名称: alt 下一步: alt 确认无误后下一步: alt 最后点击完成即可。
工程创建好后,需要定义对象模型以及服务接口,这里以用户为例,工程结构如下: alt 创建一个User实体类:

package cn.zealon.app.user.entity;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable {

    private static final long serialVersionUID=1L;
    private String id;
    private String userId;
    private String userName;
    private Date created;

    public String getId() {
        return id;
    }

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

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public Date getCreated() {
        return created;
    }

    public void setCreated(Date created) {
        this.created = created;
    }
}

一个用户服务接口:

package cn.zealon.app.user.service;

import cn.zealon.app.user.entity.User;

public interface UserService {

    /**
     * 按userId查找一个用户
     * @param userId
     * @return
     */
    public User getUserById(String userId);

    /**
     * 修改一个用户
     * @param user
     * @return
     */
    public int updateUser(User user);
}

到这里,最基本的接口工程已经完成了。

创建服务提供者工程

创建工程

这里使用SpringBoot来构建工程,新建一个Module: alt 输入好工程名称,点击下一步: alt 这里只选择了一些必要的依赖,比如Mysql、Mybatis等等,点击下一步: alt 最后确认无误后,点击完成即可。 alt

引入Maven依赖

SpringBoot初始化里的依赖明显不够用,还需要手动的将dubbo、zookeeper等依赖引入,还有需要将接口层的依赖也加进去,如下:

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

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-tomcat</artifactId>
		<scope>provided</scope>
	</dependency>

	<!--dubbo-->
	<dependency>
		<groupId>com.alibaba.boot</groupId>
		<artifactId>dubbo-spring-boot-starter</artifactId>
		<version>0.2.0</version>
	</dependency>

	<!--zookeeper client-->
	<dependency>
		<groupId>com.101tec</groupId>
		<artifactId>zkclient</artifactId>
		<version>0.10</version>
	</dependency>

	<!-- Mybatis -->
	<dependency>
		<groupId>org.mybatis.spring.boot</groupId>
		<artifactId>mybatis-spring-boot-starter</artifactId>
		<version>1.3.2</version>
	</dependency>

	<!--阿里 Druid Spring Boot Starter依赖-->
	<dependency>
		<groupId>com.alibaba</groupId>
		<artifactId>druid-spring-boot-starter</artifactId>
		<version>1.1.10</version>
	</dependency>

	<!-- json -->
	<dependency>
		<groupId>com.alibaba</groupId>
		<artifactId>fastjson</artifactId>
		<version>1.2.43</version>
	</dependency>

	<!-- JDBC驱动 -->
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<scope>runtime</scope>
	</dependency>

	<!--接口项目依赖-->
	<dependency>
		<groupId>cn.zealon</groupId>
		<artifactId>dubbo-interface</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</dependency>

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

安装注册中心

注册中心可以选择zookeeper(当然也可以选择Multicast),这样可以初步的对dubbo注册中心机制有个理解。那么zookeeper的安装和启动就不概述了。 alt

进行配置

需要的依赖引入后,这时候我们可以进行配置了;打开applicable.yml(applicable.properties):
分别配置了数据源、dubbo注册中心、mybatis的扫描包。如下:

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://xx.xx.xx.xx:3306/biz_db?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: xxxx

#dubbo配置
dubbo:
  application:
    name: dubbo-provider
    registry: zookeeper://xx.xx.xx.xx:2181

mybatis:
  mapper-locations: classpath*:mappers/*.xml

实现接口

好了,准备的差不多了,开始实现接口服务,首先创建一个mybatis的dao层接口UserMapper:

package cn.zealon.app.user.dao;

import cn.zealon.app.user.entity.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface UserMapper {

    @Insert("insert into org_user(id,userid,user_Name,created) values(#{id},#{userId},#{userName},#{created})")
    public int insert(User user);

    @Select("select id,userId,user_name userName,created from org_user where userId=#{userId} ")
    public User getUserById(String userId);
}

然后创建接口实现UserServiceImpl:

package cn.zealon.app.user.server.impl;

import cn.zealon.app.user.entity.User;
import cn.zealon.app.user.service.UserService;
import com.alibaba.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import cn.zealon.app.user.dao.UserMapper;
import org.springframework.stereotype.Component;

@Service
@Component
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public User getUserById(String userId) {
        return userMapper.getUserById(userId);
    }

    @Override
    public int updateUser(User user) {
        return userMapper.insert(user);
    }
}

需要注意的是,@Service注解不在是Spring里面的了,而是com.alibaba.dubbo.config.annotation包下的注解,使用@Component来做为Spring组件装配Bean。

最后在SpringBoot启动入口中,加入dubbo相关的注解:

package cn.zealon;

import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubboConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableDubboConfig
@EnableDubbo
public class DubboProviderApplication {

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

好了,这时候最基本的服务提供者工程就创建完了。 alt

创建服务消费者工程

这里说明一下,工程的创建基本同上,包括Maven依赖的引用等等,只是稍有不同(消费端主要是编写Controller层的代码,所以可能会依赖一些Thymeleaf等模板引擎,而不需要依赖Mybatis、Mysql等),这里就直接贴代码了。

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>cn.zealon</groupId>
    <artifactId>dubbo-web</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>dubbo-web</name>
    <description>dubbo-web for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

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

        <!--dubbo-->
        <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>0.2.0</version>
        </dependency>

        <!--zookeeper client-->
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.10</version>
        </dependency>

        <!-- json -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.43</version>
        </dependency>

        <!--接口项目依赖-->
        <dependency>
            <groupId>cn.zealon</groupId>
            <artifactId>dubbo-interface</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

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

application.yml:

server:
  port: 80

spring:
  application:
    name: dubbo-web

dubbo:
  application:
    name: dubbo-web
  registry:
    address: zookeeper://xx.xx.xx.xx:2181

重点是实现接口的调用,这里定义一个UserController:

package cn.zealon.app.user.controller;

import cn.zealon.app.user.entity.User;
import cn.zealon.app.user.service.UserService;
import com.alibaba.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.UUID;

@RestController
@RequestMapping("user")
public class UserController {

    @Reference
    private UserService userService;

    @RequestMapping("detail/{userId}")
    public User getUserByUserId(@PathVariable String userId){
        return userService.getUserById(userId);
    }

    @PostMapping("update")
    public Object update(User user){
        user.setId(UUID.randomUUID().toString().replace("-",""));
        user.setCreated(new Date());
        userService.updateUser(user);
        return user;
    }
}

其中@Reference注解来完成消费端的服务引用,由于我们注册中心在配置文件中配置好了,所以只要实现接口层的服务声明就可以实现服务自动发现,和使用了。

整体测试

首先启动服务提供者应用: alt 可以观察日志,看到UserService已经注册到zookeeper中了。

然后启动服务消费者应用: alt 观察日志可以看到,消费者已经成功的订阅了UserService服务,并且tomcat启动无异常,那么说明现在可以进行测试了。

测试资源地址:user/detail/{userId}
请求类型:Get
那么可以再浏览器中进行完成测试,请求如下: alt 已经成功的查询到数据结果,嗯到这里,最基本的dubbo应用就已经搭建好了。