【整理】后端接口设计和优化相关思路汇总

文章目录

明确的接口定义和文档化

接口的明确定义和完善的文档能够减少沟通成本,避免误用。文档化还可以方便后续维护和扩展。

使用RESTful设计规范

遵循RESTful设计风格,使得接口更具一致性和可读性,并便于理解和使用。

分页和过滤

对于返回大量数据的接口,使用分页和过滤以减少数据传输量和提高响应速度。

合理使用缓存

在高并发的后端系统中,合理使用缓存可以显著提升性能,减轻数据库的压力,并缩短接口的响应时间。缓存的核心思想是将一些计算量大、访问频繁的数据暂时存储在内存中(如Redis、Memcached等),当下次请求相同数据时,可以直接从缓存中获取,而不需要再次访问数据库或执行复杂的计算。

限流与熔断机制

限流与熔断机制旨在防止系统过载,保护服务稳定性。限流控制请求频率,避免瞬间高并发冲击;熔断则在服务不稳定时主动停止请求,防止连锁故障,并在服务恢复后逐步恢复正常请求。

安全性设计

确保接口的安全性,如身份认证、权限校验和数据加密,避免数据泄露和未授权访问。

异步处理与后台任务

对于需要耗时较长的操作,可以通过异步处理或后台任务方式提高接口的响应速度。

接口参数校验(入参和出参)

接口入参和出参都需要进行校验, ① 例如入参是否不能为空,入参数据长度,入参是否符合预期规则,很多bug由于未做参数校验导致,对于可能改变的参数建议设计为对象类型;② 对于返回值,当返回值为空时是否返回为空串、空对象、空数组,需要与前端约定好。

接口扩展性考虑

在后端接口设计中,扩展性是非常重要的考虑因素。设计良好的接口应该能够适应业务需求的变化,易于扩展而不需要对现有系统做出大规模修改。

核心接口,线程池隔离

登录接口、首页数据接口、转账提现接口等,都可能使用到线程池,某些普通接口也会使用线程池,如果不做线程池隔离,普通接口出bug线程池打满,会导致登录等主要业务受到影响。

关键接口,日志打印

关键业务代码,需要打印日志进行保驾护航,在入参和出参位置或者其他关键位置,良好的日志打印具有如下好处:① 方便排查定位线上问题,划清问题责任;② 生产环境不能直接debug,必须依靠日志查问题和具体异常。

接口功能单一性原则

单一性是指接口做的事情比较单一、专一。比如一个登陆接口,它做的事情就只是校验账户名密码,然后返回登陆成功以及userId即可。但是如果你为了减少接口交互,把一些注册、一些配置查询等全放到登陆接口,就不太妥。其实这也是微服务一些思想,接口的功能单一、明确。比如订单服务、积分、商品信息相关的接口都是划分开的。将来拆分微服务的话,是不是就比较简便啦。

接口查询优化,串行改为并行

在设计一个APP首页接口时,如果它需要从多个不同的数据源获取信息(如用户信息、banner信息、弹窗信息等),通常有两种常见的调用方式:串行调用和并行调用。为了提高接口的响应速度,优化用户体验,采用并行调用是更优的选择,尤其是在这些调用之间没有依赖关系时。

并行调用允许多个请求同时执行,不必等待彼此完成。Java中的CompletableFuture可以很方便地实现这一点。

确保接口兼容性的策略

在修改老接口时,接口的兼容性是一个非常重要的考虑因素,特别是在系统已经上线并且被多个客户端使用的情况下。以下是一些确保接口兼容性的策略和最佳实践。

  1. 向后兼容性
    定义:向后兼容性指的是旧版本的客户端仍然可以正常使用新版本的接口,而不需要任何修改。
    策略:
    保持现有字段不变:不要随意修改或删除现有的字段或参数,这样可以保证旧客户端仍然能按预期工作。
    新增字段:如果需要扩展数据模型,可以新增字段或参数,但这些新增内容应该是可选的。旧客户端可以忽略这些新字段,而新客户端则可以利用它们。
    保持返回类型不变:尽量保持返回的JSON或XML结构不变,尤其是数据类型、字段名等。如果必须改变,确保新老结构兼容,或提供降级逻辑。
  2. 版本管理
    定义:当新功能或重大修改不可避免地会破坏现有客户端时,应该采用接口版本管理策略。
    策略:
    路径版本化:在URL路径中添加版本号,例如/api/v1/user和/api/v2/user。这种方式直观,客户端明确知道调用的是哪个版本的接口。
    请求头版本化:通过HTTP请求头指定版本号,例如Accept: application/vnd.company.v1+json。这种方式不会影响URL的结构。
    API网关:使用API网关进行版本管理和路由,能够更灵活地处理不同版本的接口。

调用第三方接口要考虑异常和超时处理

在调用第三方接口时,异常和超时处理是至关重要的。这些问题如果处理不当,会导致应用程序的不稳定,甚至崩溃。为了确保系统的健壮性和用户体验的稳定性,以下是一些关键的考虑和处理策略。

重试机制:在遇到网络异常时,可以尝试进行重试,通常是几次有限次数的重试。例如,可以使用指数退避算法来增加重试间隔时间,避免因频繁重试造成更多的问题。

兜底方案:如果多次重试后仍然失败,返回默认值或使用缓存中的数据,确保系统能够继续工作。

降级处理:当第三方服务异常时,提供降级服务。例如,返回一个友好的错误信息或使用本地的备用数据。

告警通知:当出现服务异常时,触发告警通知运维团队,以便快速响应。

调用第三方接口时,必须设定合理的超时时间,以避免长时间等待。

超时重试:在设定的超时时间内如果请求未完成,可以尝试重试,通常可以设置有限次重试,避免无限循环。

当某个第三方接口频繁出现异常或超时时,可以采用熔断机制,暂时停止对该接口的调用,避免对系统产生更大的影响。

日志记录:详细记录每次第三方接口调用的请求和响应信息,特别是在出现异常和超时时,确保可以进行后续的排查。

监控与报警:设置接口调用的监控指标,如成功率、平均响应时间等,当某些指标超过阈值时,立即报警通知相关人员。

接口实现过程中,注意大文件、大事务、大对象

• 读取大文件时,不要Files.readAllBytes直接读取到内存,这样会OOM的,建议使用BufferedReader一行一行来。

• 大事务可能导致死锁、回滚时间长、主从延迟等问题,开发中尽量避免大事务。

• 注意一些大对象的使用,因为大对象是直接进入老年代的,可能会触发fullGC

仔细检查代码避免出现粗心的空指针异常

空指针异常(NullPointerException)是 Java 开发中常见的错误之一。它通常发生在尝试对一个 null 对象引用进行操作时。

使用工具如 IntelliJ IDEA 的代码分析功能、SonarQube、FindBugs、Checkstyle 等,这些工具可以帮助检测可能的空指针异常问题。

在方法和构造函数中,进行参数 null 检查,抛出适当的异常。

对可能返回 null 的方法结果进行检查或处理。

对可能的参数值都进行null检查。

考虑是否存在事务失效的问题场景

• 方法的访问权限必须是public,其他private等权限,事务失效

• 方法被定义成了final的,这样会导致事务失效。

• 在同一个类中的方法直接内部调用,会导致事务失效。

• 一个方法如果没交给spring管理,就不会生成spring事务。

• 多线程调用,两个方法不在同一个线程中,获取到的数据库连接不一样的。

• 表的存储引擎不支持事务

• 如果自己try...catch误吞了异常,事务失效。

• 错误的传播特性

相关推荐
我的心永远是冰冰哒22 分钟前
ad.concat()学习
学习
ZZZ_O^O27 分钟前
二分查找算法——寻找旋转排序数组中的最小值&点名
数据结构·c++·学习·算法·二叉树
ok!ko1 小时前
设计模式之原型模式(通俗易懂--代码辅助理解【Java版】)
java·设计模式·原型模式
2402_857589361 小时前
“衣依”服装销售平台:Spring Boot框架的设计与实现
java·spring boot·后端
吾爱星辰2 小时前
Kotlin 处理字符串和正则表达式(二十一)
java·开发语言·jvm·正则表达式·kotlin
slomay2 小时前
关于对比学习(简单整理
经验分享·深度学习·学习·机器学习
hengzhepa2 小时前
ElasticSearch备考 -- Async search
大数据·学习·elasticsearch·搜索引擎·es
哎呦没3 小时前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
编程、小哥哥3 小时前
netty之Netty与SpringBoot整合
java·spring boot·spring
小小洋洋4 小时前
BLE MESH学习1-基于沁恒CH582学习
学习