什么?你设计接口什么都不考虑?

 

如果让你设计一个接口,你会考虑哪些问题?

1.接口参数校验

接口的入参和返回值都需要进行校验。

  • 入参是否不能为空,入参的长度限制是多少,入参的格式限制,如邮箱格式限制

  • 返回值是否为空,如果为空的时候是否返回默认值,这个默认值需要和前端协商

2.接口扩展性

举个例子,比如用户在进行某些操作之后,后端需要进行消息推送,那么是直接针对这个业务流程来开发一个专门为这个业务流程服务的消息推送功能呢?还是说将消息推送整合为一个通用的接口,其他流程都可以进行调用,并非针对特定业务。

这个场景可能光靠说不是很能理解,大家想想策略工厂设计模式,是不是可以根据不同的策略,来选择不同的实现方式呢?再结合上面的这个例子,是否对扩展性有了进一步的理解呢?

3.接口幂等设计

什么是幂等呢?幂等是指多次调用接口不会改变业务状态,可以保证重复调用的结果和单次调用的结果一致。

举个例子,在购物商场里面你用手机下单,要买某个商品,你需要去支付,然后你点击了支付,但是因为网速问题,始终没有跳转到支付界面,于是你又连点了几次支付,那在没有做接口幂等的时候,是不是你点击了多少次支付,我们就需要执行多少次支付操作?

所以接口幂等到的是什么?防止用户多次调用同一个接口

  • 对于查询和删除类型的接口,不论调用多少次,都是不会产生错误的业务逻辑和数据的,因此无需幂等处理

  • 对于新增和修改,例如转账等操作,重复提交就会导致多次转账,这是很严重的,影响业务的接口需要做接口幂等的处理,跟前端约定好一个固定的token接口,先通过用户的id获取全局的token,写入到Redis缓存,请求时带上Token,后端做处理

4.关键接口日志打印

关键的业务代码,是需要打印日志进行监测的,在入参和返回值或者如catch代码块中的位置进行日志打印

  • 方便排查和定位线上问题,划清责任

  • 生产环境是没有办法进行debug的,必须依靠日志查问题,看看到底是出现了什么异常情况

5.核心接口要进行线程池隔离

分类查询啊,首页数据等接口,都有可能使用到线程池,某些普通接口也可能会使用到线程池,如果不做线程池隔离,万一普通接口出现bug把线程池打满了,会导致你的主业务受到影响

6.第三方接口异常重试

如果有场景出现调用第三方接口,或者分布式远程服务的话,需要考虑的问题

  • 异常处理

    比如你在调用别人提供的接口的时候,如果出现异常了,是要进行重试还是直接就是当做失败

  • 请求超时

    有时候如果对方请求迟迟无响应,难道就一直等着吗?肯定不是这样的,需要设法预估对方接口响应时间,设置一个超时断开的机制,以保护接口,提高接口的可用性,举个例子,你去调用别人对外提供的一个接口,然后你去发http请求,始终响应不回来,此时你又没设置超时机制,最后响应方进程假死,请求一直占着线程不释放,拖垮线程池。

  • 重试机制

    如果调用对外的接口失败了或者超时了,是否需要重新尝试调用呢?还是失败了就直接返回失败的数据?

7.接口是否需要采用异步处理

举个例子,比如你实现一个用户注册的接口。用户注册成功时,发个邮件或者短信去通知用户。这个邮件或者发短信,就更适合异步处理。总不能一个通知类的失败,导致注册失败吧。那我们如何进行异步操作呢?可以使用消息队列,就是用户注册成功后,生产者产生一个注册成功的消息,消费者拉到注册成功的消息,就发送通知。

8.接口查询优化,串行优化为并行

假设我们要开发一个网站的首页,我们设计了一个首页数据查询的接口,这个接口需要查用户信息,需要查头部信息,需要查新闻信息

等等之类的,最简单的就是一个一个接口串行调用,那要是想要提高性能,那就采取并行调用的方式,同时查询,而不是阻塞

可以使用CompletableFuture(推荐)或者FutureTask(不推荐)

  1.         Map<Long, List<SubjectLabelBO>> map = new HashMap<>();

  2.         List<CompletableFuture<Map<Long, List<SubjectLabelBO>>>> completableFutureList = 

  3.         categoryBOList.stream().map(category ->

  4.                 CompletableFuture.supplyAsync(() -> getLabelBOList(category), labelThreadPool)

  5.         ).collect(Collectors.toList());

  6.         completableFutureList.forEach(future -> {

  7.             try {

  8.                 Map<Long, List<SubjectLabelBO>> resultMap = future.get(); //这里会阻塞

  9.                 map.putAll(resultMap);

  10.             } catch (Exception e) {

  11.                 e.printStackTrace();

  12.             }

  13.         });

  14.         public Map<Long, List<SubjectLabelBO>> getLabelBOList(SubjectCategoryBO category) {...}

9.高频接口注意限流

自定义注解 + AOP

  1. @Target(ElementType.METHOD)

  2. @Retention(RetentionPolicy.RUNTIME)

  3. public @interface RateLimiter {

  4.     int value() default 1;

  5.     int durationInSeconds() default 1;

  6. }

  7. @Aspect

  8. @Component

  9. public class RateLimiterAspect {

  10.     private final ConcurrentHashMap<String, RateLimiter> rateLimiters = new ConcurrentHashMap<>();

  11.     @Pointcut("@annotation(RateLimiter)")

  12.     public void rateLimiterPointcut(RateLimiter rateLimiterAnnotation) {

  13.     }

  14.     @Around("rateLimiterPointcut(rateLimiterAnnotation)")

  15.     public Object around(ProceedingJoinPoint joinPoint, RateLimiter rateLimiterAnnotation) throws Throwable {

  16.         int permits = rateLimiterAnnotation.value();

  17.         int durationInSeconds = rateLimiterAnnotation.durationInSeconds();

  18.         // 使用方法签名作为 RateLimiter 的 key

  19.         String key = joinPoint.getSignature().toLongString();

  20.         com.google.common.util.concurrent.RateLimiter rateLimiter = rateLimiters.computeIfAbsent(key, k -> com.google.common.util.concurrent.RateLimiter.create((double) permits / durationInSeconds));

  21.         // 尝试获取令牌,如果获取到则执行方法,否则抛出异常

  22.         if (rateLimiter.tryAcquire()) {

  23.             return joinPoint.proceed();

  24.         } else {

  25.             throw new RuntimeException("Rate limit exceeded.");

  26.         }

  27.     }

  28. }

  29. @RestController

  30. public class ApiController {

  31.     @GetMapping("/api/limited")

  32.     @RateLimiter(value = 10, durationInSeconds = 60) //限制为每分钟 10 次请求

  33.     public String limitedEndpoint() {

  34.         return "This API has a rate limit of 10 requests per minute.";

  35.     }

  36.     @GetMapping("/api/unlimited")

  37.     public String unlimitedEndpoint() {

  38.         return "This API has no rate limit.";

  39.     }

  40. }

10.保障接口安全

配置黑白名单,用Bloom过滤器实现黑白名单的配置

具体代码不贴出来了,大家可以去看看布隆过滤器的具体使用

11.接口控制锁粒度

在高并发场景下,为了防止超卖等情况,我们会对共享资源进行加锁的操作来保证线程安全的问题,但是如果加锁的粒度过大,是会影响

到接口性能的。那什么是加锁粒度呢?举一个例子,你带了一封情书回家,但是不想被爸妈发现,然后你偷偷回到房间里放到一个可以锁

住的抽屉里面,而不用把房间的门锁给锁上。无论是使用synchronized加锁还是redis分布式锁,只需要在共享临界资源加锁即可,不涉

及共享资源的,就不必要加锁。

  • 锁粒度过大:

    把方法A和方法B全部进行加锁,但是实际上我只是想要对A加锁,这就是锁粒度过大

  1. void test(){

  2.     synchronized (this) {

  3.        B();

  4.        A();

  5.     }

  6. }

  • 缩小锁粒度

  1. void test(){

  2.        B();

  3.     synchronized (this) {

  4.        A();

  5.     }

  6. }

12.避免长事务问题

长事务期间可能伴随cpu、内存升高、严重时会导致服务端整体响应缓慢,导致在线应用无法使用

产生长事务的原因除了sql本身可能存在问题外,和应用层的事务控制逻辑也有很大的关系。

  • 如何尽可能的避免长事务问题呢?

  1. RPC远程调用不要放到事务里面

  2. 一些查询相关的操作如果可用,尽量放到事务外面

  3. 并发场景下,尽量避免使用@Transactional注解来操作事务,使用TransactionTemplate的编排式事务来灵活控制事务的范围

在原先使用@Transactional来管理事务的时候是这样的

  1. @Transactional

  2. public int createUser(User user){

  3.     //保存用户信息

  4.     userDao.save(user);

  5.     passCertDao.updateFlag(user.getPassId());

  6.     // 该方法为远程RPC接口

  7.     sendEmailRpc(user.getEmail());

  8.     return user.getUserId();

  9. }

使用TransactionTemplat进行编排式事务

  1. @Resource

  2. private TransactionTemplate transactionTemplate;

  3. public int createUser(User user){

  4.     transactionTemplate.execute(transactionStatus -> {

  5.       try {

  6.          userDao.save(user);

  7.          passCertDao.updateFlag(user.getPassId());

  8.       } catch (Exception e) {

  9.          // 异常手动设置回滚

  10.          transactionStatus.setRollbackOnly();

  11.       }

  12.       return true;

  13.     });

  14.     // 该方法为远程RPC接口

  15.     sendEmailRpc(user.getEmail());

  16.     return user.getUserId();

  17. }

总结:

感谢每一个认真阅读我文章的人!!!

作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

 

          视频文档获取方式:
这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片即可自行领取。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/12920.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

不相交集合的数据结构

一、不相交集合的操作 不相交集合的数据结构维护了一组不相交动态集的集合 &#xff0c;用集合中的某个成员作为代表标识集合。 集合在没有修改的情况下每次访问代表得到的答案是相同的&#xff0c;此外在其它一些应用中&#xff0c;可能按照规定选择集合的代表&#xff0c;例如…

WebSocket or SSE?即时通讯的应用策略【送源码】

最近在研究H5推送&#xff0c;发现除了我们常用的WebSocket以外&#xff0c;其实还有一种协议也能实现H5推送&#xff0c;那就是SSE协议。 而且&#xff0c;当前主流的大模型平台&#xff0c;比如ChatGPT、通义千问、文心一言&#xff0c;对话时采用的就是SSE。 什么是SSE协议…

100m/s高速轧制钢材 八轴测径仪检测毫无压力

关键词&#xff1a;八轴测径仪,在线测径仪,钢材测径仪,高速轧制 随着技术的提升&#xff0c;钢材的生产速度越来越快&#xff0c;一些高速生产的钢材&#xff0c;生产速度甚至达到了100m/s&#xff0c;这是一个非常快的速度。 如果汽车以120公里/小时的速度行驶&#xff0c;那么…

Unity WebGL全屏显示

一、删除footer节点 二、删除最下面点击事件绑定 修改Canvas宽高 canvas.style.width "960px"; canvas.style.height "600px"; 改成 canvas.style.width document.documentElement.clientWidth"px"; canvas.style.height document.document…

行为驱动开源免费接口测试框架:karate

什么是行为驱动测试&#xff1a; 行为驱动测试&#xff08;Behavior-Driven Testing&#xff0c;简称 BDT&#xff09;是一种测试方法&#xff0c;旨在通过描述系统行为和功能来编写测试用例。BDT的重点是从用户的角度出发&#xff0c;描述系统应该如何行为&#xff0c;而不是专…

DiskANN数据布局

_mem.index.data&#xff1a;和sift_base.fbin一模一样。0-3字节是总向量数&#xff0c;4-7是每个向量的特征数。后面就是依次放置的每个向量。 _disk.index&#xff1a;是存储的图&#xff0c;但是不光包含图也包含原始向量。前4KB不知道存的是啥。从第0x1000开始存放的是原始…

国内企业更喜欢私有化部署的 6 大原因

今天在 V 站看到一篇题为《为什么国内企业会更倾向于接受私有部署而不是 SaaS&#xff1f;》的帖子&#xff0c;觉得很有启发&#xff0c;这里把网友的观点稍作整理和总结&#xff0c;分享给大家参考。 在技术日益发展的今天&#xff0c;国内企业的软件部署方式似乎呈现出与欧…

【机器学习】机器学习:人工智能中实现自动化决策与精细优化的核心驱动力

&#x1f512;文章目录: &#x1f4a5;1.概述 ❤️2.机器学习基本原理 &#x1f6e4;️2.1定义与关键概念 &#x1f6e3;️2.2 机器学习算法 ☔3.自动化决策中的机器学习应用 &#x1f6b2;4.精细优化与机器学习的结合 &#x1f44a;5.挑战与前景 &#x1f4a5;1.概述 …

基于微信小程序+JAVA Springboot 实现的【房屋租赁管理系统】app+后台管理系统 (内附设计LW + PPT+ 源码+ 演示视频 下载)

项目名称 项目名称&#xff1a; 基于微信小程序的房屋租赁管理系统 在本次项目开发中&#xff0c;我们成功构建了一款基于微信小程序的房屋租赁管理系统&#xff0c;旨在通过现代化信息技术提升房屋租赁服务的效率和质量。以下是对本项目的全面总结&#xff1a; 项目背景与目…

js之选项卡制作实例

大家好&#xff0c;今天给大家书写选项卡实例&#xff0c;话不多说&#xff0c;直接上干货 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, in…

Redis-分片集群存储及读取数据详解

文章目录 Redis分片集群是什么&#xff1f;Redis分片集群的存储及读取数据&#xff1f; 更多相关内容可查看 Redis分片集群是什么&#xff1f; Redis分片集群是一种分布式部署方式&#xff0c;通过将数据分散存储在多个Redis节点上&#xff0c;从而提高了系统的性能、扩展性和…

19个测试⽤例⽣成的AI⼯具!卷起来!

在不断发展的软件开发领域中&#xff0c;确保应⽤程序的可靠性和功能性⾄关重要。 随着软件系统复杂性的增加&#xff0c;有效测试⽅法的需求也在上升。 传统的测试⽤例⽣成⽅法通常⽆法满⾜快速开发周期和复杂代码库的需求。 随着进⼊⼈⼯智能&#xff08;AI&#xff09;时…

爬虫入门经典(七) | 采集淘宝电场相关信息

大家好&#xff0c;我是不温卜火&#xff0c;昵称来源于成语—不温不火&#xff0c;本意是希望自己性情温和。 PS&#xff1a;由于现在越来越多的人未经本人同意直接爬取博主本人文章&#xff0c;博主在此特别声明&#xff1a;未经本人允许&#xff0c;禁止转载&#xff01;&a…

Galxe已投资Pencils Protocol,投资者阵营正不断扩大

近日&#xff0c;Scroll 生态项目 Penpad 将品牌进一步升级为 Pencils Protocol&#xff0c;全新升级后其不仅对 LaunchPad 平台进行了功能上的升级&#xff0c;同时其也进一步引入了 Staking、Vault 以及 Shop 等玩法&#xff0c;这也让 Pencils Protocol 的叙事方向不再仅限于…

基础之音视频2

01 前言 02 mp 03 mp实例 简易音乐播放器 04 音频 sound-pool 1.作用 播放多个音频&#xff0c;短促音频 2.过程 加载load- 3.示例 模拟手机选铃声 步骤&#xff1a; 创建SoundPool对象&#xff0c;设置相关属性 音频流存入hashmap 播放音频 05 videoview 3gp 体积小 mp4 …

web安全学习笔记(15)

记一下第25-26课的内容。弱口令爆破的四种模式与判断成功失败的三种方案&#xff1b;爆破中的验证码拦截错误次数IP限制密码加密绕过 IP获取的原理以及绕过CDN获取客户真实IP 一、弱口令的分类 1.常规弱口令&#xff1a;如123456&#xff0c;666666&#xff0c;888888等 2.…

【软件测试】需求概念|软件的⽣命周期|开发模型|测试模型

目录 推荐 一、什么是需求 1.1 ⽤⼾需求 1.2 软件需求 二、开发模型 2.1 什么是“模型” 2.2 软件的⽣命周期 2.3 常⻅开发模型 2.3.1 瀑布模型 2.3.2 螺旋模型 2.3.3 增量模型、迭代模型 2.3.4 敏捷模型 2.4 测试模型 2.4.1 V模型 2.4.2 W模型(双V模型&#xff0…

使用RN的kitten框架的日历组件的修改

官方网页地址 下面就是我参考官方封装的时间日期组件&#xff08;主要是功能和使用方法&#xff0c;页面粗略做了下&#xff0c;不好看勿怪&#xff09; import React, {useState} from react; import {StyleSheet, View, TouchableOpacity, SafeAreaView} from react-native; …

FreeRTOS消息队列queue.c文件详解

消息队列的作用 消息队列主要用来传递消息&#xff0c;可以在任务与任务之间、中断与任务之间传递消息。 传递消息是通过复制的形式&#xff0c;发送方发送时需要不断复制&#xff0c;接收方接收时也需要不断复制。虽然会有内存资源的浪费&#xff0c;但是可以保证安全。 假…

Java项目:基于ssm框架实现的实验室耗材管理系统(B/S架构+源码+数据库+毕业论文+答辩PPT)

一、项目简介 本项目是一套基于ssm框架实现的实验室耗材管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 二、技术实现 jdk版本&#xff1a;1.8 …