Spring Cloud微服务交互设计总结

采用http协议进行数据交互

在spring cloud微服务交互中,基本上还是采用http协议进行数据交互。
与dubbo不同的是,http协议与编程语言无关,所以无法向dubbo一样,将抛出的Exception的内容进行序列化传到调用方,所以只能采用错误码的方式来传递异常消息。

数据的包装形式

统一数据格式

正常数据

{
    "code": 2000,
    "message": "bad server",
    "data":{...}
}

错误数据

{
    "code": 5000,
    "message": "bad server" }

区分数据与错误码

当调用正常的情况下,只需要返回完整的数据对象即可。

josnObject or jsonArray

当出现错误的情况下,只需要返回错误码即可。
在提供方接受到错误码后,可以再转化为java中的异常抛出

{
    "code": 5000,
    "message": "bad server" }

总结

正常数据和错误码如果统一用一个包装类进行包装,会带来一些弊端

  • 在取数据的时候还要进行同一的getData()操作,十分不便。
  • 返回结果没有Exception的概念。使用try…catch的方式处理业务,可以让业务代码更集中,异常可以统一处理,避免了在业务代码中各种if…else语句乱飞,异常处理不能统一,不好组织代码。

业务场景分析

微服务间的数据调用一般可以分为

  • 获取数据
  • 验证数据
  • 提交数据

数据查询

对于简单的查询,只关心查询结果数据,没必要再外包装一层getData()。

验证数据

比如authServer,在各个网关模块中都会引用authClient对前端提交过来的token进行校验。
在校验过程中可能会返回多种校验结果,校验成功并返回身份信息,token过期,token无效等。
token过期,token无效对于网关模块中并不需要进行处理,只要直接往上抛即可。
这种场景下,使用异常的异常的是比较适合的。

提交数据

在提交数据的时候,接口实现方为了流程的完整,对接受的参数进行校验,这种情况下,如果校验不通过,返回错误码。
使用try…catch很方便对业务进行统一判断,或者当前服务不知道如何处理这些异常,直接向上层服务抛出,如果使用if…else处理这些问题是有点力不从心。

try {
    a.postData(obj);
    a.postData(obj);
    a.postData(obj);
} catch(Exception e) {
    // doSomething or throw e
}

异常码是否应该统一问题

返回的业务异常码都应该有唯一的一个含义,对于上层的调用方,才能确定到底出了什么问题并决定是继续向上抛出或者处理它。

对于最外层的网关服务,给其他外部服务调用,基于以下需求,需要自定义一套异常码(外码)
当下游服务抛出很精确的异常码(内码),对于外部服务来讲,它是不关心的,或者基于之前和外部调用方定义的接口返回规范,我们必须异常信息转换。

例如,当insert数据失败抛出数据库错误,下游服务层层抛出,在网关中得到异常信息为

{
    "code": 7894,
    "message": "insert mysql error" }

对外,我们并不需要提供这么明确的信息,或者这个内部使用的异常码并未在接口调用规范中声明,我们希望返回给调用者的信息为

{
    "code": 5000,
    "message": "bad server" }

结论

异常码应该统一内码,外码可以与外部调用者进行协商定义自己的一套。
对于内部异常码和外部异常码的对应关系,在网关服务中声明好对应关系

    原文作者:Spring Cloud
    原文地址: https://blog.csdn.net/xinluke/article/details/75050384
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞