Dubbo高级特性及SpringCloud整合Dubbo

  • Dubbo高级特性
  • 1、超时与重试
  • 2、启动检查
  • 3、多版本
  • 4、负载均衡
  • SpringCloud整合Dubbo
  • 1、功能概述
  • 2、入门案例
  • 2.1、抽取接口
  • 2.2、项目依赖
  • 2.3、服务提供者
  • 2.4、服务消费者


Dubbo高级特性

1、超时与重试

服务消费者在调用服务提供者的时候发生了阻塞、等待的情形,这个时候,服务消费者会一直等待下去。

在某个峰值时刻,大量的请求都在同时请求服务消费者,会造成线程的大量堆积,势必会造成雪崩。

  • dubbo 利用超时机制来解决这个问题(使用timeout属性配置超时时间,默认值1000,单位毫秒)
  • 若超时时间较短,当网络波动时请求就会失败,Dubbo通过重试机制避免此类问题的发生

user-consumer模块中添加配置信息

dubbo:
  registry:
    address: nacos://127.0.0.1:8848
  consumer:
    timeout: 3000
    retries: 0

2、启动检查

为了保障服务的正常可用,Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dz5YyMxD-1668472434735)(assets/image-20210727124027308.png)]

在正式环境这是很有必要的一项配置,可以保证整个调用链路的平稳运行

在开发时,往往会存在没有提供者的情况。由于启动检查的原因,可能导致开发测试出现问题

可以通过check=false关闭

user-consumer模块中添加配置信息

dubbo:
  registry:
    address: nacos://127.0.0.1:8848
  consumer:
    check: false

3、多版本

灰度发布:当出现新功能时,会让一部分用户先使用新功能,用户反馈没问题时,再将所有用户迁移到新功能。

Dubbo提供了提供者多版本的支持,平滑处理项目功能升级部署

(1)user-provider定义新的服务实现类UserServiceImpl2,指定版本

@DubboService(version = “2.0.0”)
public class UserServiceImpl2 implements UserService {
    …………
}

(2)user-consumer消费者调用时,指定版本调用

@RestController
@RequestMapping("/user")
public class UserController {
    //引用远程服务
    @DubboReference(version = "2.0.0")
    private UserService userService;    
    ………
}

4、负载均衡

在集群部署时,Dubbo提供了4种负载均衡策略,帮助消费者找到最优提供者并调用

  • Random :按权重随机,默认值。按权重设置随机概率。
  • RoundRobin :按权重轮询
  • LeastActive:最少活跃调用数,相同活跃数的随机。
  • ConsistentHash:一致性 Hash,相同参数的请求总是发到同一提供者。
@RestController
@RequestMapping("/user")
public class UserController {
    //引用远程服务
    @DubboReference(loadbalance = "roundrobin")
    private UserService userService;
}

SpringCloud整合Dubbo

通常来说,RPC协议比REST具有更好的性能。很多开发人员希望享受Spring Cloud的生态,同时有兼顾PRC的效率的效率。SpringCloud Alibaba很好的解决了这个问题。

1、功能概述

将Dubbo集成至SpringCloud主要是替换Ribbo或者Feign实现远程调用。加入Dubbo后,整体的架构如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xy6KMgn5-1668472434736)(assets/image-20210724222206792.png)]

2、入门案例

2.1、抽取接口

定义接口模块dubbo-api,并将UserService接口抽取到此模块下

package cn.jpig.dubbo.api;


import cn.jpig.dubbo.domain.User;

public interface UserService {

    User queryById(Long id);
}
2.2、项目依赖

父工程加入SpringCloud Alibaba依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
    <version>2.2.5.RELEASE</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

消费者和提供者引入nacos注册中心和Dubbo依赖

<!--nacos注册中心的依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

<!--springcloud alibaba dubbo依赖   -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>

<dependency>
    <groupId>cn.jpig</groupId>
    <artifactId>dubbo-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
2.3、服务提供者

修改UserService实现UserApi接口。并使用@DubboService注解替换@Service对外暴露dubbo服务

package cn.jpig.user.service;

import cn.jpig.dubbo.api.UserService;
import cn.jpig.dubbo.domain.User;
import cn.jpig.user.mapper.UserMapper;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;

@DubboService
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    public User queryById(Long id) {
        return userMapper.findById(id);
    }
}

在application.yml中添加配置

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/dubbo-demo?useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
  application:
    name: user-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
#配置dubbo,注册中心,暴露的端口和协议,dubbo注解的包扫描
dubbo:
  protocol:
    name: dubbo
    port: 20881
  registry:
    address: spring-cloud://localhost   #使用SpringCloud中的注册中心
  scan:
    base-packages: cn.jpig.user.service  #dubbo中包扫描
2.4、服务消费者

在OrderController中引入dubbo服务。调用UserService查询用户

package cn.jpig.order.controller;

import cn.jpig.dubbo.api.UserService;
import cn.jpig.dubbo.domain.Order;
import cn.jpig.dubbo.domain.User;
import cn.jpig.order.service.OrderService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("order")
public class OrderController {

    @Autowired
    private OrderService orderService;

    @DubboReference
    private UserService userService;

    @GetMapping("{orderId}")
    public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {
        //根据id查询订单
        Order order = orderService.queryOrderById(orderId);
        //获取用户id
        Long userId = order.getUserId();
        //查询用户
        User user = userService.queryById(userId);
        //设置用户对象
        order.setUser(user);
        // 根据id查询订单并返回
        return order;
    }
}

在Order-service的模块中添加dubbo配置