我的日常

登录/注册
您现在的位置:论坛 资料库 开源社区 > 淘宝SOA框架Dubbo之Hessian(三)
总共48086条微博

动态微博

查看: 1980|回复: 0

淘宝SOA框架Dubbo之Hessian(三)

[复制链接]
admin    

1244

主题

544

听众

1万

金钱

管理员

  • TA的每日心情

    2021-2-2 11:21
  • 签到天数: 36 天

    [LV.5]常住居民I

    管理员

    跳转到指定楼层
    楼主
    发表于 2016-02-23 16:16:23 |只看该作者 |倒序浏览
    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. public interface SolrSearchService {
    3.         String search(String collection, String q, String type, int start, int rows);
    4. }
    复制代码

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


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



    提供方实现基于Dubbo封装的Hessian协议,实现接口SolrSearchService,实现代码如下所示:
    1. package org.shirdrn.platform.dubbo.service.rpc.server;

    2. import java.io.IOException;
    3. import java.util.HashMap;
    4. import java.util.Map;

    5. import org.apache.commons.logging.Log;
    6. import org.apache.commons.logging.LogFactory;
    7. import org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService;
    8. import org.shirdrn.platform.dubbo.service.rpc.utils.QueryPostClient;
    9. import org.springframework.context.support.ClassPathXmlApplicationContext;

    10. public class SolrSearchServer implements SolrSearchService {

    11.         private static final Log LOG = LogFactory.getLog(SolrSearchServer.class);
    12.         private String baseUrl;
    13.         private final QueryPostClient postClient;
    14.         private static final Map<String, FormatHandler> handlers = new HashMap<String, FormatHandler>(0);
    15.         static {
    16.                 handlers.put("xml", new FormatHandler() {
    17.                         public String format() {
    18.                                 return "&wt=xml";
    19.                         }
    20.                 });
    21.                 handlers.put("json", new FormatHandler() {
    22.                         public String format() {
    23.                                 return "&wt=json";
    24.                         }
    25.                 });
    26.         }

    27.         public SolrSearchServer() {
    28.                 super();
    29.                 postClient = QueryPostClient.newIndexingClient(null);
    30.         }

    31.         public void setBaseUrl(String baseUrl) {
    32.                 this.baseUrl = baseUrl;
    33.         }

    34.         public String search(String collection, String q, String type, int start, int rows) {
    35.                 StringBuffer url = new StringBuffer();
    36.                 url.append(baseUrl).append(collection).append("/select?").append(q);
    37.                 url.append("&start=").append(start).append("&rows=").append(rows);
    38.                 url.append(handlers.get(type.toLowerCase()).format());
    39.                 LOG.info("[REQ] " + url.toString());
    40.                 return postClient.request(url.toString());
    41.         }

    42.         interface FormatHandler {
    43.                 String format();
    44.         }
    45. }
    复制代码
    因为考虑到后面要使用标准Hessian接口来调用,这里接口方法参数全部使用内置标准类型。然后,我们使用Dubbo的配置文件进行配置,文件search-provider.xml的内容如下所示:
    1. <?xml version="1.0" encoding="UTF-8"?>

    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3.         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
    4.         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    5.      http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    6.         <dubbo:application name="search-provider" />
    7.         <dubbo:registry
    8.                 address="zookeeper://slave1:2188?backup=slave3:2188,slave4:2188" />
    9.         <dubbo:protocol name="hessian" port="8080" server="servlet" />
    10.         <bean id="searchService"
    11.                 class="org.shirdrn.platform.dubbo.service.rpc.server.SolrSearchServer">
    12.                 <property name="baseUrl" value="http://nginx-lbserver/solr-cloud/" />
    13.         </bean>
    14.         <dubbo:service
    15.                 interface="org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService"
    16.                 ref="searchService" path="http_dubbo/search" />

    17. </beans>
    复制代码


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

    2. import javax.servlet.ServletContextEvent;
    3. import javax.servlet.ServletContextListener;

    4. import org.shirdrn.platform.dubbo.service.rpc.server.SolrSearchServer;
    5. import org.springframework.context.support.ClassPathXmlApplicationContext;
    6. import org.springframework.web.context.ContextLoader;

    7. public class SearchContextLoader extends ContextLoader implements ServletContextListener {

    8.         @Override
    9.         public void contextDestroyed(ServletContextEvent arg0) {
    10.                 // TODO Auto-generated method stub

    11.         }

    12.         @Override
    13.         public void contextInitialized(ServletContextEvent arg0) {
    14.                 String config = arg0.getServletContext().getInitParameter("contextConfigLocation");
    15.                 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(config);
    16.                 context.start();
    17.         }

    18. }
    复制代码
    最后,配置Web应用部署描述符文件,web.xml内容如下所示:
    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <web-app id="WebApp_ID" version="2.4"
    3.         xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4.         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    5.         <display-name>http_dubbo</display-name>

    6.         <listener>
    7.                 <listener-class>org.shirdrn.platform.dubbo.context.SearchContextLoader</listener-class>
    8.         </listener>
    9.         <context-param>
    10.                 <param-name>contextConfigLocation</param-name>
    11.                 <param-value>classpath:search-provider.xml</param-value>
    12.         </context-param>

    13.         <servlet>
    14.                 <servlet-name>search</servlet-name>
    15.                 <servlet-class>com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet</servlet-class>
    16.                 <init-param>
    17.                         <param-name>home-class</param-name>
    18.                         <param-value>org.shirdrn.platform.dubbo.service.rpc.server.SolrSearchServer</param-value>
    19.                 </init-param>
    20.                 <init-param>
    21.                         <param-name>home-api</param-name>
    22.                         <param-value>org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService</param-value>
    23.                 </init-param>
    24.                 <load-on-startup>1</load-on-startup>
    25.         </servlet>
    26.         <servlet-mapping>
    27.                 <servlet-name>search</servlet-name>
    28.                 <url-pattern>/search</url-pattern>
    29.         </servlet-mapping>

    30.         <welcome-file-list>
    31.                 <welcome-file>index.html</welcome-file>
    32.                 <welcome-file>index.htm</welcome-file>
    33.                 <welcome-file>index.jsp</welcome-file>
    34.                 <welcome-file>default.html</welcome-file>
    35.                 <welcome-file>default.htm</welcome-file>
    36.                 <welcome-file>default.jsp</welcome-file>
    37.         </welcome-file-list>
    38. </web-app>
    复制代码
    启动Tomcat以后,就可以将提供方服务发布到服务注册中心,这里服务注册中心我们使用的是ZooKeeper集群,可以参考上面Dubbo配置文件search-provider.xml的配置内容。

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


    基于Dubbo的Hessian协议远程调用

    服务消费方,通过Dubbo配置文件来指定注册到注册中心的服务,配置文件search-consumer.xml的内容,如下所示:
    1. <?xml version="1.0" encoding="UTF-8"?>

    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3.         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
    4.         xsi:schemaLocation="http://www.springframework.org/schema/beans [url]http://www.springframework.org/schema/beans/spring-beans-2.5.xsd[/url]
    5.      [url]http://code.alibabatech.com/schema/dubbo[/url] [url]http://code.alibabatech.com/schema/dubbo/dubbo.xsd[/url]">

    6.         <dubbo:application name="search-consumer" />
    7.         <dubbo:registry
    8.                 address="zookeeper://slave1:2188?backup=slave3:2188,slave4:2188" />
    9.         <dubbo:reference id="searchService"
    10.                 interface="org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService" />

    11. </beans>
    复制代码
    然后,使用Java实现远程调用,实现代码如下所示:
    1. package org.shirdrn.platform.dubbo.service.rpc.client;

    2. import java.util.concurrent.Callable;
    3. import java.util.concurrent.Future;

    4. import org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService;
    5. import org.springframework.beans.BeansException;
    6. import org.springframework.context.support.AbstractXmlApplicationContext;
    7. import org.springframework.context.support.ClassPathXmlApplicationContext;

    8. import com.alibaba.dubbo.rpc.RpcContext;

    9. public class SearchConsumer {

    10.         private final String collection;
    11.         private AbstractXmlApplicationContext context;
    12.         private SolrSearchService searchService;

    13.         public SearchConsumer(String collection, Callable<AbstractXmlApplicationContext> call) {
    14.                 super();
    15.                 this.collection = collection;
    16.                 try {
    17.                         context = call.call();
    18.                         context.start();
    19.                         searchService = (SolrSearchService) context.getBean("searchService");
    20.                 } catch (BeansException e) {
    21.                         e.printStackTrace();
    22.                 } catch (Exception e) {
    23.                         e.printStackTrace();
    24.                 }
    25.         }

    26.         public Future<String> asyncCall(final String q, final String type, final int start, final int rows) {
    27.                 Future<String> future = RpcContext.getContext().asyncCall(new Callable<String>() {
    28.                         public String call() throws Exception {
    29.                                 return search(q, type, start, rows);
    30.                         }
    31.                 });
    32.                 return future;
    33.         }

    34.         public String syncCall(final String q, final String type, final int start, final int rows) {
    35.                 return search(q, type, start, rows);
    36.         }

    37.         private String search(final String q, final String type, final int start, final int rows) {
    38.                 return searchService.search(collection, q, type, start, rows);
    39.         }

    40.         public static void main(String[] args) throws Exception {
    41.                 final String collection = "tinycollection";
    42.                 final String beanXML = "search-consumer.xml";
    43.                 final String config = SearchConsumer.class.getPackage().getName().replace('.', '/') + "/" + beanXML;
    44.                 SearchConsumer consumer = new SearchConsumer(collection, new Callable<AbstractXmlApplicationContext>() {
    45.                         public AbstractXmlApplicationContext call() throws Exception {
    46.                                 final AbstractXmlApplicationContext context = new ClassPathXmlApplicationContext(config);
    47.                                 return context;
    48.                         }
    49.                 });

    50.                 String q = "q=上海&fl=*&fq=building_type:1";
    51.                 int start = 0;
    52.                 int rows = 10;
    53.                 String type = "xml";
    54.                 for (int k = 0; k < 10; k++) {
    55.                         for (int i = 0; i < 10; i++) {
    56.                                 start = 1 * 10 * i;
    57.                                 if (i % 2 == 0) {
    58.                                         type = "xml";
    59.                                 } else {
    60.                                         type = "json";
    61.                                 }
    62.                                 String result = consumer.syncCall(q, type, start, rows);
    63.                                 System.out.println(result);
    64.                                 // Future<String> future = consumer.asyncCall(q, type, start,
    65.                                 // rows);
    66.                                 // System.out.println(future.get());
    67.                         }
    68.                 }
    69.         }

    70. }
    复制代码

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


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


    使用Java语言实现远程调用

    使用Java语言实现,代码如下所示:
    1. package org.shirdrn.rpc.hessian;

    2. import org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService;

    3. import com.caucho.hessian.client.HessianProxyFactory;

    4. public class HessianConsumer {

    5.         public static void main(String[] args) throws Throwable {

    6.                 String serviceUrl = "http://10.95.3.74:8080/http_dubbo/search";
    7.                 HessianProxyFactory factory = new HessianProxyFactory();

    8.                 SolrSearchService searchService = (SolrSearchService) factory.create(SolrSearchService.class, serviceUrl);

    9.                 String q = "q=上海&fl=*&fq=building_type:1";
    10.                 String collection = "tinycollection";
    11.                 int start = 0;
    12.                 int rows = 10;
    13.                 String type = "xml";
    14.                 String result = searchService.search(collection, q, type, start, rows);
    15.                 System.out.println(result);
    16.         }
    17. }
    复制代码
    我们只需要知道提供服务暴露的URL和服务接口即可,这里URL为http://10.95.3.74:8080/http_dubbo/search,接口为org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService。运行上面程序,可以调用提供方发布的服务。

    参考链接


    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
    http://shiyanjun.cn/archives/349.html




    科帮网 1、本主题所有言论和图片纯属会员个人意见,与本社区立场无关
    2、本站所有主题由该帖子作者发表,该帖子作者与科帮网享有帖子相关版权
    3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和科帮网的同意
    4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
    5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
    6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
    7、科帮网管理员和版主有权不事先通知发贴者而删除本文


    JAVA爱好者①群:JAVA爱好者① JAVA爱好者②群:JAVA爱好者② JAVA爱好者③ : JAVA爱好者③

    红红火火恍恍惚惚
    快速回复
    您需要登录后才可以回帖 登录 | 立即注册

       

    关闭

    站长推荐上一条 /1 下一条

    发布主题 快速回复 返回列表 联系我们 官方QQ群 科帮网手机客户端
    快速回复 返回顶部 返回列表