【RPC原理】dubbo介绍和使用
前言
在前面,介绍了RPC的基本概念,以及JDK原生支持RPC的方式:Java RMI。但是你会发现Java RMI有很明显的缺点。
RMI只支持Java,其他语言不支持
RMI是私有的协议(JRMP),无法拓展。序列化和反序列化都是封装好的。
其中(a)是一个致命的缺点,因为RPC大多数应用的场景是微服务中,在这个架构体系下,不同的组件采用不同的语言实现是很常见的。为了使得RPC更加的便捷,通用,以及可定制化,涌现了很多RPC框架,其中thrift和dubbo就是两个典型的代表。先说说dubbo。
Apache Dubbo
在dubbo的官网上可以看到相关的文档和介绍:https://dubbo.apache.org/zh/
这是一个轻量级的开源服务框架。
提供的能力: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,其他依赖是后续要用的,一起放进来。
然后新建子模块。注意这里是子模块,不是新建一个项目,当然你新建一个项目也可以,但是没必要。新建子模块的方法:
这个子模块会继承父亲的pom依赖,所以里面的pom.xml不需要再添加内容。新建子模块的名字:dubbo-producer
同样的操作,新建子模块:dubbo-consumer
到这里项目的基本骨架构建完成。然后开始写个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,写入内容:
<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:serviceinterface="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:
<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提供的点对点调用方式。看到这里可能有很多问题:
这里没有注册中心呀,注册中心怎么加进去呢?
现在Spring早就不用配置文件了,大家大多数用注解驱动,有注解的方式吗?
真实的线上开发是怎么做的?
dubbo怎么实现的?为什么和Spring内无缝集成?
接下来的文章会围绕着这些问题展开,敬请期待!
提醒
上述演示的JDK版本是JDK8,JDK17会出错,因为JDK17新建了一个特性,对JDK内部的安全做了更强的保证,禁止了一些反射调用,导致这个版本的dubbo反射创建代理对象是失败的。
