REST激情200



我一直想写这篇文章。 我一直想知道哪一侧更正确地输入。 但是,突然之间,最近在哈布雷(Habré)上出现了类似的文章,这引起了一场风暴。 最令我惊讶的是,尽管没有声明任何内容,但文章开始以小写大写,但提出了在REST中使用Web服务器响应代码的问题。 辩论激烈展开。 而且,有一个神化,那就是文章进入了草稿……千字节的评论,意见等。 只是消失了。 许多人成为卡莫人的受害者,想一想,:)

通常,正是这篇文章的命运促使我撰写了这篇文章。 我真的希望它会有所帮助并澄清很多。

我警告您,下面写的所有内容都是真实的经历,而不是认知上的平衡行为。 因此,他们开车。

HTTP


首先要做的是非常清楚地分离各层。 传输层是http。 好吧,实际上是REST。 在接受一切和其中的“自己”方面,这是根本重要的事情。 让我们先只谈论http。

我用术语“运输层”。 而且我没有保留。 问题是http本身实现了将请求传输到服务器并将内容传输到客户端的功能,而与tcp / ip无关。 是的,它基于tcp / ip。 似乎有必要将其视为运输工具。 但是没有 这就是为什么-套接字连接不是直接的,即 这不是客户端服务器连接。 http请求和http响应都可以通过大量服务走很长一段路。 相反,它们可以聚合或分解。 可能被缓存,可能被修改。

即 http请求和http响应都有自己的路由。 它不依赖于后端,也不依赖于前端。 我请你对此特别注意。

http路由不是静态的。 它们可能非常复杂。 例如,如果将平衡器内置到基础结构中,则它可以将接收到的请求发送到任何后端节点。 同时,后端本身可以实现自己的处理请求的策略。 其中一些将直接进入微服务,一些将由Web服务器本身处理,一些将被添加并转移给其他人,还有一些将从缓存中发出,等等。 这就是互联网的工作方式。 没什么新的。

在这里重要的是要了解-为什么我们需要响应代码? 问题是上述整个模型都基于这些决策做出决策。 即 这些代码使您可以在http路由期间做出基础结构和传输决策。

例如,如果平衡器遇到来自后备503的响应代码,则在发送请求时,他可以以此为理由认为该节点暂时不可用。 我注意到代码503的响应提供了Retry-After标头。 从头接收到重复轮询的间隔后,平衡器将在指定的时间段内将节点置于单独状态,并与可用的节点一起工作。 此外,Web服务器“开箱即用”地实施了此类策略。

深入了解的一个小问题-如果节点响应500,该怎么办? 平衡器应该做什么? 切换到另一个? 许多人会回答-当然,所有5xx禁用节点的理由。 他们会错的。 代码500是意外的错误代码。 即 一种可能永远不会再发生的事情。 最重要的是,切换到另一个节点可能不会更改任何内容。 即 我们只是禁用节点而没有丝毫好处。

如果是500,统计数据对我们有帮助。 节点的本地WEB服务器可以将其自身转换为不可用状态,其中包含500个答案,在这种情况下,与该节点联系的平衡器将收到503响应,并且不会触摸它。 结果是一样的,但是现在,此解决方案有意义,并且消除了“错误”响应。

但这还不是全部。 在这种情况下,监视将允许管理员连接到该情况以维护节点。 即 我们不仅可以使用平衡器等来实现高度可访问的服务,还可以实现有效的支持流程。

所有这些使您可以制作服务器响应代码。 任何WEB应用程序体系结构都应从传输层的设计开始。 我希望毫无疑问。

休息


我会提出一个反问:这是什么? 那你对他回答了什么? 我不会提供指向明显证据的链接,但很可能与事实不完全相同:)这只是一种意识形态,风格。 关于该主题的一些注意事项-如何与背面进行最佳沟通。 不仅可以进行通信,还可以在WEB基础结构中进行通信。 即 基于http。 上面我写过所有这些“有用的东西”。 实现界面的最终决定权归您所有

您是否曾经想过为什么没有发明单独的REST传输方式? 例如,对于websocket。 是的,它也以http开头,但是在建立连接后,通常这是一首单独的歌曲。 为什么不对REST做同样的事情?

答案很简单-为什么? 有一个漂亮的,现成的,经过验证的协议-http。 它可以很好地扩展。 使您能够实施复杂,高度可访问的服务,以应对沉重的负担。 所需要做的只是引入一些概念性规则,以便开发人员彼此了解。

从这里可以得出一个简单而明显的结论-http固有的一切都是REST固有的。 这些是不可分割的实体。 没有单独的REST标头,甚至没有暗示REST是REST。 对于任何REST服务器,该请求都与其他请求完全相同。 即 REST就是我们的想法。

REST http响应码


让我们谈谈您的服务器应响应REST请求的哪些代码? 就我个人而言,从以上所有方面看来,答案已经很明显了,因为 REST与任何其他请求没有什么不同,它必须遵循完全相同的规则。 响应代码是REST不可或缺的一部分,应与响应的本质相关。 即 如果没有通过请求找到对象,则为404,如果客户端提出了不正确的请求400,依此类推。 但是,大多数情况下,辩论并没有就此结束。 因此,我将继续。

是否可以用代码200回答所有问题? 谁会禁止你? 请……代码200与其他代码相同。 的确,此方法的基础是一个非常简单的论文-我的系统很完美,没有错误。 如果您是可以创建此类系统的人,那么这将是令人羡慕的!

但是很可能...她并不完美。 错误的确会发生。 碰巧它们是由于我们无法控制的情况而发生的。 这里典型的解决方案是创建您自己的错误编码系统。 那不好吗? 是的,那很糟糕。 这太糟糕了。 让我们找出原因。

因此,将代码200当作唯一的代码,我们负责开发系统的整个层(关键层)-错误处理。 即 开发此层的许多人的劳动被废弃了。 他的“自行车”的建造开始了。 但是,这座巨大的建筑注定要失败。

让我们从代码开始。 如果我们要回答所有200个问题,我们自己将不得不处理错误。 经典方法是try构造。 每个代码段我们都包装了其他代码。 做一些有用的事情的处理程序。 例如,他们在日志中放置了一些内容。 重要的事情。 这样可以定位错误。 如果错误出现在预期的地方? 还是如果错误处理程序中发生错误? 即 此策略在代码级别上无法正常运行。 最后,解释器或平台将处理您的错误。 操作系统终于。 该错误的实质是您不等待它。 您不需要隐藏它,您需要查找并修复它。 因此,如果REST响应一些错误为500的请求,这是正常现象 。 而且,

让我们回到问题上-为什么这样对? 因为:

  1. 代码500是基础结构令牌,基于该令牌可以禁用发生问题的节点。
  2. 5xx代码是受监视的代码,如果出现此代码,则任何监视系统都将立即通知您。 并且及时的支持服务将能够连接到问题的解决方案;
  3. 您不编写其他代码。 不要为此浪费宝贵的时间。 不要使体系结构复杂化。 您不会处理自己不寻常的问题,而是编写应用程序代码。 他们想要你什么。 他们要付什么钱?
  4. 错误地遗漏的跟踪500比您尝试超过它的尝试有用得多。
  5. 如果REST请求返回了500个代码,则在处理响应时前端已经知道通过哪种算法来处理它。 此外,问题的本质不会以任何方式改变,您不会从200和500那里收到任何明智的信息。但是从500方面您已经获得了利润-意识到这是一个意外错误。
  6. 代码500将带有保证。 无论您编写代码有多糟,都没问题。 这是你的支点。

另外,我将钉子钉在代码200的整个“主体”中:

7.即使您尽力避免来自服务器的200以外的其他响应代码到您的请求,您也不能这样做。 任何中间服务器都可以使用任何代码来响应您的请求。 而且您应该正确处理这样的答案。

总体而言,在逻辑层面上,争取代码200的努力是没有意义的。

现在让我们回到基础架构级别。 我经常听到这样的意见-5xx代码不是应用程序级别,不能给予支持。 嗯,好吧……声明本身存在矛盾。 你可以给。 但是此代码不是应用程序级别。 确实如此。 为了理解这一点,我建议考虑以下情况:
您正在实现网关。 您有几个DC,每个DC都有通往特定私人服务的专用通信通道。 好吧,例如,通过VPN付款。 并且存在与Internet进行通信的渠道。 您收到使用网关进行操作的请求,但是...该服务不可用。
那你该怎么回答? 给谁 这是一个基础结构问题,特别是备份遇到了问题。 当然,您需要大胆地回答503。这些操作将导致以下事实:该节点将在一段时间内被平衡器禁用。 同时,如果配置正确,则平衡器不会断开与客户端的连接,会将请求发送到另一个节点。 并且...最终客户很有可能收到200。并且不是错误的自定义描述,这对他没有任何帮助。

在哪里使用什么代码


问题并不简单。 没有确切的答案。 对于每个系统,都会设计一个传输层,并且其中的代码可能是特定的。

有公认的标准。 可以轻松找到它们,同样,我也不会给出明显的证据。 但是,我不会给您带来明显的印象-developer.mozilla.org/en/docs/Web/HTTP/Status
为什么是他 问题在于,代码处理程序的行为可能会有所不同,具体取决于“理解代码”的实现和上下文。 例如,浏览器具有基于响应代码的缓存策略。 并且某些服务具有自己的自定义代码。 例如,CloudFlare。

即 做出有关代码使用的决策时,您需要基于传输层中包含的所有元素,从背面的代码到客户端的代码。 这是找到正确答案的唯一方法。 在这里,我什至不会尝试给所有人服用通用药。

邪恶之源


这是我在REST中遭受代码200困扰的第三个项目。 很痛苦。 没有别的词了。 如果您仔细阅读当前的所有内容,您已经了解到,项目开始发展后,就需要基础设施开发及其可持续性。 代码200杀死了所有这些企图。 首先,您必须打破刻板印象。

在我看来,罪恶的根源在于以下事实:代码500是Web开发人员在其职业生涯中遇到的第一件事。 可以说是儿童时期的伤害。 他最初的所有努力归结为获得代码200。

顺便说一下,由于某种原因,在同一阶段,人们形成了一种强烈的意见,即只有带有代码200的答案才能提供给主体。 当然,事实并非如此,任何答案都可能随任何代码一起“出现”。 代码是代码。 身体就是身体。

此外,随着开发人员的发展,他需要管理自己应用程序的错误。 但是...,他不知道如何使用日志。 无法配置Web服务器。 他正在学习。 那些非常“伟大的”诞生了。 因为他可以使用它们,所以他可以快速制作它们。 此外,他在这个“伟大的”汽车上安装了新的车轮,加固了车架等。 这位出色的人在足够长的一段时间内成为了他的伴侣,直到...直到他完成了真正复杂的多组件任务。 正如他们所说,在这里-禁止以“巨大”和轮滑进入超市。

PS:提到的文章的作者从草稿中恢复了它-habr.com/en/post/440382 ,因此您也可以熟悉它。

PPS:我试图说明在REST中使用相关响应代码的所有方面。 我不会回应评论,请正确理解我的意思。 我会非常注意地阅读它们,但是我没有补充。 非常感谢您耐心阅读本文!

Source: https://habr.com/ru/post/zh-CN440900/


All Articles