[转载] 基于Dubbo的Hessian协议实现远程调用

转载自http://shiyanjun.cn/archives/349.html

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

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

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

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

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

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

01 package org.shirdrn.platform.dubbo.service.rpc.server;
02  
03 import java.io.IOException;
04 import java.util.HashMap;
05 import java.util.Map;
06  
07 import org.apache.commons.logging.Log;
08 import org.apache.commons.logging.LogFactory;
09 import org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService;
10 import org.shirdrn.platform.dubbo.service.rpc.utils.QueryPostClient;
11 import org.springframework.context.support.ClassPathXmlApplicationContext;
12  
13 public class SolrSearchServer implements SolrSearchService {
14  
15     private static final Log LOG = LogFactory.getLog(SolrSearchServer.class);
16     private String baseUrl;
17     private final QueryPostClient postClient;
18     private static final Map<String, FormatHandler> handlers = new HashMap<String, FormatHandler>(0);
19     static {
20         handlers.put("xml"new FormatHandler() {
21             public String format() {
22                 return "&wt=xml";
23             }
24         });
25         handlers.put("json"new FormatHandler() {
26             public String format() {
27                 return "&wt=json";
28             }
29         });
30     }
31  
32     public SolrSearchServer() {
33         super();
34         postClient = QueryPostClient.newIndexingClient(null);
35     }
36  
37     public void setBaseUrl(String baseUrl) {
38         this.baseUrl = baseUrl;
39     }
40  
41     public String search(String collection, String q, String type, int start, int rows) {
42         StringBuffer url = new StringBuffer();
43         url.append(baseUrl).append(collection).append("/select?").append(q);
44         url.append("&start=").append(start).append("&rows=").append(rows);
45         url.append(handlers.get(type.toLowerCase()).format());
46         LOG.info("[REQ] " + url.toString());
47         return postClient.request(url.toString());
48     }
49  
50     interface FormatHandler {
51         String format();
52     }
53 }

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

01 <?xml version="1.0" encoding="UTF-8"?>
02  
03 <beans xmlns="http://www.springframework.org/schema/beans"
04     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
05     xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
06      http://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd">
07  
08     <dubbo:application name="search-provider" />
09     <dubbo:registry
10         address="zookeeper://slave1:2188?backup=slave3:2188,slave4:2188" />
11     <dubbo:protocol name="hessian" port="8080" server="servlet" />
12     <bean id="searchService"
13         class="org.shirdrn.platform.dubbo.service.rpc.server.SolrSearchServer">
14         <property name="baseUrl" value="http://nginx-lbserver/solr-cloud/" />
15     </bean>
16     <dubbo:service
17         interface="org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService"
18         ref="searchService" path="http_dubbo/search" />
19  
20 </beans>

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

01 package org.shirdrn.platform.dubbo.context;
02  
03 import javax.servlet.ServletContextEvent;
04 import javax.servlet.ServletContextListener;
05  
06 import org.shirdrn.platform.dubbo.service.rpc.server.SolrSearchServer;
07 import org.springframework.context.support.ClassPathXmlApplicationContext;
08 import org.springframework.web.context.ContextLoader;
09  
10 public class SearchContextLoader extends ContextLoader implements ServletContextListener {
11  
12     @Override
13     public void contextDestroyed(ServletContextEvent arg0) {
14         // TODO Auto-generated method stub
15  
16     }
17  
18     @Override
19     public void contextInitialized(ServletContextEvent arg0) {
20         String config = arg0.getServletContext().getInitParameter("contextConfigLocation");
21         ClassPathXmlApplicationContext context = newClassPathXmlApplicationContext(config);
22         context.start();
23     }
24  
25 }

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

01 <?xml version="1.0" encoding="UTF-8"?>
02 <web-app id="WebApp_ID" version="2.4"
03     xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
04     xsi:schemaLocation="http://java.sun.com/xml/ns/j2eehttp://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
05     <display-name>http_dubbo</display-name>
06  
07     <listener>
08         <listener-class>org.shirdrn.platform.dubbo.context.SearchContextLoader</listener-class>
09     </listener>
10     <context-param>
11         <param-name>contextConfigLocation</param-name>
12         <param-value>classpath:search-provider.xml</param-value>
13     </context-param>
14  
15     <servlet>
16         <servlet-name>search</servlet-name>
17         <servlet-class>com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet</servlet-class>
18         <init-param>
19             <param-name>home-class</param-name>
20             <param-value>org.shirdrn.platform.dubbo.service.rpc.server.SolrSearchServer</param-value>
21         </init-param>
22         <init-param>
23             <param-name>home-api</param-name>
24             <param-value>org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService</param-value>
25         </init-param>
26         <load-on-startup>1</load-on-startup>
27     </servlet>
28     <servlet-mapping>
29         <servlet-name>search</servlet-name>
30         <url-pattern>/search</url-pattern>
31     </servlet-mapping>
32  
33     <welcome-file-list>
34         <welcome-file>index.html</welcome-file>
35         <welcome-file>index.htm</welcome-file>
36         <welcome-file>index.jsp</welcome-file>
37         <welcome-file>default.html</welcome-file>
38         <welcome-file>default.htm</welcome-file>
39         <welcome-file>default.jsp</welcome-file>
40     </welcome-file-list>
41 </web-app>

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

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

  • 基于Dubbo的Hessian协议远程调用

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

01 <?xml version="1.0" encoding="UTF-8"?>
02  
03 <beans xmlns="http://www.springframework.org/schema/beans"
04     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
05     xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
06      http://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd">
07  
08     <dubbo:application name="search-consumer" />
09     <dubbo:registry
10         address="zookeeper://slave1:2188?backup=slave3:2188,slave4:2188" />
11     <dubbo:reference id="searchService"
12         interface="org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService" />
13  
14 </beans>

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

01 package org.shirdrn.platform.dubbo.service.rpc.client;
02  
03 import java.util.concurrent.Callable;
04 import java.util.concurrent.Future;
05  
06 import org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService;
07 import org.springframework.beans.BeansException;
08 import org.springframework.context.support.AbstractXmlApplicationContext;
09 import org.springframework.context.support.ClassPathXmlApplicationContext;
10  
11 import com.alibaba.dubbo.rpc.RpcContext;
12  
13 public class SearchConsumer {
14  
15     private final String collection;
16     private AbstractXmlApplicationContext context;
17     private SolrSearchService searchService;
18  
19     public SearchConsumer(String collection, Callable<AbstractXmlApplicationContext> call) {
20         super();
21         this.collection = collection;
22         try {
23             context = call.call();
24             context.start();
25             searchService = (SolrSearchService) context.getBean("searchService");
26         catch (BeansException e) {
27             e.printStackTrace();
28         catch (Exception e) {
29             e.printStackTrace();
30         }
31     }
32  
33     public Future<String> asyncCall(final String q, final String type, final int start,final int rows) {
34         Future<String> future = RpcContext.getContext().asyncCall(new Callable<String>() {
35             public String call() throws Exception {
36                 return search(q, type, start, rows);
37             }
38         });
39         return future;
40     }
41  
42     public String syncCall(final String q, final String type, final int start, final introws) {
43         return search(q, type, start, rows);
44     }
45  
46     private String search(final String q, final String type, final int start, final introws) {
47         return searchService.search(collection, q, type, start, rows);
48     }
49  
50     public static void main(String[] args) throws Exception {
51         final String collection = "tinycollection";
52         final String beanXML = "search-consumer.xml";
53         final String config = SearchConsumer.class.getPackage().getName().replace(‘.‘‘/‘) + "/" + beanXML;
54         SearchConsumer consumer = new SearchConsumer(collection, newCallable<AbstractXmlApplicationContext>() {
55             public AbstractXmlApplicationContext call() throws Exception {
56                 final AbstractXmlApplicationContext context = newClassPathXmlApplicationContext(config);
57                 return context;
58             }
59         });
60  
61         String q = "q=上海&fl=*&fq=building_type:1";
62         int start = 0;
63         int rows = 10;
64         String type = "xml";
65         for (int k = 0; k < 10; k++) {
66             for (int i = 0; i < 10; i++) {
67                 start = 1 10 * i;
68                 if (i % 2 == 0) {
69                     type = "xml";
70                 else {
71                     type = "json";
72                 }
73                 String result = consumer.syncCall(q, type, start, rows);
74                 System.out.println(result);
75                 // Future<String> future = consumer.asyncCall(q, type, start,
76                 // rows);
77                 // System.out.println(future.get());
78             }
79         }
80     }
81  
82 }

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

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

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

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

01 package org.shirdrn.rpc.hessian;
02  
03 import org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService;
04  
05 import com.caucho.hessian.client.HessianProxyFactory;
06  
07 public class HessianConsumer {
08  
09     public static void main(String[] args) throws Throwable {
10  
11         String serviceUrl = "http://10.95.3.74:8080/http_dubbo/search";
12         HessianProxyFactory factory = new HessianProxyFactory();
13  
14         SolrSearchService searchService = (SolrSearchService) factory.create(SolrSearchService.class, serviceUrl);
15  
16         String q = "q=上海&fl=*&fq=building_type:1";
17         String collection = "tinycollection";
18         int start = 0;
19         int rows = 10;
20         String type = "xml";
21         String result = searchService.search(collection, q, type, start, rows);
22         System.out.println(result);
23     }
24 }

我们只需要知道提供服务暴露的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实现库:

1 git clone https://github.com/bgilmore/mustaine.git
2 cd mustaine
3 sudo python setup.py install

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

01 #!/usr/bin/python
02  
03 # coding=utf-8
04 from mustaine.client import HessianProxy
05  
06 serviceUrl = http://10.95.3.74:8080/http_dubbo/search
07 = ‘q=*:*&fl=*&fq=building_type:1‘
08 start = 0
09 rows = 10
10 resType = ‘xml‘
11 collection = ‘tinycollection‘
12  
13 if __name__ == ‘__main__‘:
14      proxy = HessianProxy(serviceUrl)
15      result = proxy.search(collection, q, resType, start, rows)
16      print result

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

参考链接

时间: 2024-08-03 07:18:16

[转载] 基于Dubbo的Hessian协议实现远程调用的相关文章

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

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

[转载] 基于Dubbo框架构建分布式服务

转载自http://shiyanjun.cn/archives/1075.html Dubbo是Alibaba开源的分布式服务框架,我们可以非常容易地通过Dubbo来构建分布式服务,并根据自己实际业务应用场景来选择合适的集群容错模式,这个对于很多应用都是迫切希望的,只需要通过简单的配置就能够实现分布式服务调用,也就是说服务提供方(Provider)发布的服务可以天然就是集群服务,比如,在实时性要求很高的应用场景下,可能希望来自消费方(Consumer)的调用响应时间最短,只需要选择Dubbo的F

android客户端与服务器交互数据(基于SAOP协议的远程调用标准,通过webservice可以将不同操作系统平台,不同语言,不同技术整合)

在PC机器java客户端中,需要一些库,比如XFire,Axis2,CXF等等来支持访问WebService,但是这些库并不适合我们资源有限的android手机客户端,做过JAVA ME的人都知道有KSOAP这个第三方的类库,可以帮助我们获取服务器端webService调用,当然KSOAP已经提供了基于android版本的jar包 首先下载KSOAP包:ksoap2-android-assembly-2.5.2-jar-with-dependencies.jar包 然后新建android项目 以

Hessian怎样实现远程调用

1.Spring中除了提供HTTP调用器方式的远程调用,还对第三方的远程调用实现提供了支持,其中提供了对Hessian的支持. Hessian是由Caocho公司发布的一个轻量级的二进制协议远程调用实现方案,Hessian也是基于HTTP协议的,其工作原理如下: (1).客户端: a.发送远程调用请求: 客户端程序—>发送远程调用请求—>Hessian客户端拦截器—>封装远程调用请求—>Hessian代理—>通过HTTP协议发送远程请求代理到服务端. b.接收远程调用响应:

Hessian轻量级二进制远程调用框架

Hessian轻量级二进制远程调用框架 Hessian是一个轻量级的二进制远程调用框架,官方文档地址,它主要包括Hessian远程调用协议.Hessian序列化协议以及客户端服务端代理等几部分,关于Hessian协议可以看下另外一篇文章Hessian远程调用及序列化协议.Hessian远程调用框架构建在Http协议之上,下面是示意图. 下面这个图是一次远程调用的过程 其中步骤3.4.5.6是核心过程,还要细化下, 步骤3:将远程方法调用转换为hessian调用,具体为,客户端首先要先和服务器端建

编写python调用dubbo接口hessian协议的例子

引子 今天有小伙伴问到了怎么用python调用dubbo的接口的方法,就随便写了这么一篇文章.其实dubbo接口可以使用loadrunner.jmeter等完成,最好是熟悉java语言的,那么编写起来就丝滑了很多哦 那么用python来调用其实也是很简单的,并不像大家想的那么复杂,基本3.4步就可以搞定,不要急,来看如何实现 接口说明 既然做接口测试,那接口的说明是必须的,问开发GG要,不要问从哪里来....大致包括如下内容: 接口地址 http://192.168.133.129:20880/

Spring Boot 2 整合 Dubbo 框架 ,实现 RPC 服务远程调用

一.Dubbo框架简介 1.框架依赖 图例说明: 1)图中小方块 Protocol, Cluster, Proxy, Service, Container, Registry, Monitor 代表层或模块,蓝色的表示与业务有交互,绿色的表示只对 Dubbo 内部交互. 2)图中背景方块 Consumer, Provider, Registry, Monitor 代表部署逻辑拓扑节点. 3)图中蓝色虚线为初始化时调用,红色虚线为运行时异步调用,红色实线为运行时同步调用. 4)图中只包含 RPC

转载 -- 基于原生JS与OC方法互相调用并传值(附HTML代码)

最近项目里面有有个商品活动界面,要与web端传值,将用户在网页点击的商品id 传给客户端,也就是js交互,其实再说明白一点就是方法的互相调用而已. 本文叙述下如何进行原生的JavaScript交互 本文包括JS调用OC方法并传值,OC调用JS方法并传值 本来想把html放进服务器里面,然后访问,但是觉得如果html在本地加载更有助于理解,特把html放进项目里 HTML代码 <!DOCTYPE html> <html> <head> <meta charset=&

基于Dubbo框架构建分布式服务 (二)

Dubbo是Alibaba开源的分布式服务框架,我们可以非常容易地通过Dubbo来构建分布式服务,并根据自己实际业务应用场景来选择合适的集群容错模式,这个对于很多应用都是迫切希望的,只需要通过简单的配置就能够实现分布式服务调用,也就是说服务提供方(Provider)发布的服务可以天然就是集群服务,比如,在实时性要求很高的应用场景下,可能希望来自消费方(Consumer)的调用响应时间最短,只需要选择Dubbo的Forking Cluster模式配置,就可以对一个调用请求并行发送到多台对等的提供方