博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何将dubbo封装成http协议
阅读量:7091 次
发布时间:2019-06-28

本文共 9018 字,大约阅读时间需要 30 分钟。

很多小伙伴在测试的时候发现使用现成的工具无法对dubbo协议进行调用,我们现在就来看一下如何通过封装,将dubbo封装成一个http协议,然后再使用现成的http测试工具即可实现dubbo的直接调用。

首先,我们来看dubbo是啥
Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。从服务模型的角度来看,Dubbo采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方(Provider)和服务消费方(Consumer)两个角色。关于注册中心、协议支持、服务监控等内容,详见后面描述。
总体架构
Dubbo的总体架构,如图所示:

Paste_Image.png

Dubbo框架设计一共划分了10个层,而最上面的Service层是留给实际想要使用Dubbo开发分布式服务的开发者实现业务逻辑的接口层。图中左边淡蓝背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口, 位于中轴线上的为双方都用到的接口。

下面,结合Dubbo官方文档,我们分别理解一下框架分层架构中,各个层次的设计要点:

服务接口层(Service):该层是与实际业务逻辑相关的,根据服务提供方和服务消费方的业务设计对应的接口和实现。

配置层(Config):对外配置接口,以ServiceConfig和ReferenceConfig为中心,可以直接new配置类,也可以通过spring解析配置生成配置类。
服务代理层(Proxy):服务接口透明代理,生成服务的客户端Stub和服务器端Skeleton,以ServiceProxy为中心,扩展接口为ProxyFactory。
服务注册层(Registry):封装服务地址的注册与发现,以服务URL为中心,扩展接口为RegistryFactory、Registry和RegistryService。可能没有服务注册中心,此时服务提供方直接暴露服务。
集群层(Cluster):封装多个提供者的路由及负载均衡,并桥接注册中心,以Invoker为中心,扩展接口为Cluster、Directory、Router和LoadBalance。将多个服务提供方组合为一个服务提供方,实现对服务消费方来透明,只需要与一个服务提供方进行交互。
监控层(Monitor):RPC调用次数和调用时间监控,以Statistics为中心,扩展接口为MonitorFactory、Monitor和MonitorService。
远程调用层(Protocol):封将RPC调用,以Invocation和Result为中心,扩展接口为Protocol、Invoker和Exporter。Protocol是服务域,它是Invoker暴露和引用的主功能入口,它负责Invoker的生命周期管理。Invoker是实体域,它是Dubbo的核心模型,其它模型都向它靠扰,或转换成它,它代表一个可执行体,可向它发起invoke调用,它有可能是一个本地的实现,也可能是一个远程的实现,也可能一个集群实现。
信息交换层(Exchange):封装请求响应模式,同步转异步,以Request和Response为中心,扩展接口为Exchanger、ExchangeChannel、ExchangeClient和ExchangeServer。
网络传输层(Transport):抽象mina和netty为统一接口,以Message为中心,扩展接口为Channel、Transporter、Client、Server和Codec。
数据序列化层(Serialize):可复用的一些工具,扩展接口为Serialization、 ObjectInput、ObjectOutput和ThreadPool。

上面的介绍看不懂?没关系,我也是从别人的论坛抄的,它就是一个分布式的协议架构,解决企业级应用问题,学dubbo之路很漫长,涉及到多种协议、网络知识、zookeeper、spring,我们统统先不管它们,直接开始将它封装成我们熟悉的http协议。

预警:以下的代码不是dubbo的常规用法,是小编从dubbo的spring架构里拆出来的函数,做做工具还可以,不要拿来学做企业级应用,否则你会越走越远。为了工具更轻量级,我们只好将它从spring里抽离出来(小编搞了好久才完成抽离,是不是应该给个红包)
啥?你想学常规版本的dubbo应用,建议你还是去网上看dubbo教程吧,出门左拐。

我们开始正式的教程。首先,你要有个dubbo的jar包,这一点alibaba做的很好,将所有dubbo需要的类封装成了一个jar,中国平安的maven可以下载到(当然其他的网站也可以):

maven依赖是(如果在spring里整合出现jar冲突,请使用exclusion规避):
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.4.10</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
</exclusions>
</dependency>

接下来直接上代码:

首先,我们先上一个springmvc的controller来封装http,具体的配置请按照标准springmvc来封装,或者你也可以使用sevlet:
@Controller@RequestMapping(value = "/bsp", produces = "application/json; charset=utf8")public class CallBspController extends BaseController { /**  * @Description: 调用bsp  * @author: dingjingjing058  * @date: 2016年7月4日  */ @RequestMapping(value = "/callbsp.do", method = RequestMethod.GET, produces = "text/html;charset=UTF-8") @ResponseBody public String callBsp(@ModelAttribute BspForm bspForm, HttpSession httpSession) {  if (bspForm.getDubboUrl() == null || bspForm.getDubboAdress()== null) {   return new ResponseUtil<>(CodeEnum.PARAFORMSTMISS).toJSONString();  }  CallBspServiceImpl callBspServiceImpl=new CallBspServiceImpl();  return  callBspServiceImpl.callBsp(bspForm).toJSONString(); }}

http传入的form如下:

package com.pingan.testcloud.form;/*** ClassName:UserForm * @Description: bsp表单类* @author dingjingjing058* @date 2016年7月4日*/public class BspForm {private String dubboAdress;private String dubboUrl;private String paraMeters;/** * @return the dubboUrl */public String getDubboUrl() { return dubboUrl;}/** * @param dubboUrl the dubboUrl to set */public void setDubboUrl(String dubboUrl) { this.dubboUrl = dubboUrl;}/** * @return the paraMeters */public String getParaMeters() { return paraMeters;}/** * @param paraMeters the paraMeters to set */public void setParaMeters(String paraMeters) { this.paraMeters = paraMeters;}/** * @return the dubboAdress */public String getDubboAdress() { return dubboAdress;}/** * @param dubboAdress the dubboAdress to set */public void setDubboAdress(String dubboAdress) { this.dubboAdress = dubboAdress;}}

下面来封装dubbo,我们采用直接点对点rpc调用,不走dubbo注册中心:

package com.pingan.testcloud.service.impl;import java.util.HashMap;import java.util.Map;import java.util.Random;import com.alibaba.dubbo.config.ApplicationConfig;import com.alibaba.dubbo.config.ReferenceConfig;import com.alibaba.dubbo.rpc.service.GenericService;import com.paic.pafa.ac.dubbo.GenericParam;import com.paic.pafa.ac.dubbo.GenericResult;import com.pingan.testcloud.form.BspForm;import com.pingan.testcloud.service.CallBspService;import com.pingan.testcloud.units.CodeEnum;import com.pingan.testcloud.units.ResponseUtil;public class CallBspServiceImpl implements CallBspService { @Override public ResponseUtil
callBsp(BspForm bspForm) { //try { ReferenceConfig
reference = new ReferenceConfig
();//获取服务,注意GenericService是一个范类型,可以替代服务端任意类 reference.setUrl("dubbo://" + bspForm.getDubboAdress() + "/" + bspForm.getDubboUrl()); //设置dubbo服务端地址和端口号 reference.setInterface(bspForm.getDubboUrl()); //设置dubbo服务地址 reference.setGeneric(true); reference.setApplication(new ApplicationConfig("ff-test")); reference.setTimeout(10000); // reference.setRegistry(new // RegistryConfig("zookeeper://10.21.66.48:2181"));//如果你要走zookeep管控中心,就使用它 GenericService genericService = reference.get();//获取服务 GenericParam param = new GenericParam(); param.setParams(getParams(bspForm.getParaMeters())); GenericResult result = (GenericResult) genericService.$invoke("anymethod", new String[] {"com.paic.pafa.ac.dubbo.GenericParam"}, new Object[] { param }); //调用远程类的方法 reference.destroy();//这里一定要用,否则dubbo会一直连接,没几十次调用系统就会挂掉 return new ResponseUtil<>(CodeEnum.SUCCESS, result); //打印结果,ResponseUtil的封装见附件 //} //catch (Exception e) {// return new ResponseUtil<>(CodeEnum.FAILURE); //} } public Map
getParams(String dubboparaMeters) { String[] paraMeters={}; if(dubboparaMeters!=null) paraMeters = dubboparaMeters.split(","); Map
params = new HashMap
(); Map
esbRequest = new HashMap
(); Map
header = new HashMap
(); Map
content = new HashMap
(); esbRequest.put("content", content); esbRequest.put("header", header); String sendSerialNo = this.getSeqNo(); esbRequest.put("sendSerialNo", sendSerialNo); if(paraMeters!=null) for (String para : paraMeters) { String[] paraKeyValues = para.split(":"); esbRequest.put(paraKeyValues[0], paraKeyValues[1]); } params.put("esbRequest", esbRequest); params.put("timeOutMs", "30000"); params.put("systemId", "958537"); params.put("requestNo", sendSerialNo); return params; } public String getSeqNo() { return String.valueOf(System.currentTimeMillis() + System.nanoTime() + new Random().nextInt(2)); }}

ok了,dubbo就封装成http了。

附件:ResponseUtil的封装

package com.pingan.testcloud.units;import java.util.Date;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.ui.ModelMap;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.serializer.SerializeConfig;import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer;public class ResponseUtil
{ private CodeEnum responseEnum; private T data; public Logger logger = LoggerFactory.getLogger(this.getClass()); public ResponseUtil(CodeEnum responseEnum, T data){ this.responseEnum=responseEnum; this.data=data; } public ResponseUtil(CodeEnum responseEnum){ this.responseEnum=responseEnum; } public ResponseUtil( T data){ this.data=data; }@Override public String toString() { ModelMap modelMap = new ModelMap(); if (responseEnum != null) { modelMap.put("code", responseEnum.getCode()); modelMap.put("message", responseEnum.getMessage()); } if (data != null) { modelMap.put("data", data); } String jsonString=JSON.toJSONString(modelMap); logger.info("返回前端的结果为:"+jsonString); return jsonString; } /** * @return the responseEnum */ public CodeEnum getResponseEnum() { return responseEnum; } /** * @param responseEnum the responseEnum to set */ public void setResponseEnum(CodeEnum responseEnum) { this.responseEnum = responseEnum; } /** * @return the data */ public T getData() { return data; } /** * @param data the data to set */ public void setData(T data) { this.data = data; } public String toJSONString(){ ModelMap modelMap = new ModelMap(); if (responseEnum != null) { modelMap.put("code", responseEnum.getCode()); modelMap.put("message", responseEnum.getMessage()); } if (data != null) { modelMap.put("data", data); } SerializeConfig mapping = new SerializeConfig(); String dateFormat; dateFormat = "yyyy-MM-dd HH:mm:ss"; mapping.put(Date.class, new SimpleDateFormatSerializer(dateFormat)); String jsonString=JSON.toJSONString(modelMap,mapping); logger.info("返回前端的结果为:"+jsonString); return jsonString; } }

转载地址:http://rysql.baihongyu.com/

你可能感兴趣的文章
2013年3月20日
查看>>
mysql数据库的简单语句的介绍(1)
查看>>
HDU 2829 Lawrence (斜率DP)
查看>>
visual studio 2012 update3
查看>>
特征值和特征向量的几何意义、计算及其性质
查看>>
Spring framework3.2整合hibernate4.1报错:No Session found for current thread
查看>>
zqgame《每日一言》
查看>>
前端与后端分离的架构实例(一)
查看>>
LoadRunner性能分析指标解释
查看>>
OC语言类的本质和分类
查看>>
如何实现phpcms v9_4X版本tag的伪静态?
查看>>
w3c标准的selection对象介绍
查看>>
Python-类属性与对象属性之间的关系
查看>>
JavaScript 函数参数传递到底是值传递还是引用传递
查看>>
LeetCode:105_Construct Binary Tree from Preorder and Inorder Traversal | 根据前序和中序遍历构建二叉树 | Medium...
查看>>
解决 No Entity Framework provider found for the ADO.NET provider
查看>>
转 用 Chrome 运行Android应用
查看>>
编程心得--不积跬步无以至千里
查看>>
thinkphp学习笔记8—命名空间
查看>>
在项目中几个需要学习的知识
查看>>