码迷,mamicode.com
首页 > 其他好文 > 详细

基于Dubbo的Hessian协议实现远程调用

时间:2015-05-09 18:55:46      阅读:283      评论:0      收藏:0      [点我收藏+]

标签:

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

下面,我们的思路是,先基于Dubbo封装的Hessian协议,实现提供方服务和消费方调用服务,双方必须都使用Dubbo来开发;然后,基于Dubbo封装的Hessian协议实现提供方服务,然后服务消费方使用标准的Hessian接口来进行远程调用,分别使用JavaPython语言来实现。而且,我们实现的提供方服务通过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);

}

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

基于DubboHessian协议实现提供方服务

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

package org.shirdrn.platform.dubbo.service.rpc.server;

 

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;

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<String, FormatHandler> handlers = new HashMap<String, FormatHandler>(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"?>

 

<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-2.5.xsd

     http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

 

    <dubbo:application name="search-provider" />

 

    <dubbo:registry

        address="zookeeper://slave1:2188?backup=slave3:2188,slave4:2188" />

    <dubbo:protocol name="hessian" port="8080" server="servlet" />

    <bean id="searchService"

        class="org.shirdrn.platform.dubbo.service.rpc.server.SolrSearchServer">

        <property name="baseUrl" value="http://nginx-lbserver/solr-cloud/" />

    </bean>

    <dubbo:service

        interface="org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService"

        ref="searchService" path="http_dubbo/search" />

 

</beans>

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

package org.shirdrn.platform.dubbo.context;

 

import javax.servlet.ServletContextEvent;

import javax.servlet.ServletContextListener;

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"?>

<web-app id="WebApp_ID" version="2.4"

    xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <display-name>http_dubbo</display-name>

 

    <listener>

        <listener-class>org.shirdrn.platform.dubbo.context.SearchContextLoader</listener-class>

    </listener>

    <context-param>

        <param-name>contextConfigLocation</param-name>

        <param-value>classpath:search-provider.xml</param-value>

    </context-param>

 

    <servlet>

        <servlet-name>search</servlet-name>

        <servlet-class>com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet</servlet-class>

        <init-param>

            <param-name>home-class</param-name>

            <param-value>org.shirdrn.platform.dubbo.service.rpc.server.SolrSearchServer</param-value>

        </init-param>

        <init-param>

            <param-name>home-api</param-name>

            <param-value>org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService</param-value>

        </init-param>

        <load-on-startup>1</load-on-startup>

    </servlet>

    <servlet-mapping>

        <servlet-name>search</servlet-name>

        <url-pattern>/search</url-pattern>

    </servlet-mapping>

 

    <welcome-file-list>

        <welcome-file>index.html</welcome-file>

        <welcome-file>index.htm</welcome-file>

        <welcome-file>index.jsp</welcome-file>

        <welcome-file>default.html</welcome-file>

        <welcome-file>default.htm</welcome-file>

        <welcome-file>default.jsp</welcome-file>

    </welcome-file-list>

</web-app>

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

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

  • 基于DubboHessian协议远程调用

服务消费方,通过Dubbo配置文件来指定注册到注册中心的服务,配置文件search-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-2.5.xsd

     http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

 

    <dubbo:application name="search-consumer" />

    <dubbo:registry

        address="zookeeper://slave1:2188?backup=slave3:2188,slave4:2188" />

    <dubbo:reference id="searchService"

        interface="org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService" />

</beans>

然后,使用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<AbstractXmlApplicationContext> 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<String> asyncCall(final String q, final String type, final int start, final int rows) {

        Future<String> future = RpcContext.getContext().asyncCall(new Callable<String>() {

            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<AbstractXmlApplicationContext>() {

            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<String> 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和服务接口即可,这里URLhttp://10.95.3.74:8080/http_dubbo/search,接口为org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService。运行上面程序,可以调用提供方发布的服务。

运行上面程序,就可以看到远程调用的结果。

 

基于Dubbo的Hessian协议实现远程调用

标签:

原文地址:http://www.cnblogs.com/yangmengdx3/p/4490814.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!