Dubbo

Author Avatar
kevin
发表:2023-05-23 13:41:00
修改:2024-10-09 13:41:30

分布式RPC框架Apache Dubbo

RPC全称为remote procedure call 远程过程调用

Dubbo提供了三大核心能力:

  • 面向接口的远程方法调用,

  • 智能容错和负载均衡,

  • 服务自动注册和发现。

核心

  • 通信效率
  • 序列化和反序列化的效率

概念

  • 服务提供者(Provider)
    • 暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务
  • 服务消费者(Consumer)
    • 调用远程服务的服务消费方,向注册中心订阅自己所需的服务
    • 从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用
  • 注册中心(Registry)
    • 注册中心返回服务提供者地址列表给消费者,
    • 如果有变更,注册中心将基于长连接推送变更数据给消费者
  • 监控中心(Monitor)
    • 服务消费者和提供者,在内存中累计调用次数和调用时间
    • 定时每分钟发送一次统计数据到监控中心

init初始化,async异步,sync同步,container表示dubbo容器

依赖注意,必须使用5.0.5.RELEASE版本的spring,dubbo2.6.0

不然和新版spring有版本冲突

服务提供方

创建 applicationContext-service.xml配置文件

<!--    注册名称-->
    <dubbo:application name="dubbo_provider"/>
<!--    注册服务-->
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!--    注册协议-->
    <dubbo:protocol name="dubbo" port="20881"/>
    <!--    包扫描-->
    <dubbo:annotation package="com.stu.service"/>

web.xml

<!--    初始化参数-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:application-service.xml</param-value>
    </context-param>
<!--    设置监听器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

服务消费方

导入的依赖和提供方一致

<!--    注册应用名称-->
    <dubbo:application name="dubbo_consumer"/>
<!--    注册zookeeper-->
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!--    包扫描-->
    <dubbo:annotation package="com.stu.controller"/>
<!--    建议在开发阶段将check值设置为false,在生产环境下改为true-->
    <dubbo:consumer check="false"/>

web.xml

<!--    设置转发器-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:application-consumer.xml</param-value>
        </init-param>
<!--        启动优先级-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

相同接口抽取

建一个公共项目,消费者和提供者相同的接口抽出,放在第三个项目上

然后消费者和 提供者对这个公共项目进行依赖,

注意,需要重写打包

事务代理的Service问题

解决Dubbo无法发布被事务代理的Service问题

<!--    数据源-->
    <bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
        <property name="username" value="root" />
        <property name="password" value="root" />
    </bean>
<!--    事务管理-->
    <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
<!--    开启事务注解,属性是使用cglib代理方式为Service类创建代理对象-->
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
proxy-target-class="true" 改为静态代理,默认为false

在Service注解中加入interfaceClass属性,指定服务的接口类型

服务提供方

service用的是dubbo的包,不是spring的

import com.alibaba.dubbo.config.annotation.Service;
//扫描进容器,指定服务的接口类型
@Service(interfaceClass = HelloService.class)
@Transactional         //开启事务
public class HelloServiceImpl implements HelloService {

    @Override
    public String sayHello(String name) {
        return "hello!"+name;
    }
}

消费者

@Controller
@RequestMapping("/demo")
public class HelloController {
    @Reference         //引入导入dubbo的包
    private HelloService helloService;
    @RequestMapping("/hello")
    @ResponseBody       //返回json
    public String getName(String name){
        String sayHello = helloService.sayHello(name);
        return sayHello;
    }
}

负载均衡

其实就是将请求分摊到多个操作单元上进行执行,从而共同完成工作任务。

一台服务器缺点

  • 如果宕机,不能提供服务
  • 可以容纳的并发数量比较少

负载均衡策略

  • Random LoadBalance 比较多
    • 随机,按权重设置随机概率。
  • RoundRobin LoadBalance 比较多
    • 轮循,按公约后的权重设置轮循比率。轮流处理
  • LeastActive LoadBalance
    • 最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
    • 使用响应毫米数最低的,延迟最低的服务器
  • ConsistentHash LoadBalance
    • 一致性 Hash,相同参数的请求总是发到同一提供者。

既可以在服务提供者一方配置,也可以在服务消费者一方配置

//在服务消费者一方配置负载均衡策略
    @Reference(check = false,loadbalance = "random")
//在服务提供者一方配置负载均衡
@Service(loadbalance = "random")
评论