【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: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:
<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反射创建代理对象是失败的。