设计好接口的36个锦囊

在这里插入图片描述
在这里插入图片描述
设计好接口的36个锦囊

  1. 接口参数校验
  2. 修改老接口时,注意接口的兼容性
  3. 设计接口时,充分考虑接口的可扩展性。策略模式
  4. 接口考虑是否需要防重处理
如果是查询类的请求,其实不用防重。如果是更新修改类的话,尤其金融转账类的,就要过滤重复请求了。简单点,可以使用Redis防重复请求,同样的请求方,一定时间间隔内的相同请求,考虑是否过滤。当然,转账类接口,并发不高的话,推荐使用数据库防重表,以唯一流水号作为主键或者唯一索引。
  1. 重点接口,考虑线程池隔离。
  2. 调用第三方接口要考虑异常和超时处理
  3. 接口实现考虑熔断和降级
为了应对服务雪崩, 常见的做法是熔断和降级。最简单是加开关控制,当下游系统出问题时,开关降级,不再调用下游系统。还可以选用开源组件Hystrix
  1. 日志打印好,接口的关键代码,要有日志保驾护航。
至少,方法调用前,入参需要打印需要吧,接口调用后,需要捕获一下异常吧,同时打印异常相关日志吧
  1. 接口的功能定义要具备单一性.这也是微服务一些思想,接口的功能单一、明确。比如订单服务、积分、商品信息相关的接口都是划分开的
  2. 接口有些场景,使用异步更合理.至于做异步的方式,简单的就是用线程池。还可以使用消息队列
  3. 优化接口耗时,远程串行考虑改并行调用.在Java中有个异步编程利器:CompletableFuture,就可以很好实现这个功能
  4. 接口合并或者说考虑批量处理思想.kafka使用批量消息提升服务端处理能力
  5. 接口实现过程中,恰当使用缓存.读多写少且数据时效要求越低的场景适合使用缓存
保证数据库和缓存一致性:缓存延时双删、删除缓存重试机制、读取biglog异步删除缓存
缓存击穿:设置数据永不过期
缓存雪崩:Redis集群高可用、均匀设置过期时间
缓存穿透:接口层校验、查询为空设置个默认空值标记、布隆过滤器。
一般用Redis分布式缓存,当然有些时候也可以考虑使用本地缓存,如Guava Cache、Caffeine等。使用本地缓存有些缺点,就是无法进行大数据存储,并且应用进程的重启,缓存会失效。
  1. 接口考虑热点数据隔离性。业务隔离、系统隔离、用户隔离、数据隔离等
业务隔离性,比如12306的分时段售票,将热点数据分散处理,降低系统负载压力。
系统隔离:比如把系统分成了用户、商品、社区三个板块。这三个块分别使用不同的域名、服务器和数据库,做到从接入层到应用层再到数据层三层完全隔离。
用户隔离:重点用户请求到配置更好的机器。
数据隔离:使用单独的缓存集群或者数据库服务热点数据。
  1. 可变参数配置化,比如红包皮肤切换等.扩展性思想
  2. 接口考虑幂等性
计算机科学中,幂等表示一次和多次请求某一个资源应该具有同样的副作用,或者说,多次请求所产生的影响与一次请求执行的影响效果相同。
防重和幂等设计其实是有区别的。防重主要为了避免产生重复数据,把重复请求拦截下来即可。而幂等设计除了拦截已经处理的请求,还要求每次相同的请求都返回一样的效果。不过呢,很多时候,它们的处理流程、方案是类似的

接口幂等实现方案主要有8种:

select+insert+主键/唯一索引冲突
直接insert + 主键/唯一索引冲突
状态机幂等
抽取防重表
token令牌
悲观锁
乐观锁
分布式锁
  1. 读写分离,优先考虑读从库,注意主从延迟问题
  2. 接口注意返回的数据量,如果数据量大需要分页
  3. 好的接口实现,离不开SQL优化
SQL优化从这几个维度思考:

explain 分析SQL查询计划(重点关注type、extra、filtered字段)
show profile分析,了解SQL执行的线程的状态以及消耗的时间
索引优化 (覆盖索引、最左前缀原则、隐式转换、order by以及group by的优化、join优化)
大分页问题优化(延迟关联、记录上一页最大ID)
数据量太大(分库分表、同步到es,用es查询)
  1. 代码锁的粒度控制好
  2. 接口状态和错误需要统一明确
    在这里插入图片描述
  3. 接口要考虑异常处理
Java 异常处理:
尽量不要使用e.printStackTrace(),而是使用log打印。因为e.printStackTrace()语句可能会导致内存占满。
catch住异常时,建议打印出具体的exception,利于更好定位问题
不要用一个Exception捕捉所有可能的异常
记得使用finally关闭流资源或者直接使用try-with-resource
捕获异常与抛出异常必须是完全匹配,或者捕获异常是抛异常的父类
捕获到的异常,不能忽略它,至少打点日志吧
注意异常对你的代码层次结构的侵染
自定义封装异常,不要丢弃原始异常的信息Throwable cause
运行时异常RuntimeException ,不应该通过catch的方式来处理,而是先预检查,比如:NullPointerException处理
注意异常匹配的顺序,优先捕获具体的异常
  1. 优化程序逻辑
  2. 接口实现过程中,注意大文件、大事务、大对象。大对象是直接进入老年代的,会触发fullGC
  3. 你的接口,需要考虑限流
在计算机网络中,限流就是控制网络接口发送或接收请求的速率,它可防止DoS攻击和限制Web爬虫。限流,也称流量控制。是指系统在面临高并发,或者大流量请求的情况下,限制新的请求对系统的访问,从而保证系统的稳定性。

可以使用Guava的RateLimiter单机版限流,也可以使用Redis分布式限流,还可以使用阿里开源组件sentinel限流
  1. 代码实现时,注意运行时异常(比如空指针、下标越界等)
  2. 保证接口安全性.保证接口的安全性有token机制和接口签名
    token机制身份验证方案还比较简单的,就是
    在这里插入图片描述
  • 客户端发起请求,申请获取token。
  • 服务端生成全局唯一的token,保存到redis中(一般会设置一个过期时间),然后返回给客户端。
    客户端带着token,发起请求。
  • 服务端去redis确认token是否存在,一般用 redis.del(token)的方式,如果存在会删除成功,即处理业务逻辑,如果删除失败不处理业务逻辑,直接返回结果。
  • 接口签名的方式,就是把接口请求相关信息(请求报文,包括请求时间戳、版本号、appid等),客户端私钥加签,然后服务端用公钥验签,验证通过才认为是合法的、没有被篡改过的请求。

除了加签验签和token机制,接口报文一般是要加密的。当然,用https协议是会对报文加密的。如果是我们服务层的话,如何加解密呢?

可以参考HTTPS的原理,就是服务端把公钥给客户端,然后客户端生成对称密钥,接着客户端用服务端的公钥加密对称密钥,再发到服务端,服务端用自己的私钥解密,得到客户端的对称密钥。这时候就可以愉快传输报文啦,客户端用对称密钥加密请求报文,服务端用对应的对称密钥解密报文。
有时候,接口的安全性,还包括手机号、身份证等信息的脱敏。就是说,用户的隐私数据,不能随便暴露。

  1. 分布式事务,如何保证
分布式事务:就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。简单来说,分布式事务指的就是分布式系统中的事务,它的存在就是为了保证不同数据库节点的数据一致性。
分布式事务的几种解决方案:

2PC(二阶段提交)方案、3PC
TCC(Try、Confirm、Cancel)
本地消息表
最大努力通知
seata
  1. 事务失效的一些经典场景
1.方法的访问权限必须是public,其他private等权限,事务失效
2.方法被定义成了final的,这样会导致事务失效。
3.在同一个类中的方法直接内部调用,会导致事务失效。
4.一个方法如果没交给spring管理,就不会生成spring事务。
5.多线程调用,两个方法不在同一个线程中,获取到的数据库连接不一样的。
6.表的存储引擎不支持事务
7.如果自己try...catch误吞了异常,事务失效。
8.错误的传播特性
  1. 掌握常用的设计模式
  2. 写代码时,考虑线程安全问题.
    Hashmap、Arraylist、LinkedList、TreeMap等都是线程不安全的;
    Vector、Hashtable、ConcurrentHashMap等都是线程安全的
  3. 接口定义清晰易懂,命名规范
  4. 接口的版本控制。请求基础报文,应该包含version接口版本号字段,方便未来做接口兼容
  5. 注意代码规范问题
    注意一些常见的代码坏味道:
  • 大量重复代码(抽公用方法,设计模式)
  • 方法参数过多(可封装成一个DTO对象)
  • 方法过长(抽小函数)
  • 判断条件太多(优化if…else)
  • 不处理没用的代码
  • 不注重代码格式
  • 避免过度设计
  1. 保证接口正确性,其实就是保证更少的bug。转账交易,扣减余额的时候,可以通过CAS乐观锁的方式保证余额扣减正确
  2. 学会沟通,跟前端沟通,跟产品沟通
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值