> 文章列表 > Doubbo

Doubbo

Doubbo

目录

1.简介

2.架构

3.配置监控中心

4.模拟服务提供者

5.模拟服务消费者

6.消费者的其他配置

6.1协议

6.2启动时检查

6.3超时和重试

6.4负载均衡

7.补充


1.简介

        Apache Dubbo是一款高性能的Java RPC框架。其前身是阿里巴巴公司开源的一个高性能、轻量级的开源Java RPC框架,可以和Spring框架无缝集成。

RPC

        RPC全称为remote procedure call,即远程过程调用。比如两台服务器A和B,A服务器上部署一个应用,B服务器上部署一个应用,A服务器上的应用想调用B服务器上的应用提供的方法,由于两个应用不在一个内存空间,不能直接调用,所以需要通过网络来表达调用的语义和传达调用的数据。

        RPC是一个泛化的概念,RPC并不是一个具体的技术,而是指整个网络远程调用过程。严格来说一切远程过程调用手段都属于RPC范畴。各种开发语言都有自己的RPC框架。Java中的RPC框架比较多,广泛使用的有RMI、Hessian、Dubbo等。

2.架构

Dubbo架构图(Dubbo官方提供)如下:

0.tomcat容器启动。

1.将提供者服务注册到注册中心当中,dubbo提供的注册中心就是zookeeper。

2.消费者想要调用提供者提供的方法时,从注册中心拉去提供者的服务地址。

3.若提供者的服务地址发生了改变,注册中心则会马上通知消费者。

4.消费者根据服务中心提供的服务地址就可以直接调用提供者了,并且在调用提供者服务之后,就会将提供者的地址主动缓存下来。

5.监控消费者调用提供者的次数。

        消费者调用后会将提供者提供的路径缓存下来,这样即使注册中心宕机,消费者也还是可以通过缓存的地址调用提供者。

        zookeeper使用的连接方式是长链接。

3.配置监控中心

        在开发时,需要知道Zookeeper注册中心都注册了哪些服务,有哪些消费者来消费这些服务。我们可以通过部署一个管理中心来实现。其实管理中心就是一个web应用,部署到tomcat即可。

步骤:

1.GitHub上下一个dubbo-admin的war包。

2.准备一个tomcat容器,将war包放在tomcat的webapps下,并修改tomcat端口号,避免端口冲突。

3.启动tomcat,在启动完成后会将dubbo-admin.war解压,此时进入到WEB-INF中修改dubbo.properties,将其中连接zookeeper的配置进行修改。

4.重启tomcat。

5.浏览器访问http://localhost:自己定义的端口号/dubbo-admin/即可。​​​​​

访问时输入用户名密码,都是root。即可出现如下页面。

由于目前没有启动任何的服务提供者、消费者的项目,所以没有什么看的。

4.模拟服务提供者

创建服务提供者接口

public interface HelloService {public String sayHello(String name);
}

创建服务提供者实现类

@Service  //把此服务注册到zookeeper dubbo的注解
public class HelloServiceImpl implements HelloService {public String sayHello(String name) {return "hello " + name;}}

创建配置文件

<?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:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 当前应用名称,用于注册中心计算应用间依赖关系,注意:消费者和提供者应用名不要一样 --><dubbo:application name="dubbodemo_provider" /><!-- 连接服务注册中心zookeeper ip为zookeeper所在服务器的ip地址--><dubbo:registry address="zookeeper://127.0.0.1:2181"/><!-- 注册 消费者调用当前项目时提供的协议名称和端口号 协议名称使用dubbo的协议 端口默认是20880 --><dubbo:protocol name="dubbo" port="20881"></dubbo:protocol><!-- 扫描指定包,加入@Service注解的类会被发布为服务  --><dubbo:annotation package="com.study.service.impl" /></beans>

创建main方法加载配置文件

    public static void main(String[] args) {ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext-provider.xml");app.start();while (true){}}

效果:

在监控中心中看到了已经启动的服务提供者。

还有此服务提供的方法。

或者使用tomcat启动,web.xml中配置监听器加载配置文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"version="2.5"><!-- 监听器监听其他的spring配置文件 --><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext-provider.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener></web-app>

5.模拟服务消费者

创建controller

@Controller
@RequestMapping("/demo")
public class HelloController {@Reference //dubbo的远程注入方式private HelloService helloService;@RequestMapping("/hello")@ResponseBodypublic String getName(String name){//远程调用String result = helloService.sayHello(name);System.out.println(result);return result;}}

创建service

//包名要和提供者的包名保持一致
public interface HelloService {public String sayHello(String name);
}

创建springmvc的配置文件

用于配置包扫描以及dubbo的配置

<?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:aop="http://www.springframework.org/schema/aop"xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.study"/><!--告诉zookeeper 当前项目是哪个--><dubbo:application name="dubbodemo_consumer"/><!--链接注册中心--><dubbo:registry address="zookeeper://127.0.0.1:2181"/><!--注解扫描 扫描的是dubbo的 @Reference注解--><dubbo:annotation package="com.itheima"/><!--    timeout:每次请求都会等待3秒  retries失败后重试次数--><dubbo:consumer timeout="3000" retries="0"/></beans>

创建web.xml配置文件

用于加载springmvc的配置文件,以及前端控制器

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"version="2.5"><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- 指定加载的配置文件 ,通过参数contextConfigLocation加载--><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/spring-mvc.xml</param-value></init-param></servlet><servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>*.do</url-pattern></servlet-mapping></web-app>

配置tomcat后启动

启动消费者后发现监控中心中还是没有消费者服务.

我们调用一次消费者的方法:

发现有所响应.并且在监控中心出现了消费者的服务.

 

此时我们把提供者服务关闭,就只剩下了消费者服务

并且告诉我们此服务没有提供者.

6.消费者的其他配置

6.1协议

<dubbo:protocol name="dubbo" port="20880"/>

        一般在服务提供者一方配置,可以指定使用的协议名称和端口号。 其中Dubbo支持的协议有:dubbo、rmi、hessian、http、webservice、rest、redis等。 推荐使用的是dubbo协议。 dubbo 协议采用单一长连接和 NIO 异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低。 也可以在同一个工程中配置多个协议,不同服务可以使用不同的协议,例如:

<!-- 多协议配置 --><dubbo:protocol name="dubbo" port="20880" />
<dubbo:protocol name="rmi" port="1099" />
<!-- 使用dubbo协议暴露服务 -->
<dubbo:service interface="com.study.api.HelloService" ref="helloService" protocol="dubbo" /><!-- 使用rmi协议暴露服务 -->
<dubbo:service interface="com.study.api.DemoService" ref="demoService" protocol="rmi" />

6.2启动时检查

<dubbo:consumer check="true"/>

        上面这个配置需要配置在服务消费者一方,如果不配置默认check值为true。Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,以便上线时,能及早发现问题。可以通过将check值改为false来关闭检查。 ​ 建议在开发阶段将check值设置为false,在生产环境下改为true。

6.3超时和重试

<!--设置超时时间以及重试次数-->
<dubbo:consumer timeout="3000"  retries="0"/>

        如果不做如上配置,默认提供者1秒之内没有响应结果就重试,总共会重试3次

6.4负载均衡

        负载均衡(Load Balance):其实就是将请求分摊到多个操作单元上进行执行,从而共同完成工作任务。在集群负载均衡时,Dubbo 提供了多种均衡策略(包括随机(random)、轮询(roundRobin)、最少活跃调用数(leastActive)、一致性Hash(consistentHash)),默认为random随机调用。配置负载均衡策略,既可以在服务提供者一方配置,也可以在服务消费者一方配置,如下:

@Controller
@RequestMapping("/demo")
public class HelloController {//在服务消费者一方配置负载均衡策略@Reference(check = false,loadbalance = "random")private HelloService helloService;@RequestMapping("/hello")@ResponseBodypublic String getName(String name){//远程调用String result = helloService.sayHello(name);System.out.println(result);return result;}
}
//在服务提供者一方配置负载均衡
@Service(interfaceClass = HelloService.class,loadbalance = "random")
public class HelloServiceImpl implements HelloService {public String sayHello(String name) {return "hello " + name;}
}

7.补充

1.以上代码的服务者和消费者的service是固定写在包里,那也就意味着如果有所修改就需要在服务端和消费端都进行修改,产生了代码的冗余。我们如果是maven项目可以将service的代码抽取到一个maven工程,需要依赖此接口的工程只需要在自己工程的pom.xml文件中引入maven坐标即可。 

2.Dubbo底层是基于代理技术为HelloService接口创建代理对象,远程调用是通过此代理对象完成的。可以通过开发工具的debug功能查看此代理对象的内部结构。另外,Dubbo实现网络传输底层是基于Netty框架完成的。

3.在远程调用的过程中,如果涉及到了java对象,需要进行序列化,因此java对象需要实现序列化接口。