dubbo协议_5年大数据专家,带你基于Dubbo的Hessian协议实现远程调用,很牛

802d1d306a7e22cf7b9bc6e787a1433f.png

前言

Dubbo基于Hessian实现了自己Hessian协议,可以直接通过配置的Dubbo内置的其他协议,在服务消费方进行远程调用,也就是说,服务调用方需要使用Java语言来基于Dubbo调用提供方服务,限制了服务调用方。同时,使用Dubbo的Hessian协议实现提供方服务,而调用方可以使用标准的Hessian接口来调用,原生的Hessian协议已经支持多语言客户端调用,支持语言如下所示:

Java:http://hessian.caucho.com/#Java

Flash/Flex:http://hessian.caucho.com/#FlashFlex

Python:http://hessian.caucho.com/#Python

C++:http://hessian.caucho.com/#C

C#:http://hessian.caucho.com/#NETC

D:http://hessian.caucho.com/#D

Erlang:http://hessian.caucho.com/#Erlang

PHP:http://hessian.caucho.com/#PHP

Ruby:http://hessian.caucho.com/#Ruby

Objective-C:http://hessian.caucho.com/#ObjectiveC

下面,我们的思路是,先基于Dubbo封装的Hessian协议,实现提供方服务和消费方调用服务,双方必须都使用Dubbo来开发;然后,基于Dubbo封装的Hessian协议实现提供方服务,然后服务消费方使用标准的Hessian接口来进行远程调用,分别使用Java和Python语言来实现。而且,我们实现的提供方服务通过Tomcat发布到服务注册中心。首先,使用Java语言定义一个搜索服务的接口,代码如下所示:

package org.shirdrn.platform.dubbo.service.rpc.api; public interface SolrSearchService {    String search(String collection, String q, String type, int start, int rows);}

上面接口提供了搜索远程调用功能。

基于Dubbo的Hessian协议实现提供方服务

提供方实现基于Dubbo封装的Hessian协议,实现接口SolrSearchService,实现代码如下所示:

package org.shirdrn.platform.dubbo.service.rpc.server; import java.io.IOException;import java.util.HashMap;import java.util.Map; import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService;import org.shirdrn.platform.dubbo.service.rpc.utils.QueryPostClient;import org.springframework.context.support.ClassPathXmlApplicationContext; public class SolrSearchServer implements SolrSearchService {     private static final Log LOG = LogFactory.getLog(SolrSearchServer.class);    private String baseUrl;    private final QueryPostClient postClient;    private static final Map handlers = new HashMap(0);    static {        handlers.put("xml", new FormatHandler() {            public String format() {                return "&wt=xml";            }        });        handlers.put("json", new FormatHandler() {            public String format() {                return "&wt=json";            }        });    }     public SolrSearchServer() {        super();        postClient = QueryPostClient.newIndexingClient(null);    }     public void setBaseUrl(String baseUrl) {        this.baseUrl = baseUrl;    }     public String search(String collection, String q, String type, int start, int rows) {        StringBuffer url = new StringBuffer();        url.append(baseUrl).append(collection).append("/select?").append(q);        url.append("&start=").append(start).append("&rows=").append(rows);        url.append(handlers.get(type.toLowerCase()).format());        LOG.info("[REQ] " + url.toString());        return postClient.request(url.toString());    }     interface FormatHandler {        String format();    }}

因为考虑到后面要使用标准Hessian接口来调用,这里接口方法参数全部使用内置标准类型。然后,我们使用Dubbo的配置文件进行配置,文件search-provider.xml的内容如下所示:

<?xml version="1.0" encoding="UTF-8"?>                                   

因为使用Tomcat发布提供方服务,所以我们需要实现Spring的org.springframework.web.context.ContextLoader来初始化应用上下文(基于Spring的IoC容器来管理服务对象)。实现类SearchContextLoader代码如下所示:

package org.shirdrn.platform.dubbo.context; import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener; import org.shirdrn.platform.dubbo.service.rpc.server.SolrSearchServer;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.web.context.ContextLoader; public class SearchContextLoader extends ContextLoader implements ServletContextListener {     @Override    public void contextDestroyed(ServletContextEvent arg0) {        // TODO Auto-generated method stub     }     @Override    public void contextInitialized(ServletContextEvent arg0) {        String config = arg0.getServletContext().getInitParameter("contextConfigLocation");        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(config);        context.start();    } }

最后,配置Web应用部署描述符文件,web.xml内容如下所示:

<?xml version="1.0" encoding="UTF-8"?>    http_dubbo             org.shirdrn.platform.dubbo.context.SearchContextLoader                contextConfigLocation        classpath:search-provider.xml                 search        com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet                    home-class            org.shirdrn.platform.dubbo.service.rpc.server.SolrSearchServer                            home-api            org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService                1                search        /search                 index.html        index.htm        index.jsp        default.html        default.htm        default.jsp    

启动Tomcat以后,就可以将提供方服务发布到服务注册中心,这里服务注册中心我们使用的是ZooKeeper集群,可以参考上面Dubbo配置文件search-provider.xml的配置内容。

下面,我们通过两种方式来调用已经注册到服务注册中心的服务。

ea06d3597481707eadc381e5749866bc.png
基于Dubbo的Hessian协议远程调用

服务消费方,通过Dubbo配置文件来指定注册到注册中心的服务,配置文件search-consumer.xml的内容,如下所示:

<?xml version="1.0" encoding="UTF-8"?>               

然后,使用Java实现远程调用,实现代码如下所示:

package org.shirdrn.platform.dubbo.service.rpc.client; import java.util.concurrent.Callable;import java.util.concurrent.Future; import org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService;import org.springframework.beans.BeansException;import org.springframework.context.support.AbstractXmlApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext; import com.alibaba.dubbo.rpc.RpcContext; public class SearchConsumer {     private final String collection;    private AbstractXmlApplicationContext context;    private SolrSearchService searchService;     public SearchConsumer(String collection, Callable call) {        super();        this.collection = collection;        try {            context = call.call();            context.start();            searchService = (SolrSearchService) context.getBean("searchService");        } catch (BeansException e) {            e.printStackTrace();        } catch (Exception e) {            e.printStackTrace();        }    }     public Future asyncCall(final String q, final String type, final int start, final int rows) {        Future future = RpcContext.getContext().asyncCall(new Callable() {            public String call() throws Exception {                return search(q, type, start, rows);            }        });        return future;    }     public String syncCall(final String q, final String type, final int start, final int rows) {        return search(q, type, start, rows);    }     private String search(final String q, final String type, final int start, final int rows) {        return searchService.search(collection, q, type, start, rows);    }     public static void main(String[] args) throws Exception {        final String collection = "tinycollection";        final String beanXML = "search-consumer.xml";        final String config = SearchConsumer.class.getPackage().getName().replace('.', '/') + "/" + beanXML;        SearchConsumer consumer = new SearchConsumer(collection, new Callable() {            public AbstractXmlApplicationContext call() throws Exception {                final AbstractXmlApplicationContext context = new ClassPathXmlApplicationContext(config);                return context;            }        });         String q = "q=上海&fl=*&fq=building_type:1";        int start = 0;        int rows = 10;        String type = "xml";        for (int k = 0; k < 10; k++) {            for (int i = 0; i < 10; i++) {                start = 1 * 10 * i;                if (i % 2 == 0) {                    type = "xml";                } else {                    type = "json";                }                String result = consumer.syncCall(q, type, start, rows);                System.out.println(result);                // Future future = consumer.asyncCall(q, type, start,                // rows);                // System.out.println(future.get());            }        }    } }

执行该调用实现,可以远程调用提供方发布的服务。这种方式限制了服务调用方也必须使用Dubbo来开发调用的代码,也就是限制了编程的语言,而无论是对于内部还是外部,各个团队之间必然存在语言的多样性,如果限制了编程语言,那么开发的服务也只能在内部使用。

  • 基于标准Hessian协议接口的远程调用

下面,使用标准Hessian接口来实现远程调用,这时就不需要关心服务提供方的所使用的开发语言,因为最终是通过HTTP的方式来访问。我们需要下载Hessian对应语言的调用实现库,才能更方便地编程。

使用Java语言实现远程调用使用Java语言实现,代码如下所示:

package org.shirdrn.rpc.hessian; import org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService; import com.caucho.hessian.client.HessianProxyFactory; public class HessianConsumer {     public static void main(String[] args) throws Throwable {         String serviceUrl = "http://10.95.3.74:8080/http_dubbo/search";        HessianProxyFactory factory = new HessianProxyFactory();         SolrSearchService searchService = (SolrSearchService) factory.create(SolrSearchService.class, serviceUrl);         String q = "q=上海&fl=*&fq=building_type:1";        String collection = "tinycollection";        int start = 0;        int rows = 10;        String type = "xml";        String result = searchService.search(collection, q, type, start, rows);        System.out.println(result);    }}

我们只需要知道提供服务暴露的URL和服务接口即可,这里URL为http://10.95.3.74:8080/http_dubbo/search,接口为org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService。运行上面程序,可以调用提供方发布的服务。

使用Python语言实现远程调用使用Python客户端来进行远程调用,我们可以从https://github.com/bgilmore/mustaine下载,然后安装Hessian的代理客户端Python实现库:

git clone https://github.com/bgilmore/mustaine.gitcd mustainesudo python setup.py install

然后就可以使用了,使用Python进行远程调用的实现代码如下所示:

#!/usr/bin/python # coding=utf-8from mustaine.client import HessianProxy serviceUrl = 'http://10.95.3.74:8080/http_dubbo/search'q = 'q=*:*&fl=*&fq=building_type:1'start = 0rows = 10resType = 'xml'collection = 'tinycollection' if __name__ == '__main__':     proxy = HessianProxy(serviceUrl)     result = proxy.search(collection, q, resType, start, rows)     print result

运行上面程序,就可以看到远程调用的结果。(原创时延军(包含链接:http://shiyanjun.cn)

转发关注小编不迷路~~每天持续更新好文〜!!

1dbe0d6d9d4197101f6a7ac4f5908c7f.png

每天分享好文,让大家学习提升自己!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值