IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 常见HTTP错误码模拟 -> 正文阅读

[系统运维]常见HTTP错误码模拟

最近发现部分同学虽然知道HTTP错误码,但对产生的具体原因并不清楚,所以我打算对比较常见的错误码进行模拟,帮助大家理解。

环境搭建

首先我们先搭建一个用于模拟的环境,公司架构一般分为负载均衡层和服务层,负载均衡我们使用nginx,服务使用Go。

Go

本次使用Go代码,所有代码位于:https://github.com/shidawuhen/asap/blob/master/controller/various/httpcode.go

服务监听端口为:8082

访问:http://127.0.0.1:8082/ping 可看到返回

图片

Nginx

安装

Mac下安装Nginx命令:brew install nginx

Nginx安装位置为:/usr/local/etc/nginx

启动

命令行执行:nginx。没有报错表示执行成功。

访问

http://localhost:8080/

图片

配置

修改Nginx的config文件,将请求代理到Go服务。

location / {       #请求的url过滤,正则匹配,~为区分大小写,~*为不区分大小写。
                proxy_pass  http://127.0.0.1:8082;  #请求转向mysvr 定义的服务器列表
                proxy_set_header Host $host;
                proxy_set_header Connection "";   #设置Connection为长连接(默认为no)
                proxy_connect_timeout 30;         #与upstream server的连接超时时间
                proxy_read_timeout 60s;           #nginx会等待多长时间来获得请求的响应
                proxy_send_timeout 12s;           #发送请求给upstream服务器的超时时间
                proxy_http_version 1.1;
        }

Nginx加载新的配置:nginx -s reload

请求ping,可看到请求转发到Go服务。

图片

图片

200-OK


我们先看一下正常情况。

请求

http://localhost:8080/httpcode/code200

代码

对应的Go代码为:

func Code200(c *gin.Context) {
   c.String(http.StatusOK, "ok")
}

返回

图片

500-Internal Server Error


说明

500 (服务器内部错误):服务器遇到错误,无法完成请求。

内部服务错误:服务器遭遇到了一个预料之外的情况,这个情况阻止了它完成请求的处理。一般是语法错误或者服务panic。

请求

http://localhost:8080/httpcode/code500

代码

func Code500(c *gin.Context) {
   panic("1")
   c.String(http.StatusOK, "ok")
}

返回

图片

图片

原因

主要是因为Gin里使用了默认Recover中间件,panic后将状态设置为500

func Default() *Engine {
	debugPrintWARNINGDefault()
	engine := New()
	engine.Use(Logger(), Recovery())
	return engine
}

func defaultHandleRecovery(c *Context, err interface{}) {
   c.AbortWithStatus(http.StatusInternalServerError)
}

504-Gateway Time-out

说明

504 (网关超时): 服务器作为网关或代理,但是没有及时从上游服务器收到请求。

网关超时:服务器,当作为一个网关或代理工作时,没有从上游服务器接收到 为了完成请求 所需访问的 及时的响应(数据)。也就是说,nginx作为网关,为了完成请求,它必须获取到上游服务器的数据,但是上游服务器在规定时间内没有给到这些数据,所以nginx无法access到这些数据。也就是上游服务器响应超时了。

网关收到请求后,要调用其它服务器完成工作,其它服务器是上游服务器。

请求

http://localhost:8080/httpcode/code504

代码

func Code504(c *gin.Context) {
   time.Sleep(time.Second * 100)
   c.String(http.StatusOK, "ok")
}

返回

图片

原因

Nginx配置的超时时间为60s,但Go服务在100s后才能响应,所以60s后,Nginx没有收到响应,就直接返回504。

502-Bad Gateway

说明

502 (错误网关):服务器作为网关或代理,从上游服务器收到无效响应。

网关错误:服务器,当它作为一个网关或者代理去工作,尝试着处理请求时,它从它所进入的到达的 上游服务器 处,接收到了一个非法、无效的响应。

所谓的非法、无效,是指预期之外的响应。

请求

http://localhost:8080/httpcode/code502

代码

Go服务down掉

对于这种情况,Nginx直接返回502。

Go主动关闭连接

方案一:新起服务

这个操作需要服务端收到请求后,立即将conn Close掉:

package main

import (
   "fmt"
   "net"
)

func main() {
   ln, err := net.Listen("tcp", "127.0.0.1:8082")
   if err != nil {
      return
   }
   go func() {
      for {
         c, err := ln.Accept()
         fmt.Println("Accept")
         if err != nil {
            break
         }
         c.Close()
      }
   }()
   select {}
}

方案二:调整writetimeout

main函数中不使用run,使用自己构建的server,并设置WriteTimeout为1s。

//r.Run(":8082")
server := http.Server{
   Addr:         ":8082",
   WriteTimeout: time.Second * 1,
   ReadTimeout:  time.Second * 10,
   IdleTimeout:  time.Second * 10,
   Handler:      r,
}

server.ListenAndServe()

同时让函数休眠2s。

func Code502(c *gin.Context) {
   //方案二
   time.Sleep(time.Second * 2)
   c.String(http.StatusOK, "ok")
}

返回

图片

503-Service Unavailable


说明

503 (服务不可用):服务器目前无法使用(由于超载或停机维护)。通常,这只是暂时状态。

一般来说,出现503错误多半是因为网站访问量大,造成了流量超限或者并发数大引起的资源超限出现的错误。

模拟这种情况,需要改很多系统参数,风险较大,本次不做模拟。如果大家有别的模拟方法,可以告诉我。

499-CLIENT CLOSED REQUEST

说明

499(客户端关闭请求):一个被nginx引入的非标准状态码,对应的场景是,当nginx正在处理请求时,客户端关闭了HTTP连接。

引申出来,就是当HTTP请求到达Nginx后,该请求还在被处理的状态时,浏览器的请求超时时间到了,主动关闭了连接。但是,此状态码在浏览器请求时几乎不可见,因为浏览器默认的超时时间会很长。多见于服务之间的调用,在业务架构中常常会分层设计,拆分为不同的子系统或者微服务,这样系统之间就会常常通过http方式来请求,并且会设置每次请求的超时时间,当请求在请求时间内所调用的上游服务无返回,则会主动关闭连接,上游服务日志中会记录一条499。

请求

因为浏览器超时时间较长,所以使用curl命令,设置三秒超时:

curl -i -m 3 http://127.0.0.1:8080/httpcode/code499

代码

func Code499(c *gin.Context) {
   time.Sleep(time.Second * 100)
   c.String(http.StatusOK, "ok")
}

返回

通过nginx -V查看Nginx日志位置,找到access.log:

127.0.0.1 - - [28/Nov/2021:23:13:09 +0800] "GET /httpcode/code499 HTTP/1.1" 499 0 "-" "curl/7.64.1"

总结

虽然这次模拟了各种情况,但更加详细的原因在Nginx源码和Go源码中,大家有兴趣的话可以深入了解。

另外,在模拟过程中,使用的例子只是导致出现对应状态码的其中一些原因,还有其它的一些原因,大家可以寻找。

在模拟的过程中,自己也发现了很多新的知识点,还是很有趣的。

资料

  1. 常见HTTP错误代码大全

  2. http 5**系列状态码详解

  3. HTTP状态码 499 / 500 / 502 / 504

  4. Golang之HTTP server 502问题分析

  5. Gin设置Timeout

  6. HTTP CODE 状态码500|502|504分析

  7. mac下安装nginx

  8. Golang之HTTP server 502问题分析

  9. 记录一次线上502排查过程

  10. Golang 优化之路——HTTP长连接

  11. 客户端主动断开连接_Go实现客户端和服务器抓包分析TCP三次握手和断开操作

  12. 服务端主动终止连接的情况分析

  13. Gin IdleTimeout本地验证

  14. Nginx 503错误总结

  15. 低配终端环境下如何模拟大规模负载

最后

大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)

我的个人博客为:https://shidawuhen.github.io/

图片

往期文章回顾:

  1. 设计模式

  2. 招聘

  3. 思考

  4. 存储

  5. 算法系列

  6. 读书笔记

  7. 小工具

  8. 架构

  9. 网络

  10. Go语言

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-11-29 16:40:48  更:2021-11-29 16:41:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 2:42:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码