你根本就不懂Nginx

这两天学习了陶辉老师的《Nginx核心知识100讲》,受益匪浅,特此记录知识点。

  • 用 GoAccess 实现可视化并实时监控Nginx的 access 日志,WEBSOCKET推送功能特别好用。
  • envoy的许多特性已经在Nginx Plus商业版中了,按通常惯例,plus中的许多特性会在不久融入到开源版Nginx中。

  • epoll其实只是为了实现完全事件驱动的异步方式,即,nginx可以用单线程实现数万并发连接的高吞吐量处理。如果是由epoll仅处理连接的建立,而建立好的连接交由一个线程处理,这种模式不是全异步的事件驱动方式,性能上不去的。

  • haproxy的进程模型导致它热部署时会影响很多连接。

  • 安装Nginx若用yum安装但很难用yum升级,热升级依赖我们对nginx的高度可控,也就是最好自己编译安装。

  • Nginx升级时,make install是采用直接覆盖的方式安装的,而升级时,生产线上的所有文件,都不应该被直接覆盖,而是根据自己的需要,保持新老版本的文件都存在,因为新版本一旦有问题,就需要及时回滚到老版本,所以升级是一件很复杂的事,make install并不适合。

  • 如果在多个服务器上部署了多个nginx,可以用syslog协议将所有日志汇总在一起。不走磁盘。

  • 在生产环境中,应该把cp命令改为mv命令,因为linux文件系统中,改名并不会影响已经打开文件的写入操作,内核inode不变,这样就不会出现丢日志了。

  • 若使用nginx做tcp的代理,如何拿到客户端真实IP?可以使用proxy_protocol协议,或者使用IP透传DSR方案。

  • openresty有哪些直连redis或mysql的场景,比如一些接口流量很大,不想影响上游的应用开发服务器。

  • 在Nginx中,如果当worker碰到阻塞的操作(比如读磁盘文件)这样性能会急剧下降,如果是FreeBSD系统还好,提供了异步的文件系统接口,但是一般的Linux是同步的,这就需要另外开始线程池来实现worker非阻塞的处理events。
    详情请见:https://www.nginx.com/blog/thread-pools-boost-performance-9x/
    所以一般,尽量将所需放在RAM中,这样是不阻塞的,除非流媒体服务。

  • cache loader进程仅在cache打开时才会有,而且存在时间非常短,它是用于将之前nginx产生的cache信息元数据读入内存中的,读取完成后就会退出。

  • 关于多个子进程监听同一个端口引发的惊群效应,惊群是操作系统内核实现上引起的问题,最新的内核已经没有太大问题了,如果使用了reuseport那么就不需要考虑worker间负载均衡问题了。

  • 在事件分发器里,其实如何区分是读事件还是写事件呢?比如客户端请求建立TCP连接(其实是三次握手中的最后一次才被Nginx看作读事件)、客户端的读请求、客户端的写请求、连接的关闭(因为关闭连接是因为收到对方发来的FIN报文,所以对Nginx来讲是读事件)对于Nginx来讲其实都是读事件,因为是有从Client端的报文进来,如果是Nginx向client发送数据,就是写事件。

  • Nginx可以在windows下生产环境使用,只是相比linux在同等服务器配置下要差。同样可以调优的。

  • 每次处理事件时,先处理epoll即操作系统生成的事件,再处理Nginx自身生成的事件。在epoll中,当需要监控某个事件时,用户进程要把它加到红黑树中,二叉树是事件全集,包括不活跃事件。它相当于链表的字典,用于快速查询;当某个事件发生时,系统把它加入到链表中,这个链表里存放的就是活跃的事件,用在epoll_wait的系统调用中。

  • 如何理解不活跃连接?(1)有些TCP连接网速很慢,只有几B/S;(2)有些客户端很慢,它的CPU 100%了;(3)有些业务应用需要用户做输入后,才会在TCP连接上继续发送消息。这些TCP连接,在某个1秒内都没有任何事件,就叫不活跃链接,反之叫活跃链接。

  • Nginx只使用ET模式,即边缘触发模式

  • Nginx采用事件驱动的异步架构,所以必须使用nonbloking socket+epoll去处理网络IO,从这个角度上说是nio;nginx处理大文件时,可以开启linux原生的aio功能,避免大文件干扰高速磁盘缓存,从这个角度它使用了aio。其实,可以这么理解,普通的异步需要切换线程,会涉及内核态与用户态的来回转换,但是在Nginx是通过应用程序(epoll+无阻塞的事件驱动的方式来切换请求)实现了“线程切换”,只在用户态。

  • 操作系统为提升可靠性,将应用程序操作内存称为用户态,OS本身为内核态。

  • epoll wait是系统调用,所有的系统调用都需要做用户态与内核态间的切换,因为内核态的地址空间与用户态不同,这是为了内核的可靠性与安全性考虑设计的。

  • 同步和异步感觉更像针对的是代码的逻辑执行,即用户侧;而阻塞非阻塞感觉针对CPU来说的,如果没有数据的时候,进程是该被挂起让其他进程执行还是这个进程呆呆地等着。即阻塞与非阻塞是在低层次中展开的,通常针对的是API,同步与异步是在高层次中展开的,针对的更多的框架。

  • Nginx实现文件上传下载可通过dav模块,webdav协议是一个文档管理协议。

  • 如何开辟共享内存? (1)如果你开发Nginx模块,可以通过ngx_shared_memory_add开辟共享内存。(2)如果你使用配置文件,通常含有zone选项的指令,都会开辟共享内存。(3)如果你在用openresty,可以用shared_dict开辟新的共享内存。

  • 分析内存slab的使用情况,需要使用ngx_slab_stat这个模块, 需要去tengine上面找,然后重新编译。

  • nginx在存放MIME type、存放server_name、存放变量、作为反向代理时设置的hide_header等场景中用到了Hash表的数据结构。

  • PCRETest是个测试正则表达式的工具,NGINX中的正则用的也是PCRE标准,是的,configure中可以用–with-pcre=选项指定pcre版本。

  • Nginx Unit其实就是为了实现Service Mesh搞出来的,可参考https://www.zhihu.com/question/65126862

  • TCP没有长短连接的概念

  • Nginx接受事件的过程:
    http://q92rdi5go.bkt.clouddn.com/Fl797Rb3X75Jk8ETJ0m3czOOwnAW.png

  • Nginx中rewrite的一些实际生产使用场景:比如你的网站在做迁移,部分URL发生变动,或者为了增强SEO,对URL做变化等

  • screen,可以很方便的切换多个终端,你可以试试,用yum install screen安装。

  • 复制生产环境用户流量,视公司的业务而定。对于四层流量,Nginx的mirror模块无能为力。对于七层流量(如TLS卸载完成),mirror模块可以在较小影响生产环境下,按Nginx配置将流量分发到开发环境,开发成本是比较小的。

  • 提升多个小文件性能,可以用concat模块,若开启了http2,使用这个模块的意义就不大了。

  • 精确的分析IP地址信息,可以关注https://github.com/maxmind/libmaxminddb是否有更新

  • 判断Nginx中一个模块是否免费,最简单的方法,就是登陆到http://nginx.org/en/docs/站点,找到模块页面,如果注明“This module is available as part of our commercial subscription. ”,那么这是收费的,否则就是免费的。

  • 测试websocket的,可以用这个 http://www.websocket.org/echo.html

  • 文件都在硬盘上,内存中的只是文件索引

  • curl只能请求http1.1,所以想请求http2,可以使用nghttp2.yum install nghttp2.

  • stream模块可以处理tcp和udp协议,其他传输层就处理不了了。你需要判断下一个私有协议是不是tcp协议,方法很简单,用wireshark或者tcpdump抓个包,看一下ip头部中的protocol字段,如果是tcp或者udp就可以

  • 代理协议(Proxy protocol),是HAProxy的作者Willy Tarreau于2010年开发和设计的一个Internet协议,通过为tcp添加一个很小的头信息,来方便的传递客户端信息(协议栈、源IP、目的IP、源端口、目的端口等),在网络情况复杂又需要获取用户真实IP时非常有用。代理协议分为V1和V2两个版本,V1是人类易读的,V2是二进制格式的。

  • udp协议虽然不是面向连接(不用三次握手)的协议,但它有面向session的属性,发送消息里的source ip和source port,天然就是上游服务udp报文的dest ip和dest port。

  • 为什么通常设置为worker进程数量等于CPU核数呢,因为应该避免worker进程之间由于争抢造成的资源损耗。

  • Nice值越低,优先级越高如何理解?Nice值越低,越不友好,就一直占着CPU,优先级就越大。对于把请求切换,从内核转换到用户态实现的异步、协程等服务,都应该将worker_priority设到最低-20,即优先级最高。

  • 句柄数的设置可从三个层面来设置,最顶层是操作系统层面,然后是用户层面,最小层面的是进程层面。

  • 在信息论中,熵更大,才能传输更多的信息

  • tcp_cookies为什么可以防止syn flood?因为它允许SYN队列满后还可以建立成功TCP连接

  • 可以使用gperftools定位nginx性能问题

  • 可以使用stub_status模块监控Nginx

  • epoll不能用于磁盘IO。AIO就是用于磁盘IO的,在linux2.6.22内核后提供的eventfd,可以让AIO的事件通知加入到epoll中,使epoll可以获取AIO异步事件的完成通知。

  • sourceinsight这个IDE可以用来查看源代码,可以在windows上写代码,用winscp实时同步到linux。调试的话主要用gdb。

完美撒花~~~~

-------------本文结束感谢您的阅读-------------