[转载] 基于Dubbo的Hessian协议实现远程调用
2015-07-02 00:21
561 查看
转载自http://shiyanjun.cn/archives/349.html
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语言定义一个搜索服务的接口,代码如下所示:
上面接口提供了搜索远程调用功能。
基于Dubbo的Hessian协议实现提供方服务
提供方实现基于Dubbo封装的Hessian协议,实现接口SolrSearchService,实现代码如下所示:
因为考虑到后面要使用标准Hessian接口来调用,这里接口方法参数全部使用内置标准类型。然后,我们使用Dubbo的配置文件进行配置,文件search-provider.xml的内容如下所示:
因为使用Tomcat发布提供方服务,所以我们需要实现Spring的org.springframework.web.context.ContextLoader来初始化应用上下文(基于Spring的IoC容器来管理服务对象)。实现类SearchContextLoader代码如下所示:
最后,配置Web应用部署描述符文件,web.xml内容如下所示:
启动Tomcat以后,就可以将提供方服务发布到服务注册中心,这里服务注册中心我们使用的是ZooKeeper集群,可以参考上面Dubbo配置文件search-provider.xml的配置内容。
下面,我们通过两种方式来调用已经注册到服务注册中心的服务。
基于Dubbo的Hessian协议远程调用
服务消费方,通过Dubbo配置文件来指定注册到注册中心的服务,配置文件search-consumer.xml的内容,如下所示:
然后,使用Java实现远程调用,实现代码如下所示:
执行该调用实现,可以远程调用提供方发布的服务。
这种方式限制了服务调用方也必须使用Dubbo来开发调用的代码,也就是限制了编程的语言,而无论是对于内部还是外部,各个团队之间必然存在语言的多样性,如果限制了编程语言,那么开发的服务也只能在内部使用。
基于标准Hessian协议接口的远程调用
下面,使用标准Hessian接口来实现远程调用,这时就不需要关心服务提供方的所使用的开发语言,因为最终是通过HTTP的方式来访问。我们需要下载Hessian对应语言的调用实现库,才能更方便地编程。
使用Java语言实现远程调用
使用Java语言实现,代码如下所示:
我们只需要知道提供服务暴露的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实现库:
然后就可以使用了,使用Python进行远程调用的实现代码如下所示:
运行上面程序,就可以看到远程调用的结果。
参考链接
https://github.com/alibaba/dubbo
http://alibaba.github.io/dubbo-doc-static/Home-zh.htm
http://alibaba.github.io/dubbo-doc-static/User+Guide-zh.htm
http://alibaba.github.io/dubbo-doc-static/Developer+Guide-zh.htm
http://alibaba.github.io/dubbo-doc-static/Administrator+Guide-zh.htm
http://alibaba.github.io/dubbo-doc-static/FAQ-zh.htm
http://hessian.caucho.com/#HessianImplementationsDownload
https://github.com/bgilmore/mustaine
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语言定义一个搜索服务的接口,代码如下所示:
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 | } |
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 > |
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 = new ClassPathXmlApplicationContext(config); |
22 | context.start(); |
23 | } |
24 |
25 | } |
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 > |
下面,我们通过两种方式来调用已经注册到服务注册中心的服务。
基于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 > |
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 int rows) { |
43 | return search(q,type,start,rows); |
44 | } |
45 |
46 | private String search( final String q, final String type, final int start, final int rows) { |
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, new Callable<AbstractXmlApplicationContext>() { |
55 | public AbstractXmlApplicationContext call() throws Exception { |
56 | final AbstractXmlApplicationContext context = new ClassPathXmlApplicationContext(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 | } |
使用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 |
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 = '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 | result |
参考链接
https://github.com/alibaba/dubbo
http://alibaba.github.io/dubbo-doc-static/Home-zh.htm
http://alibaba.github.io/dubbo-doc-static/User+Guide-zh.htm
http://alibaba.github.io/dubbo-doc-static/Developer+Guide-zh.htm
http://alibaba.github.io/dubbo-doc-static/Administrator+Guide-zh.htm
http://alibaba.github.io/dubbo-doc-static/FAQ-zh.htm
http://hessian.caucho.com/#HessianImplementationsDownload
https://github.com/bgilmore/mustaine
相关文章推荐
- 某会已疯
- Android-Webview支持缩放并隐藏讨厌的缩放控制条
- [学习笔记—Objective-C]《Objective-C 程序设计 第6版》第七章 类
- 2015070109 - 水杯
- Android Studio创建项目
- Remoting
- [转载] 基于Dubbo框架构建分布式服务
- Java容器:HashMap和HashSet解析
- 从XML文件乱码问题,探寻其背后的原理 (ZHUAN)
- Linux下编译C/C++时,出现/usr/bin/ld: cannot find -l*** 错误的处理
- [转载] Dubbo实现RPC调用使用入门
- 运行C++程序是出现错误:cannot open Debug/1.exe for writing
- [leetcode] 115.Distinct Subsequences
- [转载] Dubbo架构设计详解
- java设计模式之建造者模式
- Android手动显示和隐藏软键盘方法总结
- Oracle 11g行列互换pivot和unpivot说明
- VIM code complete: YouCompleteMe
- 2015070108 - EffactiveJava笔记 - 第49条 基本类型优于装箱类型(1)
- 简要地写出一个.NET Remoting的示例