为什么要区分不同的 http 状态码?想说服同事

2022-04-13 10:28:42 +08:00
 dunhanson

我的个人的理解还是,这么做比较规范

但是同事的理解更多是优点好处是什么

比如用户登录错误之前的方式都是返回 http 状态码 200

{
  "code":4001001001,
  "message":"用户登录失败"
}

现在按照规范应该是,返回 http 状态码 401 ,然后 json 还是老样子

17789 次点击
所在节点    程序员
176 条回复
seakingii
2022-04-13 13:57:50 +08:00
@vayci 因为这是一个对工作影响比较大的事情,而且这个事情从有 restful 规范到目前为止还没有完美解决方案.不断的新人进来,不断的有疑惑
EastLord
2022-04-13 14:01:33 +08:00
yolee599
2022-04-13 14:04:04 +08:00
全 http 状态码 200 方便,统一解析 body 再判断。如果 http 状态码和应用状态码一起用还要判断两次,比如 http 状态码为 401 ,有可能是未登录,有可能是 token 过期,有可能是触发风控...
iyaozhen
2022-04-13 14:05:55 +08:00
你要不用 restful 规范我都不说啥了,200 一把梭 坚决反对
说两点
1. 监控怎么做?都是 200 ,怎么知道错了
2. ( nginx )重试怎么做?
777777
2022-04-13 14:08:52 +08:00
直接 openapi 一把梭,还能生成文档,服务端客户端代码。
zhuweiyou
2022-04-13 14:12:36 +08:00
个人全 200, 理由是在 websocket 之类的场景,我仍然需要把 code 放在 json 里.
ZeroDu
2022-04-13 14:21:33 +08:00
restful 这东西是真不好用就是了
Chad0000
2022-04-13 14:25:23 +08:00
@adoal #58
很是赞同。业务是业务,http 服务是 http 服务。业务监控自有各种监控中间件。否则哪天不用 http 了或者需要兼容另外一种协议,就完犊子了。
Kinnice
2022-04-13 14:25:27 +08:00
@iyaozhen 虽然我也反对 200 一把梭,但是你这两点貌似都没太大关系吧,
监控:
1. 业务监控,那解析 body 是应该的,
2. 链路监控,业务出问题和你链路有啥关系?
3. 混合监控,就算你看到了 4xx/5xx 你不解析 body ,能准确反应出原因? httpcode 可没这么全
nginx 重试:
业务出问题了,你网关重试个啥? 比如我 post 添加一条数据,失败了,你 nginx 还帮我重试一下?
iyaozhen
2022-04-13 14:25:53 +08:00
@adoal
@xuanbg

监控的事情我说下个人看法

业务要监控这个是肯定的。但这就需要一个规范,不管是分开打日志还是怎么的。
http 状态就是一个规范,比如我是公司做网关的基建部门,公司几万个研发,你让 json 里面字段怎么约束?这个人用 code xxx ,那个人 status xxx ,我无法监控呀。但有个 http 状态码 5xx ,我就能知道这个业务挂了,可以进行一些预案。至于定位又要扯到 logid 串联了。

当然这也是搂底,业务自己的日志还是得配置关键字接口,两者结合。
pengtdyd
2022-04-13 14:26:01 +08:00
200 一把梭 坚决反对!!!
20X 、40X 、50X 这些是 HTTP 状态码和业务状态码混淆在一起怎么做监控???
错误码设计可以参考阿里巴巴《 Java 开发手册》错误码的制定原则:快速溯源、简单易记、沟通标准化。
1 )错误码必须能够快速知晓错误来源,可快速判断是谁的问题。
2 )错误码易于记忆和比对(代码中容易 equals )。
3 )错误码能够脱离文档和系统平台达到线下轻量化地自由沟通的目的。
iyaozhen
2022-04-13 14:30:00 +08:00
@Kinnice
我说的是网关层面的搂底监控。这种时候各个业务 json 都不一样,解析不了,而且影响性能。有个 5xx 监控会好很多

nginx 重试
说的是幂等的重试,比如 GET 、PUT ,当然如果 POST 一把梭就做不了了。
Kinnice
2022-04-13 14:33:10 +08:00
这个问题还有个孪生题目: 为什么要区分不同的 HTTP 请求方法?(hhhhhhh)
jjwjiang
2022-04-13 14:34:10 +08:00
@daimubai 同意,真不知道搞技术的也这么多一根筋的。

拿 400 和 422 举例,422 可以很容易的覆盖一部分业务错误,所有参数上的不合法都可以归到 422 里,对监控更容易,跟别的合作伙伴做对接也更简单。

比如 request 定义是
{ n:int, s: string}
而 n 要求大于 0 ,s 要求不能为'',那么
{'1'}
就会对应到 400
{n:'1',s:1}
{n:-1,s:''}
对应到 422
而 n:1998 会造成业务上出错,那自然是以 200+message 返回

界限很清楚也很好用,422 我就去检查参数值,400 就检查参数格式,而 4 开头的都会被浏览器认定为 client 错误,事实上也确实是作为 client 的调用方有错误,不挺好吗?

rest 规范你觉得不合理就选择使用就完了,全盘否定或者全盘肯定都是不现实的。
adoal
2022-04-13 14:37:09 +08:00
@iyaozhen 屁股决定脑袋。你所谓的对业务的监控,是指想知道业务挂了,这个问题本来就属于基建。我也说了,如果业务系统里发现有基建问题,硬生生抓住包成一个 200 抛回给调用方,这个我也不能接受的。但很多莱塞特福原教旨主义者想要做的是把业务逻辑层面的错误也给放到 HTTP 状态码里,比如一个大学生离校系统里要去查学生在各个单位的业务是否已结清,我一个图书馆系统的接口发现还有书没还的时候,给他返回 HTTP 200 再加一个 JSON 表示业务层面这个操作不成功,但我的系统没挂,调用方传进来的参数也符合 schema ,权限也对,所以在 HTTP 层面我认为没问题,不应该返回错误码……有人说这样不清真,应该改成在 HTTP 码里把这个当“错误”来返回,不能塞进 200 的 JSON 里。这不是扯鸡巴蛋吗。总不会有人为了方便监控离校系统调用图书馆系统接口时的业务逻辑错误率而想把我千奇百怪的业务错误码从 JSON 里提出来放到 HTTP 状态码吧。
Actrace
2022-04-13 14:43:54 +08:00
我觉得应该用 TCP 的状态( etc.. LISTEN ,SYN_SENT ,ESTABLISHED...)来表示。这样比较底层,权威性更高一些。
HTTP 协议的状态码都已经是最顶层了,不权威的。

...说笑的。

既然 https://coolshell.cn/articles/22173.html 里说到 HTTP 是协议的一种,STATUS 属于协议的部分,而承载的 BODY 才是业务内容。那么我认为用于处理业务问题的业务协议及其内容,与 HTTP 协议是两种不一样的东西,HTTP 协议的所有内容应该专注于它本身需要专注的部分。

比如 STATUS 503 是服务不可用,服务不可用是服务器硬件资源的问题,而不是业务不可用。尽管业务和服务器状态本身是互相关联的,但是我们应该尽可能去解耦,让运维团队专注解决硬件资源问题,业务团队专注解决业务问题。

虽然大多数情况下,你一个人就是一支军队,所以所有问题都自己解决的话,倒不是有必要区分得那么明显了。

所以还是看业务规模吧,以上个人观点仅供参考。
3dwelcome
2022-04-13 14:44:43 +08:00
@iyaozhen “你要不用 restful 规范我都不说啥了,200 一把梭 坚决反对
1. 监控怎么做?都是 200 ,怎么知道错了”

监控可以另外写 API 。我们的业务不仅仅是 HTTP 协议哦。HTTP 协议只是业务传输载体之一,还有 TCP 封装和 websocket 封装,底层调用的业务逻辑代码,是同一个模块。
james2013
2022-04-13 14:45:14 +08:00
反正客户端方面,接口方面区分状态码就很烦
客户端哪里知道后台接口使用 4xx,5xx 呢?比如后台在某些 4xx,5xx 里是框架自带的错误码,而不是固定的 json 对象
还不如直接返回 200,在统一的返回对象里统一处理和提示
jjwjiang
2022-04-13 14:50:50 +08:00
@james2013 你这说法就不太对了,显然在现代前端里 promise 广泛使用的情况下,catch 比 if(res.code ==200)的语义化和代码结构更佳。
lolizeppelin
2022-04-13 14:56:44 +08:00
一般是代码设计有问题,有错没错的返回混了,只能用 result 里的 code 判断了

正确设计是所有错误以 raise

http 返回的部分加一个 translation 把内部 Error 翻译成 Http Error

最好 rpc 也能把 raise 的异常传递

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://yangjunhui.monster/t/846679

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX