springboot+dubbo实现一个简单的RPC

搭建一个基于spingboot+dubbo的“用户Rpc服务”

  • 环境配置

jdk1.8、maven3.5、zookeeper3.4

  • maven模块

user-api : 服务接口, 定义服务接口和方法, 模块会打成jar包被服务实现者和调用者依赖

user-provider : 服务实现者, 实现服务接口和方法, 会被集群部署.

user-consumer : 服务调用者, 不止一个, 比如会员、积分等需要RPC调用用户服务的独立系统

  • user-api

pom文件

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

java类

1) Rpc返回错误枚举

package com.wx.rpc;

/**
 * PRC返回错误码枚举
 */
public enum RpcResCodeEnum {

    SUCCESS("0000", "成功"),
    REQUIRED_PARAM_IS_EMPTY("0001", "必要的请求参数为空"),

    USER_DISABLED("1001", "用户被冻结"),
    //其他返回码...

    UNKNOWN_ERROR("9999", "未知异常");

    String code;
    String message;

    RpcResCodeEnum(String code, String message) {
        this.code = code;
        this.message = message;
    }

    public String getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }
}

2) Rpc返回结果

package com.wx.rpc;

import java.io.Serializable;

/**
 * RPC返回结果对象
 *
 * @param <T>
 */
public class RpcResponse<T> implements Serializable {

    private String code;
    private String message;
    private T data;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    /**
     * 返回成功
     *
     * @return
     */
    public static RpcResponse succeed() {
        RpcResponse response = new RpcResponse();
        response.setCode(RpcResCodeEnum.SUCCESS.getCode());
        response.setMessage(RpcResCodeEnum.SUCCESS.getMessage());
        return response;
    }

    /**
     * 返回成功,带实体data
     *
     * @param data
     * @return
     */
    public static RpcResponse succeed(Object data) {
        RpcResponse response = new RpcResponse();
        response.setCode(RpcResCodeEnum.SUCCESS.getCode());
        response.setMessage(RpcResCodeEnum.SUCCESS.getMessage());
        response.setData(data);
        return response;
    }

    /**
     * 返回失败
     *
     * @param rpcCodeEnum 错误枚举
     * @return
     */
    public static RpcResponse fail(RpcResCodeEnum rpcCodeEnum) {
        RpcResponse response = new RpcResponse();
        response.setCode(rpcCodeEnum.getCode());
        response.setMessage(rpcCodeEnum.getMessage());
        return response;
    }

}

3) 数据传输对象

package com.wx.rpc;

import java.io.Serializable;

/**
 * 用户DTO
 */
public class UserDto implements Serializable{

    private String id;
    private String username;
    private String password;

    //略
}

4 ) Rpc接口

package com.wx.rpc;

public interface UserService {

    /**
     * 保存用户
     * @param userDto
     * @return
     */
    RpcResponse saveUser(UserDto userDto);

    /**
     * 查询用户
     * @param id
     * @return
     */
    RpcResponse getUser(String id);

}

打包并安装接口jar到本地仓库

mvn clean install -Dmaven.skip.test=true
  • user-provider

pom文件

<?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.wx</groupId>
    <artifactId>user-provider</artifactId>
    <version>1.0-SNAPSHOT</version>

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

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

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring</artifactId>
                </exclusion>
            </exclusions>
            <version>2.5.3</version>
        </dependency>

        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.1</version>
        </dependency>

        <!--服务接口-->
        <dependency>
            <groupId>com.wx</groupId>
            <artifactId>user-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

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

</project>

java类和resource文件

1) 加载dubbo配置

package com.wx.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

/**
 * dubbo服务实例化和注册
 */
@Configuration
@ImportResource("classpath:dubbo-provider.xml")
public class DubboProviderConfig {

}

2) 实现服务接口

package com.wx.rpc.impl;

import com.wx.rpc.RpcResCodeEnum;
import com.wx.rpc.RpcResponse;
import com.wx.rpc.UserDto;
import com.wx.rpc.UserService;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

/**
 * 服务接口实现类
 */
@Service
public class UserServiceImpl implements UserService {
    @Override
    public RpcResponse saveUser(UserDto userDto) {
        //参数为空校验
        if (StringUtils.isEmpty(userDto.getUsername())
                || StringUtils.isEmpty(userDto.getPassword())) {
            return RpcResponse.fail(RpcResCodeEnum.REQUIRED_PARAM_IS_EMPTY);
        }
        //@TODO: insert数据库
        //返回保存成功
        return RpcResponse.succeed();
    }

    @Override
    public RpcResponse getUser(String id) {
        //模拟查询
        UserDto userDto = new UserDto();
        userDto.setId(id);
        userDto.setUsername("dubbo");
        //返回查询结果
        return RpcResponse.succeed(userDto);
    }
}

3) 启动类

package com.wx;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * boot启动类
 */
@SpringBootApplication
public class StartUserProvider {
    public static void main(String[] args) {
        SpringApplication.run(StartUserProvider.class, args);
    }
}

4) properties文件

#web端口
server.port=8088
#zookeeper地址
zookeeper.address=127.0.0.1:2181
#dubbo服务监听端口
dubbo.port=20880

5) dubbo服务的spring配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <dubbo:application name="user-provider"/>
    <!--注册协议和注册地址-->
    <dubbo:registry protocol="zookeeper" address="${zookeeper.address}"/>
    <!--服务监听端口-->
    <dubbo:protocol name="dubbo" port="${dubbo.port}"/>
    <!--服务接口和实现类-->
    <dubbo:service interface="com.wx.rpc.UserService" ref="userServiceImpl"/>
</beans>

打jar包

mvn clean package -Dmaven.skip.test=true

本地集群部署3个服务节点

java -jar ./target/user-provider-1.0-SNAPSHOT.jar --server.port=8088 --dubbo.port=20880
java -jar ./target/user-provider-1.0-SNAPSHOT.jar --server.port=8090 --dubbo.port=20881
java -jar ./target/user-provider-1.0-SNAPSHOT.jar --server.port=8092 --dubbo.port=20882

通过dubbo-admin查看服务注册情况

  • user-consumer

pom文件

<?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.wx</groupId>
    <artifactId>user-consumer</artifactId>
    <version>1.0-SNAPSHOT</version>

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

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

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring</artifactId>
                </exclusion>
            </exclusions>
            <version>2.5.3</version>
        </dependency>

        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.1</version>
        </dependency>

        <!--服务接口-->
        <dependency>
            <groupId>com.wx</groupId>
            <artifactId>user-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

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

java类型和resource文件

1) 加载dubbo配置

package com.wx.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

/**
 * 加载dubbo消费配置
 */
@Configuration
@ImportResource("classpath:dubbo-consumer.xml")
public class DubboConsumerConfig {

}

2)  测试Controller

package com.wx.controller;

import com.wx.rpc.UserDto;
import com.wx.rpc.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 用户Controller
 */
@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("/save")
    @ResponseBody
    public Object saveUser(UserDto userDto){
        return userService.saveUser(userDto);
    }

    @RequestMapping("/user")
    @ResponseBody
    public Object getUser(String id){
        return userService.getUser(id);
    }
}

3) 启动类

package com.wx;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * boot启动类
 */
@SpringBootApplication
public class StartConsumer {
    public static void main(String[] args) {
        SpringApplication.run(StartConsumer.class, args);
    }
}

4) properties文件

#web端口
server.port=8000
#zookeeper地址
zookeeper.address=127.0.0.1:2181

5) dubbo消费的spring配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <dubbo:application name="user-consumer"/>
    <!--注册协议和注册地址-->
    <dubbo:registry protocol="zookeeper" address="${zookeeper.address}"/>
    <!--引用服务接口-->
    <dubbo:reference interface="com.wx.rpc.UserService" id="userService"/>
</beans>

打包并启动user-consumer, 通过UserController来测试整个RPC

http://127.0.0.1:8000/user/save?username=wx

{
    "code": "0001",
    "message": "必要的请求参数为空",
    "data": null
}

http://127.0.0.1:8000/user/save?username=wx&password=123456

{
    "code": "0000",
    "message": "成功",
    "data": null
}

http://127.0.0.1:8000/user/get?id=1

{
    "code": "0000",
    "message": "成功",
    "data": {
        "id": "1",
        "username": "dubbo",
        "password": null
    }
}

猜你喜欢

转载自my.oschina.net/wangxu3655/blog/1811908