全部产品
云市场

服务总线

更新时间:2019-06-06 11:08:02

1. 整体介绍

1.1. 设计目标

用于规范应用之间行为表达方式和对结果的预期。

  • 对于服务提供方来讲,通过服务标准化,能够清晰而简洁的表达本服务提供了哪些接口、定义、以及他们所应实现的具体功能,并且任何对该服务所提供的能力有依赖的应用,都必须按照这套接口来实现服务供应;
  • 对于服务依赖方来讲,(即使用该服务的应用)能够清晰而简洁的表达他所依赖的接口有哪些,分别期望这些接口完成什么样的具体功能,并且任何为其提供服务的应用,只要遵循相同的服务模型,即可实现服务提供方的替换。

1.2. 概念定义

对服务模型的定义,如下几点说明:

  1. 服务即接口。我们这里定义的服务,从概念上理解,这是一个对应用能力的抽象表达;但是从实际操作层面,服务的实际体现方式,就是Restful风格的HTTP接口。
  2. 接口是分组的。分组的原则是能力原子化,即我们按照接口的能力范围,将一组完成功能闭环的接口标定为一组。并且,我们将这一组接口,定义为“一个服务模型”。
  3. 服务模型是受管控的。目前,每一个服务模型都是由行业小二在后台制定并发布。ISV在实践过程中可以根据实际情况,向相关小儿提出调整意见。
  4. 服务模型是有版本的。一个基础服务模型,随着不用ISV、不同场景的需求,会有版本迭代。因此,唯一确定一个服务模型提供的接口信息的,是模型ID+版本。

2. 服务管控流程

image.png

3. 服务模型的管理

服务模型的定义,是由平台统一管控的。ISV在应用开发和实践中,如果需要修改或者全新定义服务模型,请联系相关人员或者提交工单。

4. 服务模型的声明

模型的声明分两个角度:服务模型的依赖和服务模型的提供。一个应用在正式上架前,需要声明该应用所提供的服务和所依赖的服务。模型的声明入口,见下图:
image.png

4.1 服务的依赖配置

如下图所示:
image.png

上图中显示,服务的依赖,是需要指定到模型下面的某一个或者多个接口的。进入配置页面,如下:
image.png

4.2 服务的提供配置

如下图所示:
image.png

图中,需要用户指定的,除了模型之外,还有指定模型版本和提供该服务能力的节点,如上红色区域。

5. 服务模型的调试

应用开发完成之后,如果应用依赖或者提供服务模型的能力,那势必需经过集成调试,方可上架。应用的调试分成两类:服务依赖的调试、服务提供的调试。

5.1 服务依赖的调试

当应用依赖一个服务时,它的调试过程需要有一个虚拟的服务提供者来为该应用提供服务,并且监测每一次应用的服务调用。
image.png

5.2 服务提供的调试

当应用提供一个服务时,它的调试过程需要有一个虚拟的客户端,来发起对该应用该服务的调用,并且监测每一次应用的服务调用。

首先,进入AppKey -> 查看,指定要调试的服务,并启动客户端,启动之后界面如下:

image.png

启动之后,ISV就可以进入每一个接口,模拟该接口像当前应用发起服务调试了。用户可以在调试界面看到服务调用的数据image.png

6. 服务模型的集成

在项目集成阶段,当应用之间有服务依赖关系时,需要在集成工作台,将服务的提供方和依赖方关联起来:
服务集成页面

7. ISV开发示例

服务模型的开发主要分为两个部分:服务提供和服务依赖。服务提供,为第三方提供标准化的的服务接口;服务依赖,使用第三方提供的服务。

7.1 案例介绍

以实现停车场服务模型(模型ID为:“parking”)的API(标识符为:“qrcodePayAndPush”)为例,分别介绍如何实现一个托管应用,**服务提供方如何实现声明的服务模型的服务能力,以及服务依赖方如何调用该服务**。
模型定义如下:
image.png

qrcodePayAndPush接口定义如下:
image.png
image.png

7.2 服务提供的开发示例

需要实现服务模型中的API定义,应用必须实现声明的服务模型的所有的API定义,并且实现的API 入参和出参需要完全保持一致。
示例代码

  1. @Slf4j
  2. @Controller
  3. @Configuration
  4. @RequestMapping("/parking")
  5. public class ParkingController {
  6. @Resource
  7. private ParkingService parkingService;
  8. /**
  9. * 发送支付二维码到显示屏(出场时)
  10. *
  11. * @param qrcodeRequest
  12. * @return
  13. */
  14. @PostMapping("/qrcodePayAndPush")
  15. public @ResponseBody
  16. BaseResponse<PushQrcodeResponse> receiveMessage(
  17. @RequestBody BaseRequest<PushQrcodeRequest> qrcodeRequest) {
  18. System.out.println("qrcodeRequest info: " + qrcodeRequest.toString());
  19. PushQrcodeResponse pushQrcodeResponse = new PushQrcodeResponse();
  20. pushQrcodeResponse.setQrcodeUrl("www.xxxx.com/qrcodePayAndPush");
  21. BaseResponse<PushQrcodeResponse> response = new BaseResponse<>();
  22. response.setId(qrcodeRequest.getId());
  23. response.setData(pushQrcodeResponse);
  24. return response;
  25. }
  26. }
  27. public class PushQrcodeRequest implements Serializable {
  28. private static final long serialVersionUID = 1L;
  29. /**
  30. * deviceUuid
  31. */
  32. private String campusId;
  33. /**
  34. * 订单号
  35. */
  36. private String tradeNo;
  37. /**
  38. * 需要支付的金额
  39. */
  40. private String totalAmount;
  41. /**
  42. * 设备uuid
  43. */
  44. private String deviceUuid;
  45. public String getCampusId() {
  46. return campusId;
  47. }
  48. public void setCampusId(String campusId) {
  49. this.campusId = campusId;
  50. }
  51. public String getTradeNo() {
  52. return tradeNo;
  53. }
  54. public void setTradeNo(String tradeNo) {
  55. this.tradeNo = tradeNo;
  56. }
  57. public String getTotalAmount() {
  58. return totalAmount;
  59. }
  60. public void setTotalAmount(String totalAmount) {
  61. this.totalAmount = totalAmount;
  62. }
  63. public String getDeviceUuid() {
  64. return deviceUuid;
  65. }
  66. public void setDeviceUuid(String deviceUuid) {
  67. this.deviceUuid = deviceUuid;
  68. }
  69. @Override
  70. public String toString() {
  71. final StringBuilder sb = new StringBuilder("{");
  72. sb.append("\"campusId\":\"")
  73. .append(campusId == null ? "" : campusId).append('\"');
  74. sb.append(",\"tradeNo\":\"")
  75. .append(tradeNo == null ? "" : tradeNo).append('\"');
  76. sb.append(",\"totalAmount\":")
  77. .append(totalAmount);
  78. sb.append(",\"deviceUuid\":\"")
  79. .append(deviceUuid == null ? "" : deviceUuid).append('\"');
  80. sb.append('}');
  81. return sb.toString();
  82. }
  83. }
  84. public class PushQrcodeResponse implements Serializable {
  85. private static final long serialVersionUID = 1L;
  86. /**
  87. * qrcodeUrl
  88. */
  89. private String qrcodeUrl;
  90. public String getQrcodeUrl() {
  91. return qrcodeUrl;
  92. }
  93. public void setQrcodeUrl(String qrcodeUrl) {
  94. this.qrcodeUrl = qrcodeUrl;
  95. }
  96. @Override
  97. public String toString() {
  98. final StringBuilder sb = new StringBuilder("{");
  99. sb.append("\"qrcodeUrl\":\"")
  100. .append(qrcodeUrl == null ? "" : qrcodeUrl).append('\"');
  101. sb.append('}');
  102. return sb.toString();
  103. }
  104. }
  105. public class BaseResponse<T> implements Serializable {
  106. private static final long serialVersionUID = 1L;
  107. /**
  108. * request里的全局唯一id透传
  109. */
  110. private String id;
  111. /**
  112. * code
  113. */
  114. private int code = 200;
  115. /**
  116. * 失败时必填,错误调试信息;成功时不填
  117. */
  118. private String message;
  119. /**
  120. * 失败时必填,用户可理解语言描述的错误信息;成功时不填
  121. */
  122. private String localizedMsg;
  123. /**
  124. * 成功时必填,失败时选填
  125. */
  126. private T data;
  127. public String getId() {
  128. return id;
  129. }
  130. public void setId(String id) {
  131. this.id = id;
  132. }
  133. public int getCode() {
  134. return code;
  135. }
  136. public void setCode(int code) {
  137. this.code = code;
  138. }
  139. public String getMessage() {
  140. return message;
  141. }
  142. public void setMessage(String message) {
  143. this.message = message;
  144. }
  145. public String getLocalizedMsg() {
  146. return localizedMsg;
  147. }
  148. public void setLocalizedMsg(String localizedMsg) {
  149. this.localizedMsg = localizedMsg;
  150. }
  151. public T getData() {
  152. return data;
  153. }
  154. public void setData(T data) {
  155. this.data = data;
  156. }
  157. @Override
  158. public String toString() {
  159. final StringBuilder sb = new StringBuilder("{");
  160. sb.append("\"id\":\"")
  161. .append(id == null ? "" : id).append('\"');
  162. sb.append(",\"code\":")
  163. .append(code);
  164. sb.append(",\"message\":\"")
  165. .append(message == null ? "" : message).append('\"');
  166. sb.append(",\"localizedMsg\":\"")
  167. .append(localizedMsg == null ? "" : localizedMsg).append('\"');
  168. sb.append(",\"data\":")
  169. .append(data);
  170. sb.append('}');
  171. return sb.toString();
  172. }
  173. }
  174. public class BaseRequest<T> implements Serializable {
  175. private static final long serialVersionUID = 1L;
  176. /**
  177. * request里的全局唯一id透传
  178. */
  179. private String id;
  180. /**
  181. * 请求协议版本
  182. */
  183. private String version;
  184. /**
  185. * 失败时必填,错误调试信息;成功时不填
  186. */
  187. private Map<String, Object> request;
  188. /**
  189. * 失败时必填,用户可理解语言描述的错误信息;成功时不填
  190. */
  191. private T params;
  192. public String getId() {
  193. return id;
  194. }
  195. public void setId(String id) {
  196. this.id = id;
  197. }
  198. public String getVersion() {
  199. return version;
  200. }
  201. public void setVersion(String version) {
  202. this.version = version;
  203. }
  204. public Map<String, Object> getRequest() {
  205. return request;
  206. }
  207. public void setRequest(Map<String, Object> request) {
  208. this.request = request;
  209. }
  210. public T getParams() {
  211. return params;
  212. }
  213. public void setParams(T params) {
  214. this.params = params;
  215. }
  216. @Override
  217. public String toString() {
  218. final StringBuilder sb = new StringBuilder("{");
  219. sb.append("\"id\":\"")
  220. .append(id == null ? "" : id).append('\"');
  221. sb.append(",\"version\":\"")
  222. .append(version == null ? "" : version).append('\"');
  223. sb.append(",\"request\":")
  224. .append(request);
  225. sb.append(",\"params\":")
  226. .append(params);
  227. sb.append('}');
  228. return sb.toString();
  229. }
  230. }

7.3 服务依赖的开发示例

A. 开发包依赖

  1. <dependency>
  2. <groupId>com.aliyun.api.gateway</groupId>
  3. <artifactId>sdk-core-java</artifactId>
  4. <version>1.6.0.3</version>
  5. </dependency>

B. 示例代码

  1. HttpClientBuilderParams builderParams = new HttpClientBuilderParams();
  2. builderParams.setAppKey("1234567"); // 请填写正确的AppKey
  3. builderParams.setAppSecret("6726732dsfdsdsfdsfds"); // 请填写正确的AppSecret
  4. ApacheHttpClient apacheHttpClient = new ApacheHttpClient(builderParams);
  5. IoTApiRequest request = new IoTApiRequest();
  6. //设置api的版本,并非模型中定义的版本,目前固定为 1.0.0
  7. request.setApiVer("1.0.0");
  8. //如果需要登陆,设置当前的会话的token
  9. //设置参数
  10. request.putParam("campusId", "testCampusId");
  11. request.putParam("tradeNo", "tradeNoTest");
  12. request.putParam("totalAmount", "12.2");
  13. request.putParam("deviceUuid", "testUuid");
  14. //请求参数域名、path、request
  15. String host = "service-mesh.api-iot.cn-shanghai.aliyuncs.com";
  16. String path = "/parking/qrcodePayAndPush";
  17. System.out.println(JSON.toJSONString(request));
  18. ApiRequest apiRequest = new ApiRequest(HttpScheme.HTTP, host,
  19. HttpMethod.POST_BODY, path, JSON.toJSONBytes(request));
  20. apiRequest.setHttpConnectionMode(HttpConnectionModel.MULTIPLE_CONNECTION);
  21. ApiResponse response = apacheHttpClient.sendSyncRequest(apiRequest);
  22. System.out.println(request.getId());
  23. System.out.println(
  24. "response code = " + response.getCode() + " response message = " + response.getMessage()
  25. + " response content = " + new String(response.getBody(),
  26. "utf-8"));