一. 背景知识

有时候微服务需要提供给多个消费者, 而不通过的消费者可能希望依据自身情况使用不同的协议. 另一方面, 有时候如果原本服务以 dubbo 协议提供服务, 但是为了调试或者监控方便, 我们也提供 rest 协议.

本文示例服务者同时提供 dubbo 和 rest 协议. 使用的 dubbo 版本为 2.7.1, springboot 版本为 2.1.5.

为了真实地模拟不同微服务之间的调用, 本文将服务者和消费分开. 对应的项目有两个, 分别为dubboshop-inventory(服务者)和dubboshop-order(消费者). 其结构如下:

dubboshop-inventory (库存微服务. 这个项目主要演示服务提供者角色)

|- dubbo-api: 包含服务接口和 DTO 对象. 打包成 `dubboshop-inventory:1.0.0-snapshot.jar`, 通过 `mvn install`到本地或者`mvn deploy`部署到私服, 在下面`dubboshop-order`项目中引用依赖.

|- fun.faceless.dubboshop.comms.entity.Result.java

|- fun.faceless.dubboshop.comms.entity.CommRetCode.java

|- dubbo-provider: 服务接口具体实现类

|- fun.faceless.dubboshop.inventory.dubboprovider.DubboApplication.java

|- fun.faceless.dubboshop.inventory.dubboprovider.impl.InventoryProviderImpl.java

dubboshop-order (订单微服务)

|- dubbo-provider: 订单服务的提供者, 同时是dubboshop-inventory服务的消费者. 这里主要演示其作为消费者的角色.

|- fun.faceless.dubboshop.order.dubboprovider.impl.OrderProviderImpl.java

二. 通用dubbo配置

本文两个项目都作为服务者, 也都支持dubbo和rest协议, 所以两者dubbo相关的依赖都包含以下几部分.

1) 首先引入通用 dubbo 依赖

org.apache.dubbo

dubbo-bom

pom

org.apache.dubbo

dubbo

${dubbo.version}

org.apache.thrift

libthrift

org.apache.dubbo

dubbo-spring-boot-starter

org.apache.dubbo

dubbo-dependencies-zookeeper

2.7.1

pom

log4j

log4j

slf4j-log4j12

org.slf4j

2) dubbo rest 依赖

org.apache.dubbo

dubbo-rpc-rest

org.apache.tomcat.embed

tomcat-embed-core

三. 服务者(Provider)实现

3.1 服务接口定义 dubbo-api

1) 数据传输对象定义 Result.java:

注意一定要定义默认构造函数和实现Serializable接口.

@Data

@NoArgsConstructor

@AllArgsConstructor

public class Result implements Serializable {

private static final long serialVersionUID = 1L;

public static String SUCCESS_MSG = "SUCC";

public static String DEFAULT_FAIL_MSG = "FAIL";

private String code;

private String msg;

private String subCode;

private String subMsg;

private String sign;

private Object data;

private Result(String code, String msg, Object data) {

this.code = code;

this.msg = msg;

this.data = data;

this.subCode = "";

this.subMsg = "";

this.sign = "";

}

/**

* Return succ result with given data.

* @return

*/

public static Result succ() {

return new Result(CommRetCode.OK, SUCCESS_MSG, null);

}

/**

* Return succ result with given data.

* @param msg

* @return

*/

public static Result succ(String msg) {

return new Result(CommRetCode.OK, msg, null);

}

/**

* Return failed result with given code, msg, and data

* @param code

* @param msg

* @param data

* @return

*/

public static Result fail(String code, String msg, Object data) {

return new Result(code, msg, data);

}

// 其他省略...

}

2) 通用返回值 CommRetCode.java

package fun.faceless.dubboshop.comms.entity;

public interface CommRetCode {

/** 一切 ok */

public final static String OK = "00000";

// 其他省略...

}

3) 定义服务提供者接口API: InventoryProvider.java

注意 REST 相关的注解都放在接口类中.

package fun.faceless.dubboshop.inventory.dubboprovider;

import javax.ws.rs.*;

import fun.faceless.dubboshop.comms.entity.Result;

import org.apache.dubbo.config.annotation.Service;

import org.apache.dubbo.rpc.protocol.rest.support.ContentType;

/**

* Order Dubbo Service

*/

@Service

@Path("inventory")

@Produces({ContentType.APPLICATION_JSON_UTF_8})

@Consumes({ContentType.APPLICATION_JSON_UTF_8})

public interface InventoryProvider {

@GET

@Path("hello")

Result hello();

/**

* 减扣商品库存

*/

@POST

@Path("debit")

Result debit(@QueryParam("goodsId") int goodsId, @QueryParam("amount") int amount);

}

3.2 服务实现具体实现

本节示例 Inventory 微服务即库存服务提供者.

1) 提供的服务的具体实现类 InventoryProviderImpl.java

package fun.faceless.dubboshop.inventory.dubboprovider.impl;

import fun.faceless.dubboshop.comms.entity.Result;

import fun.faceless.dubboshop.inventory.dao.InventoryDao;

import fun.faceless.dubboshop.inventory.dubboprovider.InventoryProvider;

import lombok.extern.slf4j.Slf4j;

import org.apache.dubbo.config.annotation.Service;

import org.springframework.beans.factory.annotation.Autowired;

@Slf4j

@Service

public class InventoryProviderImpl implements InventoryProvider {

@Autowired

InventoryDao inventoryDao;

@Override

public Result hello() {

return Result.succ("hello from inventory center");

}

@Override

public Result debit(int goodsId, int amount) {

log.debug("debit() goodsId: {}", goodsId);

log.debug("debit() amount: {}", amount);

inventoryDao.debit(goodsId, amount);

return Result.succ();

}

}

2) 服务启动类 DubboApplication.java

package fun.faceless.dubboshop.inventory.dubboprovider;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;

import org.mybatis.spring.annotation.MapperScan;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication

@EnableDubbo

@ComponentScan("fun.faceless.dubboshop.inventory")

@MapperScan("fun.faceless.dubboshop.inventory.dao.mapper")

public class DubboApplication {

public static void main(String[] args) {

SpringApplication.run(DubboApplication.class, args);

}

}

3) 模块配置文件 application-dev.yaml.

多协议支持的配置主要包含:

dubbo.config.multiple = true: 开启多个 protocol 配置绑定.

dubbo.protocols: 支持的 prottocols 列表.

# 此处省略项目其他配置...

# ========= Dubbo Provider ==============

dubbo:

config:

# 开启多个protocol配置绑定

multiple: true

# 注册中心配置

registry:

id: dubboshop-registry

address: zookeeper://yyadmin:2181

group: dubboshop

simplified: true

application:

name: dubboshop-inventory

id: dubboshop-inventory

logger: slf4j

qos-enable: false

qos-accept-foreign-ip: true

qos-port: 22223

protocols:

dubbo:

name: dubbo

port: 20882

server: netty4

rest:

name: rest

server: tomcat

port: 8082

scan:

# dubbo 服务提供者实现类所在包

base-packages: fun.faceless.dubboshop.inventory.dubboprovider

四. 消费者(Consumer)实现

本节示例 Order 微服务即作为订单的模块的服务者, 同时作为上面库存(Inventory)的消费者. 本例注重消费者.

1) 在pom.xml中添加服务者api的依赖:

fun.faceless.dubboshop.inventory

dubboapi

2) 在 OderProviderImpl.java 中消费接口.

package fun.faceless.dubboshop.order.dubboprovider.impl;

public class OrderProviderImpl implements OrderProvider {

@Autowired

private OrderDao orderDao;

// 通过 protocol="dubbo" 或者 protocol="rest" 指定使用的协议

@Reference(protocol="dubbo")

private InventoryProvider inventoryProvider;

@Override

public int createOrder(int userId, int goodsId, int orderCount) {

// 调用服务接口

Result debitResult = inventoryProvider.debit(goodsId, orderCount);

return this.saveOrder(userId, goodsId, orderCount);

}

// 省略其他代码...

}

五. 注意事项

5.1 返回值对象一定要有 默认构造函数 并实现 Serializiable 接口.

@Data

@NoArgsConstructor

@AllArgsConstructor

public class Result implements Serializable {

private static final long serialVersionUID = 1L;

// ...

如果没有默认构造函数, 则在使用 rest protocol 时, 返回值无法消费端反序列化. 消费端会报类似如下异常:

org.codehaus.jackson.map.JsonMappingException: No suitable constructor found for type [simple type, class fun.faceless.xxx.Result]: can not instantiate from JSON object (need to add/enable type information?)

如果没有实现 Serializiable 接口, 则在使用 dubbo protocol 时, 服务提供者无法正常序列化返回值. 服务 (provider) 端会报类似如下异常:

Caused by: org.apache.dubbo.remoting.RemotingException: Failed to send response: Response [id=2, version=2.0.2, status=20, event=false, error=null, result=RpcResult [result=Result(code=00000, msg=SUCC, subCode=, subMsg=, sign=, data=null), exception=null]], cause: java.lang.IllegalStateException: Serialized class fun.faceless.dubboshop.comms.entity.Result must implement java.io.Serializable

java.lang.IllegalStateException: Serialized class fun.faceless.dubboshop.comms.entity.Result must implement java.io.Serializable

5.2 调试时修改依赖模块的代码, 注意及时install/deploy

如果修改公共项目, 或者服务提供者接口所在的module, 在 mvn install 或 mvn deploy 之后, 一定也要记得再调用这些 module 的项目重新导入依赖, 否则会因为缓存, 即便重启消费者服务, 也无济于事.

5.3 REST 注解放到服务接口上

对于 rest protocol, 如果是将接口单独打包 (即不带实现类在包内) 提供给消费者. 那么需要将 JAX-RS 相关的注解放到接口上. 否则会报如下错误:

RESTEASY004600: You must use at least one, but no more than one http method annotation on XXX

这是因为 resteasy jax-rs 2客户端似乎不直接接受实现类。要使其工作,必须创建一个正确注释的接口。示例接口注解:

// InventoryProvider.java, 在 `dubboshop-inventory`项目`dubbo-api`模块中, 单独发布给消费者使用.

@Service

@Path("inventory")

@Produces({ContentType.APPLICATION_JSON_UTF_8})

@Consumes({ContentType.APPLICATION_JSON_UTF_8})

public interface InventoryProvider {

@GET

@Path("hello")

Result hello();

/**

* 减扣商品库存

*/

@POST

@Path("debit")

Result debit(@QueryParam("goodsId") int goodsId, @QueryParam("amount") int amount);

}

对应的实现类如下:

// InventoryProviderImpl.java, 在 `dubboshop-inventory`项目`dubbo-provider`模块中, 与消费者无关.

@Slf4j

@Service

public class InventoryProviderImpl implements InventoryProvider {

@Autowired

InventoryDao inventoryDao;

@Override

public Result hello() {

return Result.succ("hello from inventory center");

}

@Override

public Result debit(int goodsId, int amount) {

inventoryDao.debit(goodsId, amount);

return Result.succ();

}

}

5.4 消费端可以指定服务的服务方式

@Reference(protocol="dubbo")

// 或 @Reference(protocol="rest")

private InventoryProvider inventoryProvider;

java dubbo协议_Dubbo同时支持多种协议(以dubbo和rest为例)相关推荐

  1. dubbo协议_Dubbo框架支持多少种协议?各有什么特点?文中一一为你揭晓

    概述 Dubbo 允许配置多协议,在不同服务上支持不同协议或者同一服务上同时支持多种协议. 除了dubbo协议外, Dubbo框架还支持另外8种服务暴露协议,如rmi协议. hessian协议. ht ...

  2. Dubbo RPC框架都支持哪些协议

    RPC框架分通信协议和序列化协议 Dubbo框架支持多种通信协议和序列化协议,可以通过配置文件进行修改 Dubbo支持的通信协议 dubbo协议(默认) rmi协议 hessian协议 http协议 ...

  3. CXF:是一个开源Service框架支持多种协议:SOAP、XML/HTTP、RestfulHTTP和CORBA,同时可以和Spring集成。

    CXF:是一个开源Service框架 支持多种协议:SOAP.XML/HTTP.RestfulHTTP和CORBA,同时可以和Spring集成.

  4. 【WinSCP】强大的可视化远程文件传输 、管理工具 (支持多种协议,支持电脑与手机)

    目录 一.General 二.下载 三.简介 四.连接服务器 五.连接手机 六.WinSCP支持的传输协议简介 一.General 以前开发网站的时候,租了腾讯云的服务器,远程登录服务器进行一些文件操 ...

  5. php封装协议查看zip,支持的协议和封装协议

    用户评论: [#1] ohcc at 163 dot com [2015-11-05 18:45:38] echo$HTTP_RAW_POST_DATA;?> [#2] nguyenanthua ...

  6. 一个Windows远程工具,小巧但实用,支持RDP、SSH、SFTP、FTP等多种协议

    上次给大家推荐<一个C#开发的Windows远程桌面工具>,这个项目是基于 MSTSC的远程桌面工具,今天给大家推荐另外一个远程桌面工具,该工具小巧但非常实用.体验也非常好,支持多种协议连 ...

  7. 集成多种协议、用于USBC端口的快充协议芯片IP2723

    1. 特性 快充规格 集成 QC4/QC4+输出快充协议 - 兼容 QC2.0/QC3.0 - 支持 Class B 电压等级 集成 FCP 输出快充协议 集成 SCP 输出快充协议 集成 AFC 输 ...

  8. 支持GB28281协议的远程抓拍4G低功耗摄像头解决方案

    最近阳了在家里,趁身体恢复得差不多,想分享一下这款低功耗4G摄像头应用在石油行业的监控设备. 首先硬件设备是这样的,主控是合方圆4G模块G8100B,做成一个4G通讯板,通讯板有多个接口,能连接摄像头 ...

  9. dubbo原理_dubbo实现原理介绍

    一.什么是dubbo Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合).从服务模型的角度来看, Dubbo ...

最新文章

  1. python之路目录
  2. left join on and 与 left join on where的区别
  3. 论发展的十大关系。总结过去,正视未来!!!
  4. safari浏览器的使用tips
  5. JMetro版本5.2已发布
  6. Node.js 应用故障排查手册 —— 大纲与常规问题指标简介
  7. 消费者Heartbeat分析
  8. windows下,linux下elasticsearch安装插件head插件的步骤
  9. 华南理工大学811信号与系统真题
  10. 比特鹏哥第一节课笔记
  11. linux中磁盘阵列说明,常用磁盘阵列说明
  12. 个人发展战略基础理论
  13. 水处理相关工艺控制程序汇总(RXXW_Dor)
  14. 牛客刷题:放苹果(编程题)
  15. JGG | 中科院微生物研究所王军团队发现肠系膜淋巴系统可能为肠-肝轴第二通路...
  16. client elapsed: 0 ms, server elapsed: 1022 ms, timeout: 1000 ms,
  17. linux基础(五)----linux命令系统学习----系统管理命令
  18. Stata基础(一)
  19. cannot open file /storage/emulated/0/DCIM/Camera/yinpin.mp4 (Permission denied)
  20. php redis 详细操作

热门文章

  1. android ant批量打包
  2. Nginx之URL重写
  3. SpringBoot + uniApp实现的掌上生鲜超市购物微信小程序系统 附带详细运行指导视频
  4. evc小项目:Gps功分器测试
  5. 微信中html5获取手机号,微信小程序用户授权获取手机号(getPhoneNumber)
  6. 乔布斯的简历17.4万拍卖,HR看了想打人……
  7. Telegram-“只能给双向联系人发送消息”的错误信息
  8. 掌握一种基本图形元素光栅化算法,利用OpenGL实现直线光栅化的DDA算法。
  9. excel文件合并小工具
  10. HDMI采集卡芯片方案