如何把一个接口设计好?
如何把一个接口设计好?
- 如何设计一个接口?是在我们日常开发或者面试时经常问及的一个话题。
- 很多人觉得这不就是CRUD,能实现不就行了。单纯实现来说,并非难事,但要做到易用、易扩展、易维护并不是一件简单的事。这里并不强调一些个接口设计的原则或者设计方法,仅从如何设计一个好的接口出发,简单讨论。
命名规范
- 我们写代码,不仅仅是为了实现当前的功能,也要有利于后面的维护。所谓的维护,就是代码不仅仅是写给自己看的,也是给别人看的。所以接口定义要清晰易懂、命名规范。
- 除了接口、方法、出入参命名规范,也要注意代码规范问题。一开始接触到各种代码坏味道的小伙伴,大多都会觉得这些规范很多余、很烦人,但实际上,这些好的编码习惯是让大家都能按照基本规约开发,易于阅读易于维护的基础。
- 在接口定义时,也请注意接口功能的单一性。其实这也是微服务的一些思想,接口功能的单一职责、明确简单。比如登录接口,它做的事情就是校验账户名和密码相关;订单服务、积分服务、商品信息相关的接口都是划分开的。
参数校验
- 入参出参校验是每个程序员必备的基本素养。你设计的接口,必须先校验参数。比如入参是否允许为空、入参长度要求、入参是否在枚举值范围内等等。日常开发中,很多低级bug都是不校验参数导致的。
- 提到参数,就必须提到接口状态和错误码。无论是失败还是成功,一个完备的接口都应该告诉调用方返回信息。如果接口失败,具体失败的原因是什么,这就需要定义明确的错误码和对应描述。同时,尽量对报错信息进行封装,不要直接将服务端异常信息抛出去。
监控/性能
- 如何评判一个接口的性能就必须要有监控,这对于服务端监视接口性能和异常报警至关重要。调用次数、可用率、TP99、TP999等监视指标,极其重要的核心接口,还需要细分至秒级监控加以标识。
- 一个接口的性能不单单只看自己业务逻辑,外部远程调用也是消耗性能的重要部分。如果你调用第三方接口或者远程服务,就需要考虑异常和超时。如果异常了,怎么处理,是重试还是当作失败还是告警处理。如果重试,重试几次?这就需要站在业务角度思考这个问题。这些措施也是直接影响当前接口性能。
- 提高性能的利器还可以考虑缓存。缓存用得好,可以承载更多的请求,提升查询效率,减少数据库的压力。但是使用缓存需要考虑缓存和数据库一致性保证、缓存击穿等问题。
日志
- 接口的关键代码,要有日志的保驾护航。首先日志级别需要合理使用:error > warn > info > debug。
- 其次日志信息包含哪些呢,核心代码块调用前的入参打印、接口调用后的异常捕获日志等。需要注意的是,如果日志中涉及比较大的JSON富文本,请使用log.isInfoEnable(),在高并发和复杂log信息拼接的情况下,使用这种标准的方法输出log能够省去不小的系统开销。另外,如果构造log信息的过程需要大量字符串操作,建议使用StringBuilder来完成字符串拼接。
异常/超时
- 实现一个好的接口,离不开优雅的异常处理。比如异常匹配的顺序,优先捕获具体的异常;使用流时记得使用finally关闭流资源;
- 对于运行时错误,比如数据边界越界、空指针也在日常开发中出现,该判断、该校验的还是一项不能少哦。
- 超时问题也经常会导致接口不可用。设置合理的超时时间,也是在保护你的接口。超时一般与重试搭配使用,不过请注意,设置超时时间时,需要充分考虑你的上下游设置的超时时间。比如一个请求率先访问你的上游,而你的上游设置的超时时间是500ms,上游调用你的接口,但你设置的超时是2000ms,这其实就是无效超时时间。
- 对于接口耗时优化,也是有一些手段的,比如远程串行改为并行调用、单次调用改为批量调用等等。但请注意尽量不在循环或者事务里远程调用。
异步
- 接口有些场景,使用异步更合理。举个简单的例子,对于一些运营操作的接口,往往需要记录对应操作的操作日志,记录下是谁在什么时间操作了什么对象,便于追踪“事发现场”。但是记录操作日志并不在接口主流程上,记录操作日志是否成功失败也不应该影响正常主流程的执行,这个时候就应该考虑用消息队列等方式进行异步解耦。
注释
- 可以说,注释也是良好代码的重要组成部分。有些人,一直相信show me the code,却不想写一行注释,认为没有必要。但是你无法保证代码逻辑一直清晰、高效。如果是比较复杂的话,就建议把注释写清楚,这对于后续维护和缕清代码逻辑很重要。
降级/限流
- 如今的请求调用基本都是分布式调用链路,当分布式系统中某个基础服务不可用时,就会最终导致整个系统不可用,所以当下游系统或者自身服务出现问题时,一定要考虑降级。如果做的更完备的话,还可以考虑熔断。
- 同时,针对高并发的流量洪峰接口,必须考虑限流应对超出系统的承载能力挑战。限流措施也同样可以限制爬虫,保护系统,丢弃多余的请求。
安全
- 这里说的安全,范围可太大了。比如线性安全,很多人反手上来就是HashMap,因为它是非线性安全的,可以考虑高并发下的ConcurrentHashMap。
- 如果前端重复请求,你的逻辑如何处理?是不是考虑接口去重处理(有时候是防刷处理)。简单点,可以使用redis防重处理,同样的请求,一定时间间隔内进行过滤。当然,对于一些并发不高的接口,比如转账类接口,推荐使用数据库主键或者唯一索引。
- 如果消息队列出现重复消费的情况,你的业务逻辑怎么控制?是不是考虑幂等性校验。
- 防重主要为了避免产生重复数据,把重复请求拦截下来即可。而幂等设计除了拦截已经处理的请求,还要求每次相同的请求都返回一样的结果。不过很多时候,它们的处理流程和方式是类似的。
- 还有一些其他安全方面的考虑,比如读写分离、代码锁的粒度控制、数据加密等等。
沟通
- 为什么要有沟通?又为什么把沟通放在最后呢?遇到一些技术难题,跟技术leader对齐方案。实现需求的过程中,有什么问题,需要及时跟产品沟通。需要跟客户端对齐接口,一定不能上来就自己埋头把接口定义完了。种种场景,学会沟通是非常重要的,有效、高效沟通不仅会带来愉悦心情,开发起来很顺畅,也会提高人际关系。
相关文章:
如何把一个接口设计好?
如何把一个接口设计好? 如何设计一个接口?是在我们日常开发或者面试时经常问及的一个话题。很多人觉得这不就是CRUD,能实现不就行了。单纯实现来说,并非难事,但要做到易用、易扩展、易维护并不是一件简单的事。这里并…...

mini-vue 的设计
mini-vue 的设计 mini-vue 使用流程与结果预览: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><meta name&qu…...
React整理杂记(一)
1.React三项依赖 1.react.js -> 核心代码 2.react-dom.js -> 渲染成dom 3.babel.js->非必须,将jsx转为js 类组件中直接定义的方法,都属于严格模式下 this的绑定可以放到constructor(){}中 2. JSX语法 1.可以直接插入的元素: num…...
[100天算法】-统计封闭岛屿的数目(day 74)
题目描述 有一个二维矩阵 grid ,每个位置要么是陆地(记号为 0 )要么是水域(记号为 1 )。我们从一块陆地出发,每次可以往上下左右 4 个方向相邻区域走,能走到的所有陆地区域,我们将其…...
esp32-rust-std-examples-blinky
以下为在 ESP-IDF (FreeRTOS) 上运行的 blinky 示例: https://github.com/esp-rs/esp-idf-hal/blob/master/examples/blinky.rs //! Blinks an LED //! //! This assumes that a LED is connected to GPIO4. //! Depending on your target and the board you are …...
【docker容器技术与K8s】
【docker容器技术与K8s】 一、Docker容器技术 1、Docker的学习路线 (1)学习Docker基本命令(容器管理和镜像管理) (2)学习使用Docker搭建常用软件 (3)学习Docker网络模式 启动容器的…...

RT-DTER 引入用于低分辨率图像和小物体的新 CNN 模块 SPD-Conv
论文地址:https://arxiv.org/pdf/2208.03641v1.pdf 代码地址:https://github.com/labsaint/spd-conv 卷积神经网络(CNN)在图像分类、目标检测等计算机视觉任务中取得了巨大的成功。然而,在图像分辨率较低或对象较小的更困难的任务中,它们的性能会迅速下降。 这源于现有CNN…...
Folw + Room 实现自动观察数据库的刷新
1、Room :定义数据结构、创建数据库 // 定义实体 Entity data class TestModel ()// 定义数据库 Dao interface TestDao { Query("SELECT * FROM TestTable") fun getAll(): List<TestModel> }// 获取数据库 abstract class TestDatabase: RoomDat…...

黑马程序员微服务Docker实用篇
Docker实用篇 0.学习目标 1.初识Docker 1.1.什么是Docker 微服务虽然具备各种各样的优势,但服务的拆分通用给部署带来了很大的麻烦。 分布式系统中,依赖的组件非常多,不同组件之间部署时往往会产生一些冲突。在数百上千台服务中重复部署…...

虚拟化服务器+华为防火墙+kiwi_syslog访问留痕
一、适用场景 1、大中型企业需要对接入用户的访问进行记录时,以前用3CDaemon时,只能用于小型网络当中,记录的数据量太大时,本例采用破解版的kiwi_syslog。 2、当网监、公安查到有非法访问时,可提供基于五元组的外网访…...

FlinkSQL聚合函数(Aggregate Function)详解
使用场景: 聚合函数即 UDAF,常⽤于进多条数据,出⼀条数据的场景。 上图展示了⼀个 聚合函数的例⼦ 以及 聚合函数包含的重要⽅法。 案例场景: 关于饮料的表,有三个字段,分别是 id、name、price࿰…...

TensorFlow学习笔记--(3)张量的常用运算函数
损失函数及求偏导 通过 tf.GradientTape 函数来指定损失函数的变量以及表达式 最后通过 gradient(%损失函数%,%偏导对象%) 来获取求偏导的结果 独热编码 给出一组特征值 来对图像进行分类 可以用独热编码 0的概率是第0种 1的概率是第1种 0的概率是第二种 tf.one_hot(%某标签…...

RT-Thread:嵌入式实时操作系统的设计与应用
RT-Thread(Real-Time Thread)是一个开源的嵌入式实时操作系统,其设计和应用在嵌入式领域具有重要意义。本文将从RT-Thread的设计理念、核心特性,以及在嵌入式系统中的应用等方面进行探讨,对其进行全面的介绍。 首先&a…...
SpringBoot学习笔记-创建菜单与游戏页面(下)
笔记内容转载自 AcWing 的 SpringBoot 框架课讲义,课程链接:AcWing SpringBoot 框架课。 CONTENTS 1. 地图优化改进2. 绘制玩家的起始位置3. 实现玩家移动4. 优化蛇的身体效果5. 碰撞检测实现 本节实现两名玩家即两条蛇的绘制与人工操作移动功能。 1. 地…...
STM32一
0.前言 在B站经常看见有人用stm32做出了有趣的电子小玩艺儿,感到很羡慕,于是想了解一下。 1.什么是stm32 STM32 是一系列由STMicroelectronics(意法半导体)公司设计和制造的32位ARM Cortex-M微控制器。这一系列的微控制器广泛用…...
GPT-4 Turbo Assistants API
Assistants API Assistants API 允许您在自己的应用程序中构建 AI 助手。助手有指令,可以利用模型、工具和知识来响应用户查询。Assistants API 目前支持三种类型的工具:代码解释器、检索和函数调用。未来,我们计划发布更多 OpenAI 构建的工…...
day08_回顾与课程概括
回顾与课程概括 一、上节课复习 一、上节课复习 1、osi七层与数据传输 2、socketsocket是对传输层以下的封装ipport标识唯一一个基于网络通讯的软件3、tcp与udptcp:因为在通信之前必须建立双向连接,通常都是客户端主动连接服务端的,所以必须…...

iptables、netfilter、firewalld、ufd简单介绍
参考:...

Python基础入门例程53-NP53 前10个偶数(循环语句)
最近的博文: Python基础入门例程52-NP52 累加数与平均值(循环语句)-CSDN博客 Python基础入门例程51-NP51 列表的最大与最小(循环语句)-CSDN博客 Python基础入门例程50-NP50 程序员节(循环语句)-CSDN博客 目录 最近的博文: 描…...

v-bind和v-model
目录 前言 v-bind 作用 语法格式 编译原理 简写 v-model 作用 使用方法 v-bind和v-model的区别和联系 前言 本文我们来了解一下模板语法之指令语法中的v-bind和v-model v-bind 作用 v-bind可以让html标签的某个属性的值产生动态的效果 语法格式 <html标签 v-bin…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...

linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...

ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...