热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Springboot整合dubbo搭建基本的消费、提供和负载均衡

文章目录1.确定接口2.创建提供者2.1pom配置2.2dubbo配置文件2.3application.properties2.4mybatis相关2.4.1配置UserMappe

文章目录

    • 1.确定接口
    • 2.创建提供者
      • 2.1 pom配置
      • 2.2dubbo配置文件
      • 2.3 application.properties
      • 2.4 mybatis相关
        • 2.4.1 配置UserMapper.xml
        • 2.4.2 配置UserMapper接口
        • 2.4.3 实现UserService接口
      • 2.5 让dubbo配置生效
      • 2.6 实现Springboot application
    • 3.创建消费者
      • 3.1 pom依赖
      • 3.2 dubbo配置
        • 3.2.1 dubbo.properties
        • 3.2.2 dubbo-consumer.xml
        • 3.2.3 dubbo配置生效
      • 3.3 web创建
    • 4.启动测试

 

1.确定接口

新建一个springboot项目,什么模块都不用选,然后里面新建entity实体类和service接口。
如下图:
Springboot整合dubbo搭建基本的消费、提供和负载均衡
User.java如下,这里需要注意的是要实现序列化接口。

public class User implements Serializable{
    private Long id;

    private String email;

    private String nickName;

    private String password;

    private String regTime;

    private String userName;

    public Long getId() {
        return id;
    }

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

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email == null ? null : email.trim();
    }

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName == null ? null : nickName.trim();
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password == null ? null : password.trim();
    }

    public String getRegTime() {
        return regTime;
    }

    public void setRegTime(String regTime) {
        this.regTime = regTime == null ? null : regTime.trim();
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName == null ? null : userName.trim();
    }
}

UserService.java如下:

public interface UserService {

    int deleteByPrimaryKey(Long id);

    int insert(User record);

    User selectByPrimaryKey(Long id);

    List selectAll();

    int updateByPrimaryKey(User record);

    Map addMethod();
}

 

2.创建提供者

因为要实现负载均衡,这里就需要创建两个提供者。这里使用的是dubbo传统的配置方式:xml。现在dubbo已经支持注解方式,不过个人更偏向于xml配置。
创建两个Springboot项目:Provider和ProviderB。Provider和ProviderB基本配置和代码都一样,除了一个协议端口不一样。这里就记录Provider的配置方式。

2.1 pom配置

因为是用xml方式,在springboot项目里就引入最干净的dubbo依赖库。如果你是用注解的方式,需要引入springboot-dubbo的依赖库,该库在dubbo基础上做了springboot适配。

	
		
			org.springframework.boot
			spring-boot-starter
		

		
			org.springframework.boot
			spring-boot-starter-test
			test
		

		
			com.alibaba
			dubbo
			2.6.4
			
				
					org.springframework
					spring
				
			
		

		
			org.apache.zookeeper
			zookeeper
			3.4.12
		
		
			
			
			
		
		
			org.apache.curator
			curator-recipes
			4.0.0
			
				
					org.apache.zookeeper
					zookeeper
				
			
		

		
			mysql
			mysql-connector-java
			runtime
		

		
			org.mybatis.spring.boot
			mybatis-spring-boot-starter
			1.3.2
		

		
			com.alibaba
			druid-spring-boot-starter
			1.1.10
		
	

 

 

这里不需要使用引入web依赖,因为只提供接口服务。然后需要引入mybatis、mysql模块(这两个在初始化springboot时勾选引入)。再加上dubbo,排除掉它自带的sping库,防止冲突。引入zookeeper库,zookeeper客户端依赖库curator-recipes(排除冲突,去除zookeeper库),再引入druid数据库连接池。

2.2dubbo配置文件

通过xml方式配置,在resources下新建一个dubbo文件夹,然后创建两个文件:dubbo.properties和dubbo-provider.xml,如下图:
Springboot整合dubbo搭建基本的消费、提供和负载均衡
dubbo.properties写一些配置参数,

dubbo.application.name=dubbo-provider
dubbo.registry.protocol=zookeeper
dubbo.registry.address1=172.16.30.100:2181
dubbo.registry.address2=172.16.30.101:2181
dubbo.registry.address3=172.16.30.101:2181
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880

 

dubbo-provider.xml设置提供方名称,注册服务中心,配置协议,暴露服务:




    
    

    
    

    
    

    

 

这里需要配置一个参数loadbalance="random",用来设定负载均衡策略。这里设置是Random,随机的。
还有其他三种策略,参考官网:http://dubbo.apache.org/zh-cn/docs/user/demos/loadbalance.html

2.3 application.properties

这里只要配置数据库访问相关的参数就行。这里也贴一下吧

spring.datasource.name=datasource
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#监控统计拦截的filters
spring.datasource.druid.filters=stat
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=true&useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=root
#配置初始化大小/最小/最大
spring.datasource.druid.initial-size=1
spring.datasource.druid.min-idle=1
spring.datasource.druid.max-active=20
#获取连接等待超时时间
spring.datasource.druid.max-wait=60000
#间隔多久进行一次检测,检测需要关闭的空闲连接
spring.datasource.druid.time-between-eviction-runs-millis=60000
#一个连接在池中最小生存的时间
spring.datasource.druid.min-evictable-idle-time-millis=300000
spring.datasource.druid.validation-query=SELECT 1
spring.datasource.druid.test-while-idle=true
spring.datasource.druid.test-on-borrow=false
spring.datasource.druid.test-on-return=false
#打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为false
spring.datasource.druid.pool-prepared-statements=false
spring.datasource.druid.max-pool-prepared-statement-per-connection-size=20

#映射方式 配置下面这个就行了
#pojo类所在包路径
mybatis.type-aliases-package=com.steven.xmldubbo.entity

#xml方式
#xml文件所在路径
mybatis.mapper-locatiOns=classpath:mybatis/mapper/*.xml
mybatis.config-location=classpath:mybatis/mybatis-config.xml

 

2.4 mybatis相关

2.4.1 配置UserMapper.xml



  
    
    
    
    
    
    
  
  
    delete from user
    where id = #{id,jdbcType=BIGINT}
  
  
    insert into user (id, email, nick_name, 
      password, reg_time, user_name
      )
    values (#{id,jdbcType=BIGINT}, #{email,jdbcType=VARCHAR}, #{nickName,jdbcType=VARCHAR}, 
      #{password,jdbcType=VARCHAR}, #{regTime,jdbcType=VARCHAR}, #{userName,jdbcType=VARCHAR}
      )
  
  
    update user
    set email = #{email,jdbcType=VARCHAR},
      nick_name = #{nickName,jdbcType=VARCHAR},
      password = #{password,jdbcType=VARCHAR},
      reg_time = #{regTime,jdbcType=VARCHAR},
      user_name = #{userName,jdbcType=VARCHAR}
    where id = #{id,jdbcType=BIGINT}
  
  
  

 

2.4.2 配置UserMapper接口

在项目包下创建dao文件夹,然后创建UserMapper.java

@Repository
public interface UserMapper {
    int deleteByPrimaryKey(Long id);

    int insert(User record);

    User selectByPrimaryKey(Long id);

    List selectAll();

    int updateByPrimaryKey(User record);
}

 

2.4.3 实现UserService接口

包下创建service文件夹,再创建impl文件夹,然后创建UserServiceImpl,实现UserService接口。
这里需要配置项目Provider依赖Interface,然后就找得到Interface里的UserService了

@Service
public class UserServiceImpl implements UserService{

    private Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private UserMapper userMapper;

    @Override
    public int deleteByPrimaryKey(Long id) {
        return userMapper.deleteByPrimaryKey(id);
    }

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

    /**
     * 增加调用方基本信息
     * @param id
     * @return
     */
    @Override
    public User selectByPrimaryKey(Long id) {
        // 本端是否为提供端,这里会返回true
        boolean isProviderSide = RpcContext.getContext().isProviderSide();
        // 获取调用方IP地址
        String clientIp = RpcContext.getContext().getRemoteHost();
        // 获取当前服务配置信息,所有配置信息都将转换为URL的参数
        String url = RpcContext.getContext().getUrl().toFullString();

        logger.info("{} {} {}", isProviderSide, clientIp, url);
        return userMapper.selectByPrimaryKey(id);
    }

    @Override
    public List selectAll() {
        return userMapper.selectAll();
    }

    @Override
    public int updateByPrimaryKey(User record) {
        return userMapper.updateByPrimaryKey(record);
    }

    /**
     * 接口新增一个方法测试
     * @return
     */
    @Override
    public Map addMethod() {
        Map result = Maps.newHashMap();
        result.put("attachment", true);
        String count = RpcContext.getContext().getAttachment("count");
        result.put("count", count);
        return result;
    }
}

 

2.5 让dubbo配置生效

在项目包下新建一个config文件夹,创建DubboConfig.java

/**
 * com.steven.xmldubbo.config
 * Created by ZhiLiSteven
 * Date 2018/10/30
 */
@Configuration
@PropertySource("classpath:dubbo/dubbo.properties")
@ImportResource({"classpath:dubbo/*.xml"})
public class DubboConfig {
}

 

2.6 实现Springboot application

因为Provider不是web项目,所以启动方式要调整。并且为防止它启动main之后,因为不是以web方式启动,直接退出,需要增加一个阻塞:

@SpringBootApplication
@MapperScan("com.steven.xmldubbo.dao")
public class XmldubboApplication implements CommandLineRunner{

	private Logger logger = LoggerFactory.getLogger(XmldubboApplication.class);

	@Bean
	public CountDownLatch countDownLatch() {
		return new CountDownLatch(1);
	}

	public static void main(String[] args) throws InterruptedException {
		ApplicationContext ctx = new SpringApplicationBuilder(XmldubboApplication.class)
				.web(WebApplicationType.NONE)//非web项目
				.run(args);
//		SpringApplication.run(XmldubboApplication.class, args);

		CountDownLatch countDownLatch = ctx.getBean(CountDownLatch.class);
		countDownLatch.await();
	}

	@Override
	public void run(String... args) throws Exception {
		logger.info("Dubbo Provider start now.................");
	}
}

 

至此,提供方搭建完成。
然后再新建一个ProviderB,其他都一样,唯一区别就是项目名不一样和dubbo.properties一个参数不一样。
dubbo.protocol.port=20881
这里ProviderB改成20881
然后,在接口实现的一个方法里增加一个参数

    /**
     * 接口新增一个方法测试
     * @return
     */
    @Override
    public Map addMethod() {
        Map result = Maps.newHashMap();
        result.put("attachment", true);
        String count = RpcContext.getContext().getAttachment("count");
        result.put("count", count);
        //区别Provider和ProviderB,这里增加一个参数
        result.put("more", "providerB");
        return result;
    }

 

3.创建消费者

新建spingboot项目Consume,初始化时,勾选web就可以了。

3.1 pom依赖

然后项目依赖dubbo库,zookeeper库,curator-recipes这几个,和Provider一样。

	
		
			org.springframework.boot
			spring-boot-starter-web
		

		
			org.springframework.boot
			spring-boot-starter-test
			test
		

		
			com.alibaba
			dubbo
			2.6.4
			
				
					org.springframework
					spring
				
			
		

		
			org.apache.zookeeper
			zookeeper
			3.4.12
		
		
		
		
		
		
		
		
			org.apache.curator
			curator-recipes
			4.0.0
			
				
					org.apache.zookeeper
					zookeeper
				
			
		
	

 

项目结构如下图:
Springboot整合dubbo搭建基本的消费、提供和负载均衡

3.2 dubbo配置

配置和Provider差不多,在resources下新建dubbo文件夹,然后新建dubbo.properties和dubbo-consumer.xml

3.2.1 dubbo.properties
dubbo.application.name=dubbo-consumer
dubbo.registry.protocol=zookeeper
dubbo.registry.address1=172.16.30.100:2181
dubbo.registry.address2=172.16.30.101:2181
dubbo.registry.address3=172.16.30.102:2181

 

3.2.2 dubbo-consumer.xml

设置消费方名称,注册中心,调用接口服务




    
    

    
    

    

    

 

3.2.3 dubbo配置生效

项目包下创建config文件夹,创建DubboConfig.java

/**
 * com.steven.xmldubbo.config
 * Created by ZhiLiSteven
 * Date 2018/10/30
 */
@Configuration
@PropertySource("classpath:dubbo/dubbo.properties")
@ImportResource({"classpath:dubbo/*.xml"})
public class DubboConfig {
}

 

3.3 web创建

创建一个UserController.java

/**
 * com.steven.xmldubbo.web
 * Created by ZhiLiSteven
 * Date 2018/10/30
 */
@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("user")
    public Map user(String id) {
        Map result = new HashMap<>();
        try {
            result.put("user", userService.selectByPrimaryKey(Long.parseLong(id)));
            result.put("type", "200");
            result.put("content", "success");
        } catch (Exception e) {
            e.printStackTrace();
            result.put("type", "500");
            result.put("content", e.getMessage());
        }
        return result;
    }

    @GetMapping("allUsers")
    public Map allUsers() {
        Map result = new HashMap<>();
        try {
            result.put("users", userService.selectAll());
            result.put("type", "200");
            result.put("content", "success");
        } catch (Exception e) {
            e.printStackTrace();
            result.put("type", "500");
            result.put("content", e.getMessage());
        }
        return result;
    }

    /**
     * 回声测试
     * @return
     */
    @GetMapping("echoTest")
    public Map echoTest() {
        // 所有服务自动实现 EchoService 接口
        EchoService echoService = (EchoService) userService;
        // 回声测试可用性
        String status = (String) echoService.$echo("OK");
        Map result = Maps.newHashMap();
        result.put("status", status);
        return result;
    }

    /**
     * 获取上下文信息
     */
    @GetMapping("rpcContext")
    public Map rpcContext() {
        // 要先请求一次
        userService.selectAll();
        // 本端是否为消费端
        boolean isCOnsumerSide= RpcContext.getContext().isConsumerSide();
        // 获取最后一次调用的提供方IP地址
        String serverIp = RpcContext.getContext().getRemoteHost();
        // 获取当前服务配置信息,所有配置信息都将转换为URL的参数
        String application = RpcContext.getContext().getUrl().getParameter("application");

        Map result = Maps.newHashMap();
        result.put("isConsumerSide", isConsumerSide);
        result.put("serverIp", serverIp);
        result.put("application", application);

        return result;
    }

    private int count = 0;
    /**
     * 隐式参数
     *
     */
    @GetMapping("attachment")
    public Map attachment() {
        if (++count%2 != 0) {
            // 隐式传参,后面的远程调用都会隐式将这些参数发送到服务器端,类似COOKIE,用于框架集成,不建议常规业务使用
            RpcContext.getContext().setAttachment("count", count+"");
        }
        return userService.addMethod();
    }
}

 

然后application.properties 设定一个端口
server.port=8882

至此,消费方也创建好了。

4.启动测试

启动两个提供者Provider,ProviderB项目,然后启动Consume项目

调用http://localhost:8882/allUsers
{“type”:“200”,“users”:[{“id”:9,“email”:“bb”,“nickName”:“bb123456”,“password”:“bb@126.com”,“regTime”:“2018年10月24日 下午02时03分53秒”,“userName”:“bb2”},{“id”:10,“email”:“cc”,“nickName”:“cc123456”,“password”:“cc@126.com”,“regTime”:“2018年10月24日 下午02时03分53秒”,“userName”:“cc3”},{“id”:11,“email”:“steven@126.com”,“nickName”:“steven”,“password”:“123456”,“regTime”:“2018年10月24日 下午02时06分57秒”,“userName”:“steven”},{“id”:12,“email”:“Liz@126.com”,“nickName”:“Liz”,“password”:“123321”,“regTime”:“2018年10月24日 下午02时06分57秒”,“userName”:“Liz”},{“id”:13,“email”:“HanHan@126.com”,“nickName”:“HanHan”,“password”:“654321”,“regTime”:“2018年10月24日 下午02时06分57秒”,“userName”:“HanHan”},{“id”:15,“email”:“YaoYao@126.com”,“nickName”:“YaoYao”,“password”:“654321”,“regTime”:“2018-01-01”,“userName”:“YaoYao”}],“content”:“success”}

调用http://localhost:8882/attachment(该接口测试负载均衡)
分别得到两种类型结果:
{“attachment”:true,“count”:“1”}

{“attachment”:true,“more”:“providerB”,“count”:null}

这两个结果随机出现。

至此,搭建测试完成!


推荐阅读
author-avatar
傲慢的寒风呼啸_539
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有