常见Http错误码学习

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

常见 http 错误码

服务器巡检时比较常见的 http 错误码

  • 400 Bad Request
  • 408 Request Timeout
  • 499 client has closed connection
  • 502 Bad Gateway
  • 504 Gateway Timeout
    这些错误码反映了服务器什么样的状态仅看字面意思还不太容易理解就动手做个试验吧

试验环境

在 linux 主机上运行 nginx在本机(windows 10)上运行 jettylinux 上的 nginx 反向代理到本机 jetty

试验工具

发送 http 请求主要采用 postman也使用了 telnet 和 python 脚本

试验

400

错误的请求比如必须的参数未传递那么我们来试下

@Controller
@RequestMapping("/api/")
public class TestController {


    @ResponseBody
    @RequestMapping("test.debug")
    public String test(@RequestParam(required = true) String name) {
        return name;
    }


}

可以看到 name 参数是必须的那么不带参数调用一下

http://xxxxx.in.xxxx.com/api/test.debug

返回 200.

怎么返回了 200 而不是预期的 400呢经过一番检查原来是有个异常处理程序捕捉到了参数未传递的异常并进行了处理如下

@Component
public class ExceptionHandler implements HandlerExceptionResolver {


    private static final Logger log = Logger.getLogger(ExceptionHandler.class);




    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
                                         Object handler, Exception ex) {
        response.setContentType("application/json; charset=UTF-8");
        String code = null;
        String message = null;
        if (ex instanceof BizException) {
            BizException exception = (BizException) ex;
            message = exception.getMessage();
            code = Integer.toString(exception.getErrorCode());
        } else if (ex instanceof MissingServletRequestParameterException) {
            code = "900002";
            message = ex.getMessage();
            log.error(message);
        } else {
            code = "403";
            message = ex.getMessage();
            log.error(ex, ex);
        }
        
        ModelAndView mav = new ModelAndView("error");
        mav.addObject("code", code);
        mav.addObject("message", message);
        mav.addObject("value", message);
        return mav;
    }


}

禁用该异常处理以后重新试验返回了 400如下

此外胡乱的发送数据给 nginx 服务器而不按 http 协议规范组织数据也会得到 400 的返回码可以用 telnet 试验一下如下图

在用 telnet 给 nginx 发送数据时输入 “HTTP/2.3.”由于 2.3. 是不存在的版本nginx 当即返回了 400 错误码

408

请求超时nginx 在规定的时间内无法获取到客户端的请求
这个错误码很奇怪根据该错误码的含义使用 telnet 和 python 进行模拟但无法使 nginx 返回 408 错误码…试验失败了
另外查看 nginx 日志发现返回 408 错误码的日志实际上请求都已经转发给 jetty 并且 jetty 也返回了 200 响应码.

所以这个错误码目前还无法解释

499

在 nginx 返回结果之前客户端断开了连接nginx 会记录 499 错误码到日志要重现这个错误码只需要让接口等待一段比较长的时间并在请求端主动断开即可如下

@Controller
@RequestMapping("/api/")
public class TestController {


    @ResponseBody
    @RequestMapping("test.debug")
    public String test(@RequestParam(required = true) String name) {
        try {
            Thread.sleep(300 * 1000);
        } catch (InterruptedException e) {
        }
        return name;
    }
}

在 postman 里发起请求并在等待的过程中点击 cancel 按钮

这时 postman 没有任何返回但是查看 nginx 的日志会发现一条 499 的记录如下

502

这个比较好理解jetty 服务挂了或者没有启动我们停掉 jetty 就可以得到这个错误码.

504

这是 jetty 响应超时了我们让接口等待 300 秒后返回来测试一下

@Controller
@RequestMapping("/api/")
public class TestController {


    @ResponseBody
    @RequestMapping("test.debug")
    public String test(@RequestParam(required = true) String name) {
        try {
            Thread.sleep(300 * 1000);
        } catch (InterruptedException e) {
        }
        return name;
    }
}

可以看到在60秒(准确的说60133 ms)以后nginx 返回了 504

这是因为 nginx 默认等待 jetty 60 秒时间到了 jetty 没有响应 nginx 就会自行返回 504如果想要 nginx 多等一段时间可以如下配置

proxy_read_timeout 6m; 

现在再试一下

可以看到经过 300 秒300062 ms的漫长等待我们得到了 jetty 的响应

结论

  • 400 客户端请求数据格式不对不符合接口规范.和客户端沟通要求客户端修复.服务端进行容错处理

  • 408不知道.继续研究

  • 499 由于服务器处理太慢客户端在规定的时间内未接收到响应主动断开连接.客户端网络被断开了在移动互联网环境下这还是比较常见的例如用户移动到 WIFI 覆盖区域以外/服务端优化性能

  • 502 服务器宕机, 重启服务器

  • 504 服务端响应太慢了, 优化性能

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

“常见Http错误码学习” 的相关文章