vlambda博客
学习文章列表

【RPC原理】dubbo介绍和使用

前言

    在前面,介绍了RPC的基本概念,以及JDK原生支持RPC的方式:Java RMI。但是你会发现Java RMI有很明显的缺点。

    1. RMI只支持Java,其他语言不支持

    2. RMI是私有的协议(JRMP),无法拓展。序列化和反序列化都是封装好的。

   其中(a)是一个致命的缺点,因为RPC大多数应用的场景是微服务中,在这个架构体系下,不同的组件采用不同的语言实现是很常见的。为了使得RPC更加的便捷,通用,以及可定制化,涌现了很多RPC框架,其中thrift和dubbo就是两个典型的代表。先说说dubbo。

Apache Dubbo

    在dubbo的官网上可以看到相关的文档和介绍:https://dubbo.apache.org/zh/

     这是一个轻量级的开源服务框架。

【RPC原理】dubbo介绍和使用

提供的能力:RPC,复杂均衡(Load Balance),服务注册发现(Service Register And Discovery),高度的可扩展能力等。其中前边几个是我们比较关心的,后面大部分都是服务治理相关的,暂时不关心。文档上注明了发音,注意看音标。别读错了。

    Dubbo在早期起源于alibaba,是alibaba的开源项目,后来贡献给了Apache开源基金会,并且顺利毕业,成为Apache 顶级项目之一。也是国内开源产品的代表。

怎么用?

    说了那么多,那么这个框架该怎么用呢?按照之前的说法,一个RPC系统主要是三部分 服务提供者(Producer),服务消费者(Consumer),以及用于存储协调两者的注册中心。这里面注册中心不是必须的,因为你可以把消费者调用的服务路径给写成固定的,他就不需要去注册中心寻找服务提供者的ip。这种方式叫做点对点调用。Dubbo提供了这种调用方法,也是最简单的。

    演示项目项目依赖构建工具maven,jdk版本:jdk8.

点对点调用

    首先是引入相关的依赖

 <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/dubbo --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.6.6</version> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.10</version> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.5</version> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.32.Final</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>2.8.0</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>2.8.0</version> </dependency> </dependencies>

这里面必须的只有dubbo和netty,因为dubbo依赖了netty,其他依赖是后续要用的,一起放进来。

    然后新建子模块。注意这里是子模块,不是新建一个项目,当然你新建一个项目也可以,但是没必要。新建子模块的方法:

【RPC原理】dubbo介绍和使用

这个子模块会继承父亲的pom依赖,所以里面的pom.xml不需要再添加内容。新建子模块的名字:dubbo-producer

【RPC原理】dubbo介绍和使用

同样的操作,新建子模块:dubbo-consumer

【RPC原理】dubbo介绍和使用

到这里项目的基本骨架构建完成。然后开始写个demo。

dubbo-producer

    producer的目的是提供一个服务,首先定义一个服务:

public interface ProviderService { String SayHello(String word);}

    然后实现一下:

public class ProviderServiceImpl implements ProviderService{ public String SayHello(String word) { return word; }}

    接着把这个服务配置一下:在resource目录下,首先新建一个目录spring,然后在spring下新建文件,producer.xml,写入内容:

<?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:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!--当前项目在整个分布式架构里面的唯一名称,计算依赖关系的标签--> <dubbo:application name="provider" owner="mmatrixyg"> <dubbo:parameter key="qos.enable" value="true"/> <dubbo:parameter key="qos.accept.foreign.ip" value="false"/> <dubbo:parameter key="qos.port" value="55555"/> </dubbo:application>
<dubbo:monitor protocol="registry"/>
<!--dubbo这个服务所要暴露的服务地址所对应的注册中心--> <!--<dubbo:registry address="N/A"/>--> <dubbo:registry address="N/A" />
<!--当前服务发布所依赖的协议;webserovice、Thrift、Hessain、http--> <dubbo:protocol name="dubbo" port="20880"/>
<!--服务发布的配置,需要暴露的服务接口--> <dubbo:service interface="ProviderService" ref="providerService"/>
<!--Bean bean定义--> <bean id="providerService" class="ProviderServiceImpl"/></beans>

    这个文件和Spring的没啥区别,其实就是Spring的xml。里面有几个标签,第一部分就是应用相关配置,不用管。然后是协议:registry,这个后面再说,先这样写。接着是注册中心配置,这个因为我们是点对点调用,所以不用注册中心。然后,是服务的端口。这个很重要,这个是服务消费者消费服务的依据。最后是服务的配置。

    服务配置好以后,需要把服务发布出去,也就是监听某个端口。

public class App { public static void main( String[] args ) throws IOException { //加载xml配置文件启动 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/provider.xml"); context.start(); System.in.read(); // 按任意键退出 }}

    这里和启动Spring项目没啥区别。启动成功以后:

注意下面的信息: export /192.168.31.184:20880 这里代表了当前服务的元信息。等下需要继续用。到这里producer服务在等待调用者发起调用。

dubbo-consumer

    produce写完之后,接下来就是consumer。刚才已经新建了consumer服务,consumer服务也是继承于父pom,但是consumer的pom文件,需要再加一个依赖,就是对producer的依赖。这里也很好理解,因为consumer需要调用producer的服务,所以需要知道producer提供的接口。

<dependency><groupId>org.example</groupId><artifactId>dubbo-producer</artifactId><version>1.0-SNAPSHOT</version><scope>compile</scope></dependency>

    加上这个依赖即可。consumer做的事情就比较简单,直接调用服务。但是它要怎么调用呢?按照之前的说法,服务调用者是需要在本地生成一个用于代理远程服务的对象的。所以,需要先把这个对象配置起来。在resource下面,新建consumer.xml:

<?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:dubbo="http://code.alibabatech.com/schema/dubbo"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"><dubbo:application name="consumer" owner="matrixyg"/><dubbo:registry address="N/A" /><!--生成一个远程服务的调用代理--><!--点对点方式--><dubbo:reference id="providerService"interface="ProviderService"url="dubbo://192.168.31.184:20880/ProviderService"/></beans>

注意这里的url参数,这个参数就是指明了producer服务所在的地方,这里必须和上面producer暴露出来的保持一致,否者就找不到具体的服务。

      然后新建一个主函数,调用服务:

public class App { public static void main(String[] args) throws Exception{ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("consumer.xml"); context.start(); ProviderService providerService = context.getBean("providerService", ProviderService.class); String str = providerService.SayHello("hello"); System.out.println(str); System.in.read(); }}

    这个代码也很简单,就是启动了Spring容器,然后获取实例。调用的结果:

可以发现调用成功。

总结

    本次分享展示了一个dubbo最基本的使用,学习肯定是要从简单的开始学起来。这是dubbo提供的点对点调用方式。看到这里可能有很多问题:

  1. 这里没有注册中心呀,注册中心怎么加进去呢?

  2. 现在Spring早就不用配置文件了,大家大多数用注解驱动,有注解的方式吗?

  3. 真实的线上开发是怎么做的?

  4. dubbo怎么实现的?为什么和Spring内无缝集成?

    接下来的文章会围绕着这些问题展开,敬请期待!


提醒

    上述演示的JDK版本是JDK8,JDK17会出错,因为JDK17新建了一个特性,对JDK内部的安全做了更强的保证,禁止了一些反射调用,导致这个版本的dubbo反射创建代理对象是失败的。