RPC框架:dubbo的基本使用

常见的RPC协议:

  • Dubbo协议
  • Triple协议
  • Rest协议
  • gPRC协议
  • HTTP协议
  • Redis协议
  • Hessian协议
  • WebService协议
  • Memcached协议
    具体文档:https://dubbo.apache.org/zh/docs3-v2/java-sdk/reference-manual/protocol/

注意:

  • TCP、UDP是传输层的协议,而HTTP和RPC是应用层协议。
  • HTTP:超文本传输协议,RPC:远程过程调用。HTTP诞生于90年代,RPC诞生于80年代。那么为什么有了RPC还有HTTP呢?
  • 电脑上的各种软件,如:xx管家,它们都是作为客户端(C)需要跟服务端(S)建立连接收发消息,此时可以使用自家的RPC协议,因为它们只用连接自己公司的服务器就可以了
  • 浏览器不一样,B/S架构 ,需要连接不同家的服务器

问题:

  1. 为什么了有了RPC还要有HTTP?

RPC专门负责连接自家服务器(C/S架构)或者自己微服务组件的通信

  1. 为什么有了HTTP2.0还要使用RPC?

原理上说HTTP2.0效率比RPC更好,但是很多公司自己实现的RPC已经稳定了很多年了,也就没必要更换了

  1. 区别
  • RPC要求服务提供方和服务调用方都需要使用相同的技术,要么都hessian,要么都dubbo
    而http无需关注语言的实现,只需要遵循Rest规范
  • RPC主要关注自家服务器,HTTP需要关注各家

1 Dubbo概念

Dubbo是由阿里推出的用来进行RPC的框架,主要用于分布式上,其推荐的注册中心为zookeeper,它还有自己的监控中心,不过需要我们自己配置

官网https://dubbo.apache.org/zh/

2 SpringBoot整合Dubbo

主要有三种方式:

  1. 导入dubbo-starter,在application.properties中配置属性,@Service【dubbo的,暴露服务】,@Reference引用服务,@EnableDubbo(配置包扫描)
  2. 保留dubbo.xml文件:导入dubbo-starter,使用@ImportResouce导入dubbo的配置文件
  3. 使用注解API方式,将每一个组件手动创建到容器中,每一个配置标签都对应一个Config配置类(@Bean),最后放在一个总的下面

2.1 首先本地启动一个zookeeper

①首先到conf目录下,直接复制zoo_sample.cfg,然后将名称修改为zoo.cfg
②在zk安装目录的bin目录下,直接执行zkServer.cmd即可

rpc 底层端口111能否修改 rpc协议端口号_rpc 底层端口111能否修改

2.2 创建API工程

创建一个maven工程,主要存储实体类和service接口

rpc 底层端口111能否修改 rpc协议端口号_RPC_02


①实体类

需要实现序列化,因为dubbo在RPC过程中会将数据进行序列化与反序列化

public class UserAddress implements Serializable {

    private Integer id;
    private String userAddress;
    private String userName;

    public UserAddress() {
        super();
    }

    public UserAddress(Integer id, String userAddress, String userName){
        this.id = id;
        this.userAddress = userAddress;
        this.userName = userName;
    }

    public Integer getId() {
        return id;
    }

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

    public String getUserAddress() {
        return userAddress;
    }

    public void setUserAddress(String userAddress) {
        this.userAddress = userAddress;
    }

    public String getUserName() {
        return userName;
    }

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

②接口

public interface UserService {

    /**
     * 根据id返回用户收获地址
     * @return
     */
    public List<UserAddress> getUserAddressList(String userId);
}

2.3 创建服务提供者provider

rpc 底层端口111能否修改 rpc协议端口号_RPC_03


①导入依赖

<!--引入api依赖-->
 <dependency>
     <groupId>com.zi</groupId>
     <artifactId>user-api</artifactId>
     <version>1.0-SNAPSHOT</version>
 </dependency>

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

dubbo的0.2.0版本帮我们自动导入了zk及客户端

rpc 底层端口111能否修改 rpc协议端口号_java_04


②配置文件

# 应用名称
dubbo.application.name=boot-user-service-provider
dubbo.registry.address=zookeeper://127.0.0.1:2181
server.port=8082

③服务具体实现【provider】

@Service//暴露服务【是dubbo的】
@Component
public class UserServiceImpl implements UserService {

    @Override
    public List<UserAddress> getUserAddressList(String userId) {
        List<UserAddress> list = new ArrayList<>();
        UserAddress address1 = new UserAddress(1, "阿根廷", "梅西");
        UserAddress address2 = new UserAddress(2, "巴西", "内马尔");
        list.add(address1);
        list.add(address2);
        return list;
    }
}

④启动类

@SpringBootApplication
@EnableDubbo//开启基于注解的dubbo
public class BootUserServiceProviderApplication {

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

}

2.4 创建服务消费者

rpc 底层端口111能否修改 rpc协议端口号_rpc 底层端口111能否修改_05


①导入依赖

需要引入web模块,因为需要启动创建controller测试

<!--引入api依赖-->
 <dependency>
     <groupId>com.zi</groupId>
     <artifactId>user-api</artifactId>
     <version>1.0-SNAPSHOT</version>
 </dependency>

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

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

②配置文件

# 应用名称
dubbo.application.name=boot-order-service-consumer
dubbo.registry.address=zookeeper://127.0.0.1:2181
server.port=8081

③service

@Service
public class OrderService {

    @Reference//导入dubbo的
    private UserService userService;

    public List<UserAddress> getUserAddressLis(String id){
        List<UserAddress> addressList = userService.getUserAddressList(id);
        return addressList;
    }
}

④controller

@Controller
public class OrderController {

    @Autowired
    private OrderService orderService;

    @GetMapping("/getOrderList")
    @ResponseBody
    public List<UserAddress> getUserOrderList(){
        List<UserAddress> list = orderService.getUserAddressLis("1");
        return list;
    }

    @ResponseBody
    @GetMapping("/test")
    public String test(){
        return "success...";
    }
}

⑤启动类

@SpringBootApplication
@EnableDubbo//开启基于注解的dubbo
public class BootOrderServiceConsumerApplication {

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

}

【常见问题】

①本地zookeeper是否启动,或者远程zookeeper地址是否正确
②zk是否导入、zk客户端是否导入
③实体类是否实现序列化、是否设置了get、set方法
④provider的@Service与consumer的@Reference是否导入的是dubbo的
⑤启动类上是否加上@EnableDubbo

【使用Dubbo的大体步骤】

  1. 创建api模块
  2. 创建provider,导入api模块依赖
  3. 创建consumer,导入api模块依赖
  4. zookeeper的地址
  5. dubbo的@Service、@Reference、@EnableDubbo【主要是包扫描】

3 其他概念

3.1 使用Spring整合dubbo

applicationContext.xml:

  • application:指定应用名
  • service:声明为Dubbo服务
  • consumer:reference间共享的默认配置
  • provider:service间共享的默认配置
  • protocol:RPC协议及通信端口号,默认20880
  • registry:注册中心类型、地址及相关配置
  • monitor:监控类型及地址

service 与 reference 是 Dubbo 最基础的两个配置项,它们用来将某个指定的接口或实现类注册为 Dubbo 服务,并通过配置项控制服务的行为。

  • service 用于服务提供者端,通过 service 配置的接口和实现类将被定义为标准的 Dubbo 服务,从而实现对外提供 RPC 请求服务。
  • reference 用于服务消费者端,通过 reference 配置的接口将被定义为标准的 Dubbo 服务,生成的 proxy 可发起对远端的 RPC 请求。
  • 一个应用中可以配置任意多个 service 与 reference
3.2 配置概念

①配置优先级

-D(命令行参数) > application.properties(applicationContext.xml) > dubbo.xml

②检查

可以设置check为false,就算没有一些服务或配置也不会报错
dubbo.consumer.check=false 所有的消费者都不检查

③超时

<dubbo:reference interface="com.zi.gmall.service.UserService" 
 id="userService" timeout="5000"> 
也可以在method上面配置

方法级优先 - 接口级 - 全局配置【级别一样则消费者优先】
<dubbo:consumer timeout="1000"></dubbo:consumer>

- 精确优先、消费者优先
3.3 重试次数、多版本

①retryies:重试次数

  • 幂等(设置重试次数)【查询、删除、修改】

是否每次请求返回的值是一样的

  • 非幂等(不能设置重试次数)【新增】

②version:设置版本,实现灰度发布

3.4 本地存根、dubbo直连

本地存根:stub,主要放在interface模块下
dubbo直连:直接在@Reference设置服务提供者地址,可以绕过注册中心

3.5 高可用:负载均衡
  1. 基于权重的随机
  2. 轮询
  3. 基于权重的轮询
  4. 最少活跃数【选择执行时间耗时最短的】
  5. 一致性hash

DUBBO默认使用的是随机的负载均衡机制,通过@Reference(loadbalance="roundrobin")修改负载均衡策略。
可以通过@Service(weight=“”)修改权重,也可以到管理中心对权重进行倍增(权重*2)和半增(权重/2)

3.6 服务降级、容错

dubbo管理端地址:https://github.com/apache/incubator-dubbo-ops,下载项目之后,通过maven打包,然后java -jar + 打好的war直接运行

  • 在dubbo的管理端页面进行屏蔽:直接不调用远程服务,直接返回为null
  • 容错:在调用远程服务失败以后,才返回为null

通过hystrix进行容错:
①导入依赖

<!--引入hystrix依赖-->
 <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
     <version>2.2.10.RELEASE</version>
 </dependency>

②在启动类上添加@EnableHystrix//开启服务容错,服务提供者和消费者都需要添加
③添加@HystrixCommand注解

@HystrixCommand(fallbackMethod = "hello")//服务调用失败之后,调用hello方法

4 RPC&Netty原理

dubbo原理:https://dubbo.apache.org/zh/docs3-v2/java-sdk/concepts-and-architecture/code-architecture/

4.1 Dubbo框架设计图

rpc 底层端口111能否修改 rpc协议端口号_java_06