一、RPC
-
什么是RPC?
RPC(Remote Procedure Call)远程过程调用。见名知意 - 从远程主机调用一个过程/函数。
RPC的目标是:使得本程序调用其它远程主机上的函数,好像调用本程序内的函数一样简单,并且屏蔽编程语言的差异性。
要实现上述目标首先是设计一种通讯协议,称之为:RPC协议(Protocol)
- RPC协议不是一个具体的协议,而是一个类型名,代表一类协议,这类协议叫做RPC协议;
- RPC协议在TCP/UDP之上,广义上可以跨越平台、语言进行应用间通讯(说广义是因为可以开发一个协议且不支持跨语言);
-
为什么要用RPC?
其实这是应用开发到一定的阶段的强烈需求驱动的。
-
如果我们开发简单的单一应用,逻辑简单、用户不多、流量不大,那我们用不着;
-
当我们的系统访问量增大、业务增多时,我们会发现一台单机运行此系统已经无法承受。此时,我们可以将业务拆分成几个互不关联的应用,分别部署在各自机器上,以划清逻辑并减小压力。此时,我们也可以不需要RPC,因为应用之间是互不关联的。
-
当我们的业务越来越多、应用也越来越多时,自然的,我们会发现有些功能已经不能简单划分开来或者划分不出来。此时,可以将公共业务逻辑抽离出来,将之组成独立的服务Service应用 。而原有的、新增的应用都可以与那些独立的Service应用 交互,以此来完成完整的业务功能。所以此时,我们急需一种高效的应用程序之间的通讯手段来完成这种需求,所以你看,RPC大显身手的时候来了!
其实#3
描述的场景也是服务化 、微服务 和分布式系统架构 的基础场景。即RPC框架就是实现以上结构的有力方式。
-
有哪些RPC?
有很多RPC框架:CORBAR、Thrift、Dubbo等等。基本上他们分为两种类别:
- 一种是跨语言的;
- 一种是同语言的,如果你的分布式应用架构主体都是Java应用,显然我们不应该使用跨语言的RPC来多一层中转浪费效率。
就Java来说,我认为其本身API提供的RMI
就是一种RPC协议,但是其毕竟太原始,需要自己去添加很多机制才能上生产环境。所以,今天介绍下我最近使用的Dubbo框架。
二、Dubbo使用实例
-
什么是Dubbo?
Dubbo是阿里巴巴为Java开发的RPC,据网上评价来看,非常不错。在Dubbo开源后很多公司都使用其来构建自己的分布式架构。今天我来做一个使用实例。
由于Dubbo官方文档已经把一切都说的很详细了,我就不没意思的摘抄了,放上地址:官网
-
官网上也有详细使用方法,那我为什么还要写个使用实例呢?
是因为,似乎到2012年,Dubbo已经比较稳定的完成了所有开发,所以现在Dubbo其实是在一个松散的维护状态下的。有些文档内容已经失效:地址无法访问,一些错误没有明确说明。
所以参照官网会有一些问题,我这里就是解决了某些问题而完成的一个实例,放在这里供大家参考。
建议大家先去看文档,形成一个整体概念再做实例。
所以,我的整体架构是这样的:
步骤
-
首先,要确保Zookeeper的安装和配置正确,可以直接按照我另一篇文章Zookeeper简介与安装来做。
-
我们需要一个Dubbo服务管理控制台:
本身这个项目的war
包,Dubbo在其文档中是给出了下载地址的,但是地址已经失效了。所以,现在只能去其GitHub地址上自己下载源码下来打包了。
-
使用Eclipse,用其自带的git插件下载dubbo项目整体,地址是:https://github.com/alibaba/dubbo.git;
-
先将dubbo项目
转为Maven项目,然后单独将其中的子Maven项目dubbo-admin
导出来,这就是一个JavaWeb项目。
-
但是这个项目,别直接Maven打包,因为它有一些依赖问题需要修改,打开其pom.xml
文件:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
</exclusions>
</dependency>
如果使用Spring的2.5.6.SEC03
版本直接打包,就会有如下错误:
ERROR context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'uriBrokerService': Cannot create inner bean '(inner bean)' of type [com.alibaba.citrus.service.uribroker.impl.URIBrokerServiceImpl$URIBrokerInfo] while setting bean property 'brokers' with key [0]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#25': Cannot create inner bean 'server' of type [com.alibaba.citrus.service.uribroker.uri.GenericURIBroker] while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'server': Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'URIType' of bean class [com.alibaba.citrus.service.uribroker.uri.GenericURIBroker]: Bean property 'URIType' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:230)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:122)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedList(BeanDefinitionValueResolver.java:287)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:126)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1245)
-
接着,如果此项目你不打算部署到与任意一个Zookeeper一个机器的话,就需要修改/dubbo-admin/src/main/webapp/WEB-INF/dubbo.properties
文件,在其中指定你的Zookeeper
地址(要保证这些机器能互相通讯)。
-
没有要修改的了。可以使用Maven的package命令打包了。之后部署war项目,可以按照官网的部署方式,也就是将之部署为ROOT应用,官网地址点这里。
-
服务提供者项目
源码地址:dubbo-practice-provider
其中有两个子项目:
dubbo-practice-provider-api
:暴漏接口和JavaBeans,让实现项目引用然后去实现、让消费者引用然后调用。这个比较简单,一看就懂就不展开讲了。dubbo-practice-provider-impl
:上面api项目的实现项目,是一个普通Java项目;
实现者项目dubbo-practice-provider-impl
的主要内容就是Dubbo如何暴漏一个服务的使用了,说一下:
-
首先是依赖关系,pom.xml
中
<dependency>
<groupId>dubbo-practice-provider-api</groupId>
<artifactId>dubbo-practice-provider-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>${zookeeper.version}</version>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>${zkclient.version}</version>
</dependency>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
-
其次是dubbo配置,配置在Spring配置文件中,我放在/META-INF/spring/spring-dubbo.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="dubbo-practice-provider" />
<dubbo:registry protocol="zookeeper" address="192.168.157.130:2181,192.168.157.129:2181" />
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:service interface="com.ddup.dubbo.service.api.PersonService" ref="personService" />
</beans>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 最后,做好之后就可以运行了,我写了一个简单的启动服务类
/dubbo-practice-provider-impl/src/main/java/com/ddup/dubbo/service/impl/DubboContainerStart.java
,运行这个就行了,不要关。
-
服务消费者项目
源码地址:dubbo-practice-consumer;
主要就是Dubbo服务的调用了,见/META-INF/spring/spring-dubbo.xml
:
<dubbo:application name="dubbo-practice-consumer" />
<dubbo:registry protocol="zookeeper" address="192.168.157.130:2181,192.168.157.129:2181" />
<dubbo:reference id="personService" interface="com.ddup.dubbo.service.api.PersonService" init="true" />
然后,运行/dubbo-practice-consumer/src/main/java/com/ddup/dubbo/consumer/SpringStart.java
,鹅妹子嘤!!!可以看到,调用成功啦!
-
在上面#2
说的管理控制台上,现在你就可以看到服务了,能看到服务者以及每个服务的消费者等等信息;
登录
![这里写图片描述](https://img-blog.csdn.net/20160621003514086)
查看Dubbo服务
![这里写图片描述](https://img-blog.csdn.net/20160621003523070)
以上!
TIPS:
-
dubbo-admin项目的tomcat启动后无法访问:
打开catalina.out查看错误
[root@localhost logs]
如果发现如下错误,是因为Zookeeper没有成功启动,可以去检查Zookeeper的状态。
INFO velocity.VelocityEngine - SpringResourceLoaderAdapter : initialization starting.
INFO velocity.VelocityEngine - SpringResourceLoaderAdapter : set path '/templates/common/'
INFO velocity.VelocityEngine - SpringResourceLoaderAdapter : initialization complete.
INFO rule.ExtensionMappingRule - Initialized extension.input:ExtensionMappingRule with cache disabled
INFO rule.ExtensionMappingRule - Initialized extension.output:ExtensionMappingRule with cache disabled
INFO rule.DirectModuleMappingRule - Initialized action:DirectModuleMappingRule with cache disabled
INFO rule.DirectModuleMappingRule - Initialized screen.notemplate:DirectModuleMappingRule with cache disabled
INFO rule.FallbackModuleMappingRule - Initialized screen:FallbackModuleMappingRule with cache enabled
INFO rule.DirectTemplateMappingRule - Initialized screen.template:DirectTemplateMappingRule with cache disabled
INFO rule.FallbackTemplateMappingRule - Initialized layout.template:FallbackTemplateMappingRule with cache enabled
INFO rule.DirectModuleMappingRule - Initialized control.notemplate:DirectModuleMappingRule with cache disabled
INFO rule.FallbackModuleMappingRule - Initialized control:FallbackModuleMappingRule with cache enabled
INFO rule.DirectTemplateMappingRule - Initialized control.template:DirectTemplateMappingRule with cache disabled
INFO zkclient.ZkEventThread - Starting ZkClient event thread.
-
Provider的服务与Consumer引用时的一些问题:
-
关闭启动时检查
Dubbo默认会在启动时检查依赖的服务是否可用,不可用会抛出异常,阻止Spring初始化完成。如果对有些服务不关心,或者出现了循环依赖,必须有一方先启动时,可以关闭启动时检查。方式如下:
<dubbo:reference interface="com.xxx.XxxService" check="false" />
-
引用默认还是延迟初始化的,只有引用被注入到其它Bean,或者被getBean()
获取时,才会初始化。如果需要饥饿加载,即Dubbo启动时就立即生成动态代理实例,则可以配置:
<dubbo:reference interface="com.xx.XxxService" init="true" />
2017.07.31更新:Dubbo官网声明官方要重新开始重点维护此项目了!