nginx源码分析之header小写问题以及C开源项目调试技巧
写在前面我为什么要写博客,总感觉东西是自己,知道就知道了。为什么一定要写下来呢?我也不知道。前言nginx开启HTTP2模式下 header头全部小写,导致前端取header头出错。HTTP2模式下,header会压缩,并采用霍夫曼编码的压缩方式。推测可能,HTTP2如果header头大小写敏感的话,可能压缩效果不是很好。为什么?组合数学,信息论?此不在本文讨论范畴。header头为...
写在前面
我为什么要写博客,总感觉东西是自己,知道就知道了。为什么一定要写下来呢?
我也不知道。
前言
nginx开启HTTP2模式下 header头全部小写,导致前端取header头出错。
HTTP2模式下,header会压缩,并采用霍夫曼编码的压缩方式。推测可能,HTTP2
如果header头大小写敏感的话,可能压缩效果不是很好。为什么?组合数学,信息论?
此不在本文讨论范畴。header头为什么会小写,这些不是nginx的东西,这些是HTTP2协议的规范,nginx只是实现而已。
本机环境
Linux wwx-desktop 4.15.0-54-generic #58~16.04.1-Ubuntu SMP Mon Jun 24 13:21:41 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
nginx调试
nginx调试有点特别,因为nginx不仅会启动main方法,还会在main方法中fork子进程,
俗称nginx的工作进程,可能fork多个子进程,仅从nginx配置可窥知一二。
默认gdb调试配置,
是不会进入子进程的断点的,所以gdb调试需要用到以下两个命令
set detach-on-fork off
set follow-fork-mode child
步骤
- 下载nginx源码文件http://nginx.org/en/download.html,选择1.10.3版本以上,因为至此开始
nginx才支持HTTP2协议。源码目录
- 简单编译安装只需要两个命令:
./configure --prefix=/usr/local/nginx
--with-http_stub_status_module
--with-http_ssl_module
--with-http_v2_module --with-debug
make install
第一个命令解释如下:nginx高性能,你用哪些模块我就编译哪些模块,所以nginx不会主动编译所有模块。
至于–with-debug,nginx不会主动把debug模块加入进去,如果你想nginx支持日志级别debug你也要编译进去。
- 记录一些编译的时候的日志输出:
在我们执行第二个步骤的第一个命令的时候,nginx会在源码的根目录创建文件夹objs,并生成三个重要的文件
/home/nginx-1.10.3/objs/ngx_auto_config.h
/home/nginx-1.10.3/objs/ngx_auto_headers.h
/home/nginx-1.10.3/objs/ngx_modules.c
这些文件在以后的编译都会用到。
在执行第二个命令的时候,makefile会打印这样一条链接的日志输出:
...
objs/src/http/modules/ngx_http_stub_status_module.o \
objs/ngx_modules.o \
-ldl -lpthread -lcrypt -lpcre -lssl -lcrypto -ldl -lz \
-Wl,-E
...
这个以后也会用到。
- 把代码移植到clion ide中,clion是什么?我是JetBrains的铁粉。
移植后的目录如下:
cmake是什么?自行百度,这里面我简单提一下几个配置说明:
- ADD_DEFINITIONS() 宏定义为空,因为nginx所欲宏的预定义都在自动生成的两个个头文件里面
对应的就是
/home/nginx-1.10.3/objs/ngx_auto_config.h
/home/nginx-1.10.3/objs/ngx_auto_headers.h - TARGET_LINK_LIBRARIES(nginx_1_10_3 -ldl -lpthread -lcrypt -lssl -lpcre -lcrypto -lcrypto -lz)
为什么这么写,参见make install日志输出即可。 - SET(SOURCE_FILES …) nginx源文件包含哪些,有些不需要就不要写进去,比如
在src/event/modules/有如下一下网络模型文件并区分操作系统:
ngx_devpoll_module.c
ngx_epoll_module.c
ngx_eventport_module.c
ngx_kqueue_module.c
ngx_poll_module.c
ngx_select_module.c
ngx_win32_select_module.c
为什么我知道要用第二个文件?很简单,你去你的objs对应的目录下查看存在哪些.o文件即可。
4. cmake命令大小写不敏感
- 开始debug
几点配置直接上图
编写nginx.conf
worker_processes 1;
daemon off;
error_log /home/nginx-1.10.3/logs/error.log debug;
error_log /dev/stdout debug;
worker_processes 1;我不知道配置多个工作进程,clion在debug的时候会出现什么怪异现象。
daemon off;ngnix前台启动,方便debug断点。
error_log /dev/stdout debug;nginx日志输出到标准输出上面。就是控制台啦。
upstream book_pool{
server 127.0.0.1:8081;
}
server {
access_log /home/nginx-1.10.3/logs/host.access.log main;
access_log /dev/stdout main;
listen 80;
server_name lbs.test.com;
listen 443 ssl http2;
ssl_certificate /home/py/cert.crt;
ssl_certificate_key /home/py/rsa_private.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers AESGCM:ALL:!DH:!EXPORT:!RC4:+HIGH:!MEDIUM:!LOW:!aNULL:!eNULL;
ssl_prefer_server_ciphers on;
开启ssl和http2。
关于
ssl_certificate /home/py/cert.crt;
ssl_certificate_key /home/py/rsa_private.key;
自行百度即可。
断点一定要打在main还没有fork子进程之前,如下如图:
然后打开gdb,依次输入以下命令,并放开断点即可
set detach-on-fork off
set follow-fork-mode child
命令含义:
GDB默认调试的是只跟进父进程,是由follow-fork-mode(fork跟进模式)和detach-on-fork
(是否分离两个进程)共同决定的,他们的作用效果见下:
follow-fork-mode | detach-on-fork | 功能 |
---|---|---|
parent | on | 只调试父进程(默认) |
child | on | 只调试子进程 |
parent | off | 调试两个进程,跟进父进程,子进程阻塞在fork处 |
child | off | 调试两个进程,跟进子进程,父进程阻塞在fork处 |
- 编写python3简单web脚本
from http.server import HTTPServer, BaseHTTPRequestHandler
class MyHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Lbs_Channel', 'QuickApp')
self.end_headers()
self.wfile.write(b'hello world')
return
if __name__ == '__main__':
try:
server = HTTPServer(('', 8081), MyHandler)
server.serve_forever()
except KeyboardInterrupt:
print
'^c received,shutting down the web server!'
server.socket.close()
启动之。
- 你可以在浏览器输入http://lbs.test.com/ 或者https://lbs.test.com/
查看分析nginx在不同的情况下处理流程,http1和http2还是很有区别的。
本文目的不在这,主要分析在http2下header小写的问题。
debug关键位置
从上问的处理流程可看出问题霍夫曼编码的存在。
header压缩,采用huff编码,nginx静态huff编码方式。
在HTTP2中使用的是静态Huffman编码。Huffman编码按理说应该不属于计算机,
而是信息论的东西,这里不细说。对于HTTP2,查表即可。
表格地址:https://tools.ietf.org/html/rfc7541#appendix-B
调试项目 github 地址:https://github.com/wwxname/nginx-debug.git
结束
撒花 撒花
enjoy it
更多推荐
所有评论(0)