初步认识 nginx

综合技术 2018-12-08 阅读原文

一、背景

最近几周简单的看了 Nginx 的源码,并做了一个分享。

这里简单记录一下。

二、WEB 服务器

在以前的时候,互联网上的数据量还较少,大家使用 Apache 就解决了全部性能问题。

Apache 处理请求的特点是一个请求连接对应一个进程。

当访问量上涨的时候,大家可以通过 增加进程、更换为高配机器、增加机器的数量来解决请求处理不过来的问题。

后来互联网爆炸式发展,各大网站的请求量都呈现指数级增长。

此时传统的砸机器、砸钱方式已经无法解决高访问量的问题了。

然后 Nginx 横空出世了。

目前主流的 WEB 服务器有 Apache、Tomcat、Nginx, 可以看到各家服务器的安装量情况。

由于 Apache 已经火爆那么多年了,所以目前安装量的比例还是比较高的。

不过可以根据各家服务器的历年来的比例趋势,看出 Nginx 是增长最快的。

到这里,大家可能会有疑问: Nginx 是因为什么这么厉害,性能这么高呢?

那是因为 Nginx 使用了一种高深的技术,叫做事件驱动。

这个技术的缺点是比较难,优点时性价比很高,可以处理很多请求。

另外,由于 Nginx 的模块设计比较好,大家也很容易做定制化的功能,所以被广为使用。

三、Nginx 的特征

既然 Nginx 这么厉害,有哪些显著的特征呢?

1.部署简单

Nginx 安装后,关键文件特别少。

主要有有一个可执行程序、一个配置文件、一个访问日志、一个错误日志。

其他的文件几乎都不需要关心。

2.操作简单

Nginx 有几个简单的命令。

如启动、停止、热加载、热重启。

通过这四个命令,就可以玩转 Nginx 的平常操作了。

3.设计简单

Nginx 采用了多进程共同监听端口,分别处理请求模式。

由于每个进程都是使用事件触发的模式处理请求的,分配的进程数只需要和CPU个数接近即可。

4.热加载

前面说操作的时候提到过热加载,这里单独再介绍下。

可以不客气的说,对于高并发服务,热加载与热启动的应用是一个巨大的进步。

之前的服务器,在升级过程中,往往需要停止服务。

在这期间部分请求会收到影响,而通过热启动,请求量几乎不受影响,可以平滑的切换到新的服务上。

而热加载的原理也很简单。

主进程使用新的配置生成新的进程,此时新旧进程同时干活。

然后主进程告诉旧进程,不要接受新的请求了,现有的处理完就退出吧。

于是旧进程按照这个指令去执行,就完整了热加载。

四、高深的事件驱动

我们知道在 Linux 上一切都是文件。

操作文件的时候,都是通过 FD 来操作的。

另外,对于文件的操作无非是读与写,所以 FD 就对应的有读事件和写事件。

在对 FD 操作的时候,往往存在等待。

就像我们两微信聊天,你给我发送消息后,我需要一段时间才会回复你一样。

这个期间你如果一直等待我的回复的话,就不能做其他事情了,你的时间就这样浪费了。

这种聊天方式叫做阻塞聊天。

比如我们监听一个端口的时候,更特殊,我们不知道谁会来,只能一直等待。

对于这种情况,我们一般会去做其他事情。

比如你先去和其他人聊天,过一会看看我有没有回复。

这样你就可以节约一下时间了。

你的这个聊天就是非阻塞聊天

对于监听端口一样,我们隔一会查一下是否有连接过来了。

对于微信,我们非阻塞聊天的时候,就可以同时和很多人一起聊天了。

那我们怎么快速判断是否要回复消息呢?

微信的小红点来帮助我们解决。

我们可以发现,微信帮我们监听了所有的群和好友的聊天事件。

当有新的聊天事件时,微信会在对应的角标上+1。

对于 FD 的事件,也一样。

我们把所有的时间加入到一个集合中,然后查询是否有新事件,有了,我们就处理对应的事件就可以了。

通过这种事件通知的方式,我们就可以快速知道有哪些事情要处理,从而可以做到高并发聊天了。

五、惊群

这个是多进程等待同一个资源时常会面临的问题。

多个进程都使用事件通知的方式来处理消息,假设只了一个消息,多个进程都收到通知。

除了第一个,其他的都会发现实际上没有需要处理的消息。

针对这个问题,解决方案也很简单:只通知一个进程。

怎样才能做到只通知一个进程呢?

如果操作系统支持(高版本),那使用高版本的操作系统。

如果操作系统不支持,那同一时间只允许一个进程来监听监听,就可以做到只监听一个进程了。

怎么才能做到只有一个进程监听呢?

使用锁来解决。

谁抢到锁,谁去监听。

六、Nginx 为啥如此优秀

1.没有对比就没有伤害

优秀是相对的。

既然说 Nginx 优秀,那肯定是和其他 WEB 服务器对比的。

和谁对比呢? 同步处理消息的 Apache 啦。

Apache 作为传统的 WEB 服务器,在互联网上的并发量较小时,存在了很多很多年。

那时候,Nginx 的孪生兄弟可能出现过,但是都死了。

为啥? Appche 就够了。

后来,互联网爆炸式增长了,Apache 遇到瓶颈了, 异步处理消息的 Nginx 就站出来了。

所以,Nginx 优秀只是和那些的同步方式处理消息的服务相比的。

近十几年新出现的服务器都是使用异步的方式处理消息的,他们在底层技术上相比,是势均力敌的。

如果有人说自己开发了 XX 功能,比 Nginx 性能还高,那说明那个人错误的使用了 Nginx。

比如他们同步的方式使用了 Nginx,然后遇到了并发量上不去的问题,最后又回到了传统的开一堆线程来提高并发量。

2.没有冗余就没有浪费

软件工程中,大家是鼓励功能复用的。

为了功能能够复用、通用,就会做很多冗余的事情。

而 Nginx 为了提高性能,所有的功能都自己来实现了。

比如 SLAB 内存管理,array、list、hash、红黑树、regex等等。

自己实现的时候,仅仅实现自己需要的功能。

这样做出来的功能没有那么通用,但是没有冗余,自己使用时性能会更高。

3.良好的模块设计

一个系统仅仅是高性能是不够的,你还需要好用。

而 Nginx 的模块设计的比较好,很容易增加各种第三方插件。

这样才使得 Nginx 能够广泛推广使用。

前提提到,很多人宣称自己基于 Nginx 做了一个比 Nginx 性能还高的服务,具体是什么回事呢? 那是因为他们使用了某些以同步模式开发的第三方插件。

服务一旦同步处理,比增加进程或线程的话,并发量肯定就上不去了。

4.适合业务的架构

Nginx 既然如此优秀,为啥我们所有的业务不都使用 Nginx 实现呢?

这是因为 Nginx 只是一个优秀的代理服务(做简单的事情),而不是一个优秀的网络框架。

换句话说就是 Nginx 服务设计都存在局限性,只是在某些场景下非常出色,而在其他场景下就比较鸡肋了。

其实所有的服务都是这样的,都存在自身的局限性。

比如 Redis 很多人都听过,也是使用事件触发实现的单进程单线程的服务。

性能是很高,但是只有一个进程,只能用一个CPU,一个人的力量再大也有上限的。

我们为了使得 Redis 用上多核 CPU,往往是部署多个 Redis 实例,这样就存在了很高的管理成本。

而且多个 Redis 实例,还需要有一层路由 HASH 层,这一层的成本也要考虑进来。

所以对于任何系统,不管如何高性能,都存在其局限性,都有对应的使用场景。

超过了使用场景,可能就不是高性能了,或者良好的模块设计就不那么良好了。

Nginx 是如此, Redis 依旧如此。

七、最后

虽说 Nginx 有其自身的局限性,但是其使用场景也很广泛,还是值得去研究一下 Nginx 的源码实现的。

后面我也会分几次来分享 Nginx 设计到的东西。

本文首发于公众号:天空的代码世界,微信号:tiankonguse-code。

tiankonguse blog

责编内容by:tiankonguse blog阅读原文】。感谢您的支持!

您可能感兴趣的

Linux Nginx 配置 SSL 证书 切到 Nginx 目录下 cd /etc/nginx 新建 cert 文件夹 mkdir cert 上传从颁发证书网站下载下来的 Nginx 专用的 *.crt 和 *.key 文件 # 切到本地证书...
基于Docker实现服务治理(三) 前言 我们已实现了服务的注册与发现。不过目前还存在的问题是: 负载均衡的业务逻辑跟应用层混在一起; 采用客服端实现的方式实现,如果采用java实现,那么还需要开发一套客户端的逻辑,与具体的语言耦合在...
正确地配置一个安全的 https 网站 (nginx/Apache/Lighttpd)... 如果你想配置一个安全的 https 网站的话,你就可以需要下面这个了。 请根据您所使用的网站服务器程序,选择对应的配置文件,然后根据自己的需要修改自己现行的网站配置即可! 如果您使用下面的配置,您可以需要自己配置证书 CRT ...
WEB请求处理二:Nginx请求反向代理 上一篇 《WEB请求处理一:浏览器请求发起处理》 ,我们讲述了浏览器端请求发起过程,通过DNS域名解析服务器IP,并建立TCP连接,发送HTTP请求。本文将讲述请求到达反向代理服务器的一个处理过程,比如:在Nginx中请求的反向代理处理流...
Nginx监控数据采集与分析 简介 nginx和很多软件一样(php-fpm、docker、apache等)内建了一个状态页,对于nginx的状态查看以及监控提供了很大帮助。本文主要介绍通过日志服务logtail采集nginx status信息,并对采集的st...