关于后端:如何做好上下游对接

3次阅读

共计 3204 个字符,预计需要花费 9 分钟才能阅读完成。

本人的模块,经常要对接上下游,如何在对接的过程中,保障正确性呢?
个别和上下游对接的有两种形式:

一:接口对接

在接口对接中,须要留神上面的点。
1,首先和上下游约定接口的性能是什么,这往往和承载的业务有关系,须要提前在产品宣讲阶段 + 产品评审阶段定义分明,每个接口预期的性能都应该精确的形容在接口正文上。

2,约定好接口的性能后,紧接着就是约定好接口的入参和返回值数据结构,确定参数数据结构中哪些是必传的,哪些是不用传的,他们的传值范畴是什么?
确定返回值的数据结构是什么。什么时候失败,什么时候胜利等等,都须要定义分明。这里比拟举荐罕用的 yapi 治理接口。
另外留神字典保护,比方 sex 中的 ” 未知 ” “ 男 ” “ 女 ”,是对立应用中文示意,还是 0 1 2 编码表示,还是英文示意。如此这类的,都要标准化。另外字段名称也尽量对立。
对于接口返回集体倡议应用上面这种通用的数据结构

public class Message<T> {
 private boolean success
 private String errcode
 private String errmsg
 private T data

public Message(boolean success,String errcode,String errmsg,T data){
this.success=success;
this.errcode=errcode;
this.errmsg=errmsg;
this.data=data;
}

// 返回胜利
 public Message success(T  data){return new Message(true,"0","",data);
 }

// 返回失败
 public Message fail(String msg){return new Message(false,"400","param is illegal",null);
 }
}

对于返回胜利还是失败,这里有一些案例值得思考

pubilc User findOneUserById(Long userId){// 这个 userId 应该是之前系统生成的,那么依据这个 userId,在数据中应该肯定能查到数据,但如果查不到呢?此时应该返会失败。}

pubilc User findOneUserByName(String selectName){// 依据 selectName 去搜寻的时候,在数据库中可能查不到,这种状况是失常的,因而要返回胜利。提醒没有数据。}

还有比方依据用户手机号作为惟一标识,插入用户信息,如果第一个申请曾经插入胜利,当第二个申请携带雷同的参数插入时,接口是返回胜利,还是返回失败?这在上下游对接的过程中比拟重要

3,接口解决
3.1 在接口 impl 层面的第一件事件,先打印申请参数日志。在接口实现的关键点也须要打印日志。这样不便后续定位问题边界。

3.2 紧接着第二件事就是依照约定的数据结构进行参数校验,对谬误的参数申请做好拦挡,避免他们捣鬼零碎,毁坏数据。这一点可能很多人疏忽,但其实是最重要的

3.3 对于非必传参数,接口应该如何解决,也须要明确,这一点个别反馈在该接口在不同的场景中应用。

3.4 解决异样,不要应用抛异样的形式退出某个办法,并毫无保留的把异样信息传递给上下游,除非办法有捕捉异样,并且晓得怎么解决。

3.5 明确返回值和错误信息:如果解决胜利返回 success=true。如果失败,不能仅仅返回失败就完事了,必须在返回信息明确的告知上下游是什么起因导致这次申请解决失败,是参数校验不通过,缺省哪些值? 还是要操作的数据,在数据库中不存在?等等。

3.6 接口开发结束,对接口进行单元测试,我集体认为这是很重要的一步:依据步骤 1 的正文,必须依照这些预期性能进行测试,如果预期提供的性能,在单元测试中胜利通过,那么阐明该接口提供的性能基本上是牢靠的,能够和上下游对接了。但这还不够,单元测试的参数最好分各种各样的状况,如果你模仿的参数状况比实在用户收回的参数组合多,并且返回都依照预期响应,那么该接口能够说是合格的了。这样,你就能够拍着胸脯说没有 bug 了,能够去开发另外的接口了。

一般来说,接口对接做好下面就足够了,然而还不够!接口设计的时候还必须思考以下事件:

a,幂等:也就是说雷同的申请来了(可能是多线程并发申请,也可能是反复申请),该接口如何实现这一点,这个别反馈在增删改等接口。
接口该怎么反对幂等?一种形式是利用数据库的惟一索引来。还有利用分布式锁(为什么不必 jvm 锁?)

b,分布式事务:比方该接口是一个扣减库存的接口,那么在和上下游对接的过程中,须要留神如何解决分布式事务。谁负责解决分布式事务?
在泛滥的我的项目教训,我得出一个论断,分布式事务,肯定是利用最终一致性 +ack 的思维解决,两阶段,三阶段不适宜大规模的零碎

c,并发:这可能是最容易疏忽的,很多神奇的问题,都是因为这个而找不到起因,跟个鬼一样。特地是在 soa 和微服务架构,往往会利用 k8s 部署多个 pod 状况下。所以对于提供的写操作接口,肯定要钻研有没有并发问题。如果有,往往是利用分布式锁解决(除非只运行一个 pod)

d,性能:有些业务解决可能比较复杂,一次响应须要太久的工夫,这对使用者来说,都是一次不好的体验,在上下游对接中,咱们提供的接口可能仅仅是整个业务中的一环,因而须要留神接口的性能。
有书籍说 ” 如果可能失常运行,就不要进行性能优化,否则会带来劫难 ”,这句话不全对。
首先须要剖析是慢在哪里了。其中我感觉须要疾速得出结论,是否因为数据组织,零碎架构不合理而导致查问自身就很慢,如果是,那么就须要疾速的商讨对策了。为什么这一点很重要?如果在接口上线一段时间才发现这个问题,再去调整数据,调整零碎架构那往往是劫难。
如果不是这些问题,那么能够建一些 todo,或者是加缓存,或者是算法优化等等

e,申请量限度:
有的时候,可能工夫很紧迫,上下游轻易扔过去一个查问需要,如果没有工夫做好需要调研,那么性能实现后,肯定要加上限流的策略。这些组件有很多比入 sentinel。肯定要爱护好本人的零碎。

f,模块:
雷同性能的接口,最好放在对立的模块中进行治理

二:音讯对接

利用 mq 等中间件音讯
音讯对接和接口对接大部分都是雷同的。

不同之处在于,音讯处理完毕不会立即返回上下游,此次音讯的处理结果是什么。因而以后零碎,必须对解决失败的音讯,做好响应。

1,首先解决音讯有个小技巧,接音讯的类,不要进行进行任何业务逻辑解决,仅仅打印消息日志就好了。应该有独自的一个类的办法,来实现音讯的解决。这样做的益处,在于把音讯也看成一次一般的接口申请,这样也不便后续做单元测试。所以设计音讯的解决,大部分能够参照接口的设计。

2,对重要的音讯,肯定做好记录,后续可查,中间件上的音讯个别保留 7 天,如果某天被告知前 7 天的某条数据处理有问题,如果没有记录,就不得而知了。如果找不到起因,用户可不认这一点。

3,音讯解决做好幂等。

4,解决失败的音讯,记录好失败的起因,依据业务判断是否须要进行重试。

5,做好单元测试

如果做到以上,音讯对接不会有太大的问题,然而还须要思考以下事件:
a,音讯是否有序:音讯是否须要依照程序来解决,如果和发送没有约定好这一点,可能会呈现莫名微妙的 bug。能够利用 kafka 的分区有序性来实现

b,音讯量大小:音讯的数据级是什么?如果数据量太大,是依照 pod 扩容,还是说把相干代码独自保护进来,组成一个集群

c,提早:一般来说,音讯解决都是异步解决,所以它存在肯定的并发问题,可能在音讯解决的过程中,须要的数据还没有实现。那么该音讯可能要进行提早解决,而不是间接丢掉。

最初,记录点非技术的问题:
1,在和上下游对接中,要和共事搞好关系,在生产环境遇到问题不要甩锅,要及时帮忙排查问题呈现的起因和提供技术解决方案。

2,以本人负责的业务为核心,梳理好所有相干的性能,这样当呈现问题时,能力第一工夫察觉到是哪个环节呈现问题了。

正文完
 0