从云端坠落:PUT和DELETE请求在大公司的失宠之谜

从云端坠落:PUT和DELETE请求在大公司的失宠之谜

PUT 和 DELETE 请求是什么?

在深入探讨 PUT 和 DELETE 请求被弃用的原因之前,先来简单了解一下它们的定义和用途。PUT 和 DELETE 是 HTTP 协议中定义的两种请求方法,在 RESTful API 设计中扮演着重要角色。

PUT 请求主要用于更新资源,它的设计理念是客户端将完整的资源数据发送到服务器,服务器用这些数据替换指定的资源。例如,假设我们有一个用户资源,其唯一标识为123,存储在/users/123路径下。当需要更新这个用户的信息时,可以使用 PUT 请求:

Plain 复制代码
PUT /users/123 HTTP/1.1
Content-Type: application/json

{
    "name": "张三",
    "age": 30,
    "email": "zhangsan@example.com"
}

在这个请求中,请求体包含了完整的用户信息,服务器接收到请求后,会用这些数据完全替换/users/123路径下原来的用户资源。

DELETE 请求则用于删除资源。继续以上述用户资源为例,如果要删除 ID 为123的用户,可以发送如下 DELETE 请求:

Plain 复制代码
DELETE /users/123 HTTP/1.1

服务器收到这个请求后,会删除/users/123对应的用户资源,并返回相应的状态码,如204 No Content表示删除成功且没有返回内容。

曾经的 "宠儿",如今的 "弃子"

在早期的 Web 开发中,PUT 和 DELETE 请求可是 API 设计领域的 "宠儿"。它们清晰的语义和简洁的操作方式,与 RESTful 架构的理念完美契合,为开发者们提供了一种优雅的方式来管理资源。想象一下,就像一位优雅的管家,PUT 请求能够精准地更新资源,DELETE 请求则可以果断地删除不再需要的资源,一切都显得那么有条不紊 。许多大型互联网公司在构建 API 时,也都将 PUT 和 DELETE 请求视为不可或缺的一部分,大量应用在各种业务场景中,如用户信息管理、订单处理、内容发布等系统。

然而,时过境迁,曾经备受青睐的 PUT 和 DELETE 请求,在如今的大公司中却逐渐沦为了 "弃子"。越来越多的大型项目开始避免使用它们,甚至有些公司已经明确规定禁止在新的 API 中使用 PUT 和 DELETE 请求,这一转变不禁让人感到十分诧异。是什么原因导致了这种曾经被视为行业标准的请求方法在大公司中失宠呢?接下来,就让我们深入剖析背后的种种因素。

弃用背后的 "四大元凶"

PUT 和 DELETE 请求失宠的背后,有着多方面深层次的原因,这些原因相互交织,共同促使大公司们做出了弃用它们的决策。

幂等性难题:高并发下的 "定时炸弹"

首先,幂等性问题是 PUT 和 DELETE 请求在高并发场景下的一大 "致命伤"。幂等性是指一个操作无论执行一次还是多次,其产生的效果应该是相同的,不会对系统状态造成额外的影响 。从理论上来说,PUT 和 DELETE 请求都具备幂等性。对于 PUT 请求,无论向服务器发送多少次相同的更新数据,资源最终的状态都应该是一致的;DELETE 请求也是如此,多次删除同一个资源,最终结果都是该资源被删除,不会出现重复删除导致的额外问题。

然而,理想很丰满,现实却很骨感。在实际的高并发环境中,网络延迟、系统故障等各种不确定因素层出不穷,使得 PUT 和 DELETE 请求的幂等性难以得到有效保障。以电商系统的库存更新为例,假设商品库存初始值为 100 件,当有多个用户同时发起 PUT 请求来更新库存时,就可能出现问题。由于网络波动,第一个用户的 PUT 请求在传输过程中出现延迟,但并未超时,此时第二个用户的 PUT 请求先到达服务器并被处理,库存更新为 99 件。随后,第一个用户延迟的 PUT 请求也到达了服务器,由于它携带的是旧的库存数据(100 件),服务器会再次执行更新操作,将库存又改回了 100 件,这就导致了库存数据的不一致,可能引发超卖等严重问题 。DELETE 请求也存在类似风险,如果在删除资源的过程中,由于网络中断等原因导致请求被重复发送,可能会造成资源被多次移除,给业务带来意想不到的后果。

错误处理与回滚:复杂业务的 "荆棘丛"

错误处理和回滚机制的复杂性,也是 PUT 和 DELETE 请求在实际应用中面临的一大挑战,尤其是在分布式系统中。在分布式电商订单处理系统中,当使用 PUT 请求来更新订单信息时,可能涉及到多个服务和数据库的交互。比如,一个订单的状态更新,可能需要同时修改订单服务中的订单状态表、支付服务中的支付记录表以及物流服务中的物流信息表。如果在这个过程中,某个服务出现故障或者网络连接中断,导致 PUT 请求部分成功,部分失败,那么如何回滚到原来的状态就成为了一个棘手的问题。由于各个服务之间的事务是相互独立的,要实现全局的原子操作,确保所有相关数据要么全部更新成功,要么全部回滚,需要引入复杂的分布式事务管理机制,这不仅增加了系统的开发难度和运维成本,还可能影响系统的性能和可用性 。

DELETE 请求的情况则更为严峻,因为删除操作通常是不可逆的。一旦 DELETE 请求执行出错,想要恢复被删除的数据往往是非常困难的,甚至是不可能的。比如,在删除一个重要的订单数据时,如果因为数据库故障或者人为误操作,导致删除操作意外执行,而又没有完善的备份和恢复机制,那么这个订单数据就可能永远丢失,给企业带来巨大的损失。在大公司的复杂业务场景中,对数据的完整性和可靠性要求极高,任何数据丢失或错误都可能引发连锁反应,影响整个业务流程的正常运转。因此,DELETE 请求的高风险特性使得大公司在使用时不得不慎之又慎。

灵活性与易用性不足:复杂业务的 "绊脚石"

在灵活性和易用性方面,PUT 和 DELETE 请求也逐渐暴露出其局限性,难以满足现代复杂业务场景的多样化需求。与 POST 和 PATCH 等请求方法相比,PUT 和 DELETE 请求的操作相对较为单一和固定。PATCH 请求主要用于部分更新资源,它允许客户端只发送需要修改的字段,而不是像 PUT 请求那样必须提供完整的资源数据。这在实际应用中非常实用,比如当我们只需要修改用户的邮箱地址时,使用 PATCH 请求就可以只发送邮箱字段的更新内容,大大减少了数据传输量和服务器的处理负担,也降低了因为数据不全而导致更新失败的风险 。

POST 请求则更加灵活多变,它不仅可以用于创建资源,还可以通过在请求体中传递不同的参数和指令,实现各种复杂的业务逻辑。例如,在一个多功能的文件管理系统中,通过 POST 请求并搭配不同的参数,我们可以实现文件的上传、下载、复制、移动、重命名等多种操作,而不需要为每个操作都定义一个单独的 API 接口。相比之下,PUT 和 DELETE 请求的功能相对单一,难以适应这种灵活多变的业务需求。在面对日益复杂的业务场景时,它们的局限性就显得愈发明显,这也是大公司逐渐弃用它们的原因之一。

安全性风险:数据安全的 "漏洞"

安全性风险也是 PUT 和 DELETE 请求在大公司中被弃用的重要因素之一。直接使用 PUT 和 DELETE 请求来修改和删除资源,会给系统带来较大的安全隐患。在一个权限管理不够严格的系统中,如果黑客获取了用户的认证信息,就可以利用 DELETE 请求恶意删除用户的重要数据,如订单信息、个人资料等,给用户造成严重的损失。PUT 请求同样存在风险,如果黑客能够伪造合法的请求数据,就可能通过 PUT 请求篡改用户的敏感信息,如修改用户的支付密码、收货地址等,从而实施诈骗等犯罪行为 。

为了防范这些安全风险,大公司需要投入大量的精力和资源来加强审计和权限管理。这包括对每个 PUT 和 DELETE 请求进行严格的身份验证和授权检查,记录详细的操作日志以便于事后追踪和审计等。然而,即使采取了这些措施,仍然无法完全消除安全隐患,而且复杂的审计和权限管理机制还会增加系统的复杂性和运行成本。对于大公司来说,数据安全是至关重要的,任何一点潜在的风险都可能引发严重的后果。因此,为了降低安全风险,简化系统的安全管理,许多大公司选择放弃使用 PUT 和 DELETE 请求,转而采用更加安全可控的方式来处理资源的更新和删除操作。

替代方案大揭秘

既然 PUT 和 DELETE 请求存在这么多问题,那么大公司们都采用了哪些替代方案呢?

POST 模拟 PUT 和 DELETE 操作

一种常见的替代方式是使用 POST 请求来模拟 PUT 和 DELETE 操作。在这种方案中,客户端通过 POST 请求向服务器发送更新或删除资源的指令,并在请求体中添加一些自定义参数来标识请求的真正意图。例如,为了模拟 PUT 请求更新用户信息,客户端可以这样发送 POST 请求:

Plain 复制代码
POST /users/123 HTTP/1.1
Content-Type: application/json

{
    "_method": "PUT",
    "name": "李四",
    "age": 35,
    "email": "lisi@example.com"
}

在这个请求中,_method参数被设置为PUT,告诉服务器这实际上是一个 PUT 操作,而请求体中的其他数据则是要更新的用户信息。服务器接收到请求后,会根据_method参数的值来判断请求的类型,并执行相应的更新操作。

同样,模拟 DELETE 请求也可以采用类似的方式:

Plain 复制代码
POST /users/123 HTTP/1.1
Content-Type: application/json

{
    "_method": "DELETE"
}

这种模拟方式的原理其实很简单,就是利用 POST 请求的灵活性,将原本属于 PUT 和 DELETE 请求的语义和操作封装在 POST 请求中。通过自定义参数的方式,服务器可以解析出请求的真实意图,从而实现与 PUT 和 DELETE 请求相同的功能 。它有效地解决了 PUT 和 DELETE 请求在某些环境下不被支持或存在风险的问题,同时也继承了 POST 请求广泛被支持和灵活多变的优点。

PATCH 结合其他请求实现复杂功能

另一种常用的替代方案是使用 PATCH 请求结合其他请求方法来实现资源的更新和删除。如前文所述,PATCH 请求主要用于部分更新资源,它只需要客户端发送需要修改的字段,而不是整个资源数据,这在很多场景下都非常实用 。在更新用户信息时,如果只需要修改用户的邮箱地址,可以使用如下 PATCH 请求:

Plain 复制代码
PATCH /users/123 HTTP/1.1
Content-Type: application/json

{
    "email": "newemail@example.com"
}

服务器接收到这个请求后,会根据请求体中的数据,只更新用户资源中的邮箱字段,而其他字段保持不变。这种方式不仅减少了数据传输量,还降低了因为数据不全而导致更新失败的风险。

对于删除操作,除了可以使用 POST 模拟 DELETE 请求外,还可以通过在业务层面实现软删除的方式来替代真正的 DELETE 操作。软删除并不是直接从数据库中删除资源,而是在资源表中增加一个删除标记字段(如deleted_at),当需要删除资源时,只需要将该字段的值更新为当前时间或其他表示删除的标识即可 。这样,在查询资源时,通过过滤掉deleted_at字段不为空的记录,就可以实现逻辑上的删除效果。这种方式结合 PATCH 请求来更新删除标记字段,既保证了数据的安全性和可恢复性,又实现了类似 DELETE 请求的功能。

在实际应用中,大公司通常会根据具体的业务需求和系统架构,灵活选择合适的替代方案。这些替代方案不仅能够有效地解决 PUT 和 DELETE 请求存在的问题,还能更好地适应复杂多变的业务场景,为系统的稳定运行和业务的高效发展提供有力支持。

相关推荐
文心快码BaiduComate2 小时前
有奖征集|解锁Comate超能力:一文玩转Comate Skills
前端·后端
StackNoOverflow2 小时前
Spring Boot 核心知识点总结
java·spring boot·后端
世界哪有真情2 小时前
使用 Arthas 精准排查 SpringBoot 多模块项目中未使用的类(安全清理无用代码)
java·后端
司南-70492 小时前
claude初探- 国内镜像安装linux版claude
linux·运维·服务器·人工智能·后端
wangchunting2 小时前
Spring Boot 概述
java·spring boot·后端
JuiceFS2 小时前
ARM 架构 JuiceFS 性能优化:基于 MLPerf 的实践与调优
后端·性能优化
颜酱2 小时前
回溯算法实战练习(2)
javascript·后端·算法
未秃头的程序猿2 小时前
Redis也能做消息队列!Spring Boot实战:从List到Stream的优雅实现
redis·后端
编码忘我2 小时前
JVM 运行时数据区详解
java·后端·程序员