wenqiang li
wenqiang li
### 前言 最近,又再重复着看nginx的代码。越看越激动,设计的如此精妙。代码写的也非常的好。 nginx是个非常强大的web服务器、反向代理服务器。他的强大之处离不开他的配置文件。那么配置文件是如何解析的呢?又是通过什么数据结构存放的呢? ### 解析流程 首先,c函数从`main`开始执行,在`main`函数调用了`ngx_init_cycle`函数。在该函数中初始化了一个`conf_ctx`指针数组用来存放各个模块的配置文件结构体指针,随后又调用了所有`NGX_CORE_MODULE`模块的`create_conf`创建核心模块配置结构体。最后通过调用两个方法来解析命令行配置和文件配置指令。这两个函数分别是:`ngx_conf_param`和 `ngx_conf_parse`。前面是解析命令行配置参数,后面是解析文件配置参数。前面的函数最终还是调用了后面的,那我们直接看后面的函数,如果传入配置文件结构体指针不为空,那么打开配置文件读取配置文件指令。最后调用`ngx_conf_handler`解析配置指令,该方法才是解析配置文件最核心的方法,会根据配置指令遍历所有模块找到能解析该指令的方法,找到后调用对应模块的set方法。 ### 解析细节说明 上述从整体流程介绍了一下解析配置文件的过程。本节通过具体的函数说明一下。 ./core/nginx.c:main ``` c ...... //根据编译生成的模块数组初始化每个模块的序号index。同时把模块的个数赋值给ngx_max_module ngx_max_module = 0; for (i = 0; ngx_modules[i]; i++) { ngx_modules[i]->index = ngx_max_module++; }...
当我们在代码里面curl一个url的时候,有时候会遇到一些奇葩的设计,url里有中文需要对url进行编码。如果直接调用`url.QueryEscape`转码,`http.Get()`时候会报错"unsupported protocol scheme"。如果不转码那么又会报http status 400. 那么,该怎么转码呢?go里貌似也没有一个现成的函数供直接转url的参数的。那就需要我们自己封装一个: ``` func UrlEncode(u string) (string, error) { uary := strings.SplitAfterN(u, "?", 2) if len(uary) == 2 { m, e := url.ParseQuery(uary[1]) if e !=...
http2.0 协议是一个二进制协议。具体特性就不再多介绍了。 http2.0是应用层协议,传输层还是tcp协议。http2.0协议支持http的和https的,http的需要多一次协议协商。https的需要ssl支持alpn。 ### 明文协议: + client -> server: ``` GET / HTTP1.1 Connection: Upgrade, HTTP2-Settings Upgrade: h2c ``` + server -> client: ``` HTTP/1.1 101 Switching Protocols Connection: Upgrade...
# http2.0介绍 ### 背景 几乎所有互联网上的网页内容都采用了http1.1传输。随着网页内容和样式的发展,http1.1协议的劣势逐渐明显并最终拖了后腿。 于是在2014年HTTPbis小组决定定制http2.0协议。而早在2012年google就设计了SPDY协议用来解决http1.1的缺陷,并被用于Google Chrome浏览器中来访问Google的SSL加密服务,据官方说明使用spdy协议页面加载时间相比于http1.x减少了64%。因此,HTTPbis便基于SPDY/3草案进行一些修改之后发布了http2的draft-00。 RFC 7540 (HTTP/2) 和 RFC 7541 (HPACK) ### http2.0 #### 简介 + 继续维持HTTP1.1的模型。 客户端基于tcp协议发送请求到服务器。 + 不改变`http://`和`https://`协议的URL。 + 新的二进制格式。 为了解h2协议还需要了解这三个概念: - 数据流(stream): 已建立的连接内的双向字节流,用唯一ID标示,可以承载一条或多条消息。 -...
### 概述 nginx开启http2.0, safari报:“NSPOSIXErrorDomain:100” 在MacBook上 curl(curl 7.64.1 (x86_64-apple-darwin19.0) libcurl/7.64.1 (SecureTransport) LibreSSL/2.8.3 zlib/1.2.11 nghttp2/1.39.2)也会报错: ```sh * Connection state changed (MAX_CONCURRENT_STREAMS == 128)! * http2 error: Invalid HTTP header field was received:...
### 概述 ngx中有些代码逻辑看起来很奇葩,不知道背后是否有什么牛逼的设计哲学。 先记录下来吐槽一下。 1. 处理请求头connection时,会调用ngx_http_process_connection函数,该函数判断请求头的connection的val是否包含了close或keep-alive。判断逻辑:`ngx_strcasestrn(h->value.data, "close", 5 - 1)`,**比较费解的是5-1是个什么鬼?怎么理解,是比较clos这个4个字符么?** 当然不是比较clos了,是查找value中包含close这个子串的位置。 n在ngx_strcasestrn函数中压根没用,直接传递给ngx_strncasecmp函数了,而传递给该函数的s2子串是在ngx_strcasestrn中++后的,也就是说s2打印出来是lose,所以调用ngx_strcasestrn传递给n的是5-1。 吐槽:为什么不在ngx_strcasestrn内部对s2++后再对n--呢。。。 ngx_strstrn函数也有相同之处。 ```c u_char * ngx_strcasestrn(u_char *s1, char *s2, size_t n) { ngx_uint_t c1, c2; c2 = (ngx_uint_t)...
nginx stream 提供了四层代理。可以通过` proxy_download_rate`和`proxy_upload_rate`设置下载和上传限速。其实,七层在http核心模块`ngx_http_core_module`也提供一个参数`limit_rate`支持http resp的限速。七层和四层的限速是有区别的,但是限速的原理是一样的,都是通过`sleep`读写实现的。以后有机会仔细研究一下七层的限速。 四层限速的核心模块大概是涉及到两个函数,一个是`ngx_stream_proxy_process`,另一个是`ngx_stream_proxy_process_connection`。这个函数`ngx_stream_proxy_process `在四层代理算是个核心函数,从下游读取内容发送到上游,或者从上游读取内容发送到下游。 ```c // from_upstream: 1-从上游读取数据,0-从下游读取数据 // do_write: 1-发送数据到下游或发送数据到上游。0-不发送数据 static void ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream, ngx_uint_t do_write) { off_t *received, limit; size_t size, limit_rate; ssize_t...
今天碰到一个问题,程序运行时找不到动态库libxxx.so.0。而这个动态库是我们自己写的,所以: 1. rpm查看是否装了该rpm包。 2. 查看该包动态库装的路径是否在`/etc/ld.so.conf`文件中有配置,查看是否有`LD_LIBRARY_PATH`环境变量。 3. ldconfig 更新缓存。 4. 运行程序,还是有问题。 最后,看了下我们自己的动态库,装的是libxxx.so,而需要的是libxxx.so.0。如果打包动态库的时候没有指定soname(简单共享名,Short for shared object name)那就需要手动加个软连接。很显然是没有指定,因为如果指定了的话,`ldconfig -n .` 就会自动生成。 具体看下是否指定了呢? 可以用`readelf -d libxxx.so.1.0.1` 命令看下,如果有`SONAME`这一行,说明是指定了的。没有则没有指定。 ``` Dynamic section at offset 0x670 contains...
### 概述 http模块提供了map模块,用以把字符串映射成对应的值赋到指定变量。map的提供相当于提供了go语言`switch`-`case`部分能力。 例如,官方文档的例子,根据UA的不同把结果赋值到mobile变量,其他指令就可以使用mobile变量,例如access_log 指令if条件。 ```nginx map $http_user_agent $mobile { default 0; "~Opera Mini" 1; } ``` 对应的golang代码: ```golang var mobile int switch { case regexp.MatchString(".*Opera Mini.*", http_user_agent): mobile =...
## 概述 pcre是与perl一致的正则表达式,nginx就是用的该库。 系统:Mac OS X pcre版本:version 8.38 2015-11-23 安装路径: ```zsh $brew list pcre /usr/local/Cellar/pcre/8.38/bin/pcre-config /usr/local/Cellar/pcre/8.38/bin/pcregrep /usr/local/Cellar/pcre/8.38/bin/pcretest /usr/local/Cellar/pcre/8.38/include/ (6 files) /usr/local/Cellar/pcre/8.38/lib/libpcre.1.dylib /usr/local/Cellar/pcre/8.38/lib/libpcre16.0.dylib /usr/local/Cellar/pcre/8.38/lib/libpcre32.0.dylib /usr/local/Cellar/pcre/8.38/lib/libpcrecpp.0.dylib /usr/local/Cellar/pcre/8.38/lib/libpcreposix.0.dylib /usr/local/Cellar/pcre/8.38/lib/pkgconfig/ (5 files) /usr/local/Cellar/pcre/8.38/lib/ (10...