dubbo中的参数回调

释放双眼,带上耳机,听听看~!

在正常的dubbo项目中,我们使用dubbo功能的目的是使服务调用方可能直接调用服务提供方提供的接口,而不需关系底层的实现。而在有的时候,我们想让服务提供方调用服务调用方的方法这应该怎么办呢?可能有人会觉的不会有这种可能性,但在实际的开发中这种业务是真实存在的。例如推送系统等。并且在dubbo中直接提供了这种业务的解决方案,也就是参数回调功能。下面我们详细介绍一下。


在使用dubbo中的参数回调功能时,需要定义两个接口,并且将其中的一个接口当作另一个接口的参数进行传递,所以刚方式也叫参数回调。下面我们看一下这两个接口的源码:

CallbackListener:

/**
 * 参数接口
 */
public interface CallbackListener {

    /**
     * 调用服务提供方
     *
     * @param str
     */
    void change(String str);

}

CallbackService:

/**
 * 普通的dubbo服务接口
 */
public interface CallbackService {

    /**
     * 接口对客户端暴露的服务
     *
     * @param key
     * @param listener
     * @throws Exception
     */
    void addListener(String key, CallbackListener listener) throws Exception;

}

下面我们看一下服务提供方的接口实现:

CallbackServiceImpl:

/**
 * 接口实现类
 */
@Service
public class CallbackServiceImpl implements CallbackService {

    public void addListener(String key, CallbackListener listener) {
        listener.change(String.format("key:	%s time:	%s", key, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())));
    }
}

下面我们看一下服务提供方的配置文件:

provider.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://code.alibabatech.com/schema/dubbo
       http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!-- 提供方信息-->
    <dubbo:application name="jilinwula"/>

    <!-- 使用zookeeper暴露服务地址 -->
    <dubbo:registry address="127.0.0.1:2181" protocol="zookeeper"/>

    <!-- 暴露服务端口 -->
    <dubbo:protocol name="dubbo" port="20880"/>

    <dubbo:service interface="com.jilinwula.api.CallbackService" ref="callbackServiceImpl" connections="1" callbacks="1000">
        <dubbo:method name="addListener">
            <dubbo:argument type="com.jilinwula.api.CallbackListener" callback="true"/>
        </dubbo:method>
    </dubbo:service>

    <!-- component-scan自动扫描注解 -->
    <context:component-scan base-package="com.jilinwula.*"/>

</beans>

服务调用方的配置文件和其它dubbo中的配置一样:

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="jilinwula"/>

    <!-- 使用zookeeper查找服务地址 -->
    <dubbo:registry address="127.0.0.1:2181" protocol="zookeeper"/>

    <!-- Dubbo自动生成远程服务代理 -->
    <dubbo:reference id="callbackService" interface="com.jilinwula.api.CallbackService"/>

</beans>

服务调用方客户端代码:

Consumer:

/**
 * 服务调用方
 */
public class Consumer {
    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"consumer.xml"});
        context.start();

        CallbackService callbackService = context.getBean("callbackService", CallbackService.class);

        callbackService.addListener("jilinwula", new CallbackListener() {
            public void change(String str) {
                System.out.println("callback:" + str);
            }
        });

    }
}

日志:

2018-08-20 15:44:45:679 INFO [ProductBossService,com.alibaba.dubbo.rpc.protocol.dubbo.CallbackServiceCodec,113]:  [DUBBO] export a callback service :dubbo://192.168.5.179:53291/com.jilinwula.api.CallbackListener.1801942731?addListener.1.callback=true&anyhost=true&application=jilinwula&callbacks=1000&check=false&connections=1&dubbo=2.6.2&generic=false&interface=com.jilinwula.api.CallbackListener&is_callback_service=true&isserver=false&methods=change&pid=6796®ister.ip=192.168.5.179&remote.timestamp=1534750840565&side=consumer×tamp=1534751084292, on NettyChannel [channel=[id: 0x2235eaab, /192.168.5.179:53291 => /192.168.5.179:20880]], url is: dubbo://192.168.5.179:20880/com.jilinwula.api.CallbackService?addListener.1.callback=true&anyhost=true&application=jilinwula&callbacks=1000&check=false&connections=1&dubbo=2.6.2&generic=false&interface=com.jilinwula.api.CallbackService&methods=addListener&pid=6796®ister.ip=192.168.5.179&remote.timestamp=1534750840565&side=consumer×tamp=1534751084292, dubbo version: 2.6.2, current host: 192.168.5.179
callback:key:    jilinwula time: 2018-08-20 15:44:45
2018-08-20 15:44:45:821 INFO [ProductBossService,com.alibaba.dubbo.config.AbstractConfig$1,81]:  [DUBBO] Run shutdown hook now., dubbo version: 2.6.2, current host: 192.168.5.179

这样我们服务提供方就相当于调用了服务调用方的方法了。如果我们将服务提供方的代码做以下修改,那程序的执行结果会是什么样的呢?下面代码为服务实现源码。

/**
 * 接口实现类
 */
@Service
public class CallbackServiceImpl implements CallbackService {

    public void addListener(String key, CallbackListener listener) {
        for (int i = 0 ;i < 10; i++) {
            listener.change(String.format("key:	%s time:	%s", key, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())));
        }
    }
}

我们将服务实现中的代码添加了循环,也就是多次调用change方法,那么此时我们的服务调有方也会被动的调用多次change方法。

日志:

2018-08-20 16:07:49:975 INFO [ProductBossService,com.alibaba.dubbo.rpc.protocol.dubbo.CallbackServiceCodec,113]:  [DUBBO] export a callback service :dubbo://192.168.5.179:53908/com.jilinwula.api.CallbackListener.1801942731?addListener.1.callback=true&anyhost=true&application=jilinwula&callbacks=1000&check=false&connections=1&dubbo=2.6.2&generic=false&interface=com.jilinwula.api.CallbackListener&is_callback_service=true&isserver=false&methods=change&pid=21460®ister.ip=192.168.5.179&remote.timestamp=1534751067298&side=consumer×tamp=1534752468537, on NettyChannel [channel=[id: 0x4082ba93, /192.168.5.179:53908 => /192.168.5.179:20880]], url is: dubbo://192.168.5.179:20880/com.jilinwula.api.CallbackService?addListener.1.callback=true&anyhost=true&application=jilinwula&callbacks=1000&check=false&connections=1&dubbo=2.6.2&generic=false&interface=com.jilinwula.api.CallbackService&methods=addListener&pid=21460®ister.ip=192.168.5.179&remote.timestamp=1534751067298&side=consumer×tamp=1534752468537, dubbo version: 2.6.2, current host: 192.168.5.179
callback:key:    jilinwula time: 2018-08-20 16:07:50
callback:key:    jilinwula time: 2018-08-20 16:07:50
callback:key:    jilinwula time: 2018-08-20 16:07:50
callback:key:    jilinwula time: 2018-08-20 16:07:50
callback:key:    jilinwula time: 2018-08-20 16:07:50
callback:key:    jilinwula time: 2018-08-20 16:07:50
callback:key:    jilinwula time: 2018-08-20 16:07:50
callback:key:    jilinwula time: 2018-08-20 16:07:50
callback:key:    jilinwula time: 2018-08-20 16:07:50
callback:key:    jilinwula time: 2018-08-20 16:07:50
2018-08-20 16:07:50:127 INFO [ProductBossService,com.alibaba.dubbo.config.AbstractConfig$1,81]:  [DUBBO] Run shutdown hook now., dubbo version: 2.6.2, current host: 192.168.5.179

这就是dubbo中参数回调功能。

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧