Dubbo是一个RPC远程调用的框架,对于一个服务提供方,暴露了一个接口给外部消费方调用。如果服务提供方自身也需要调用这个接口会怎么样呢,难道也需要走远程编解码和数据网络传输这套流程吗?
对于Dubbo这么优秀的开源框架,显然是需要支持本地调用的,Dubbo提供了本地调用的InjvmProtocol
协议。今天我们代码演示来详细分析下InjvmProtocol
是的工作原理。
application.xml
如下:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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="demo-provider"/> <dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"/> <dubbo:protocol name="dubbo" port="20880"/> <bean id="helloWorldServiceImpl" class="cn.gov.zcy.dubbotest.api.HelloWorldServiceImpl"/> <dubbo:service interface="cn.gov.zcy.dubbotest.api.HelloWorldSerivice" ref="helloWorldServiceImpl"/> <dubbo:reference id="helloWorldService" interface="cn.gov.zcy.dubbotest.api.HelloWorldSerivice"/>beans>
演示测试代码如下:
public class DubboInjvmTest {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml"); HelloWorldSerivice helloWorldSerivice = context.getBean("helloWorldService", HelloWorldSerivice.class); Response> returnMessage = helloWorldSerivice.hello("aaa"); System.out.println(returnMessage.getResult().get()); LockSupport.park(); }}
说明:使用Dubbo本地调用并不需做特殊配置,按正常 Dubbo 服务暴露即可。Dubbo服务在暴露远程服务的同时,也会同时以 injvm 协议暴露本地服务。injvm 是一个伪协议,不会像其他协议那样对外开启端口,仅用于本地调用。
02. Service暴露行为
首先,我们知道,任何一个dubbo配置标签都对应一个后台的解析Bean,拿
dubbo:service
举例,其对应的后台解析bean为
com.alibaba.dubbo.config.spring.ServiceBean
,我们来跟踪其代码看看Dubbo服务暴露的过程:
/** * ServiceFactoryBean * * @author william.liangf * @export */public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener, BeanNameAware {
...... public void onApplicationEvent(ApplicationEvent event) {
if (ContextRefreshedEvent.class.getName().equals(event.getClass().getName())) {
if (isDelay() && ! isExported() && ! isUnexported()) {
if (logger.isInfoEnabled()) {
logger.info("The service ready on spring started. service: " + getInterface()); } export(); } } } .....