一、HTTP 介绍
HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。
HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。
1、HTTP 工作原理
HTTP协议工作于客户端-服务端架构上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。
Web服务器有:Nginx,Apache服务器,IIS服务器(Internet Information Services)等。
Web服务器根据接收到的请求后,向客户端发送响应信息。
HTTP默认端口号为80,但是你也可以改为8080或者其他端口。
HTTP三点注意事项:
-
HTTP是无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
-
HTTP是媒体独立的:这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型。
-
HTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。·
以下图表展示了HTTP协议通信流程:
2、HTTP 消息结构
HTTP是基于客户端/服务端(C/S)的架构模型,通过一个可靠的链接来交换信息,是一个无状态的请求/响应协议。
一个HTTP"客户端"是一个应用程序(Web浏览器或其他任何客户端),通过连接到服务器达到向服务器发送一个或多个HTTP的请求的目的。
一个HTTP"服务器"同样也是一个应用程序(通常是一个Web服务,如Apache Web服务器或IIS服务器等),通过接收客户端的请求并向客户端发送HTTP响应数据。
HTTP使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。
一旦建立连接后,数据消息就通过类似Internet邮件所使用的格式[RFC5322]和多用途Internet邮件扩展(MIME)[RFC2045]来传送。
3、客户端请求消息
客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行(request line)、请求头部(header)、空行和请求数据四个部分组成,下图给出了请求报文的一般格式。
4、服务器响应消息
HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。
实例
下面实例是典型的使用GET来传递数据的实例:
客户端请求:
Connected to www.testpm.cn (47.244.247.240) port 80 (#0) > GET /hello.txt HTTP/1.1 # 请求方式与版本协议。 > User-Agent: curl/7.29.0 #用什么客户端访问 > Host: www.testpm.cn #主机名,域名。主机和端口号, > Accept: */* #匹配什么文件类型,“*” 是通用匹配。匹配所有类型
服务端响应:
< HTTP/1.1 200 OK #请求返回的状态码 < Server: nginx/1.16.0 #请求的服务和版本号 < Date: Thu, 04 Jul 2019 08:19:40 GMT < Content-Type: text/plain #文本类型,有html,plain:普通文本 < Content-Length: 12 < Last-Modified: Thu, 04 Jul 2019 08:13:25 GMT < Connection: keep-alive #是否支持长连接 < ETag: "5d1db525-c" #标识,每次访问如果与最开始的一样返回304否则校验不一致返回200 < Accept-Ranges: bytes
输出结果:
hello world
5、HTTP 请求方法
根据HTTP标准,HTTP请求可以使用多种请求方法。
HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法。
HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。
重点方法:
GET:单纯获取数据(获取一个index.html页面)
POST:上传/创建文件(会产生新的数据)
PUT:保存数据(覆盖/更新文件、图片等,不会产生新的数据)
DELETE:删除
6、HTTP 响应头信息
HTTP请求头提供了关于请求,响应或者其他的发送实体的信息。
在本章节中我们将具体来介绍HTTP响应头信息。
应答头 | 说明 |
---|---|
Allow | 服务器支持哪些请求方法(如GET、POST等)。 |
Content-Encoding | 文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档的下载时间。Java的GZIPOutputStream可以很方便地进行gzip压缩,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。因此,Servlet应该通过查看Accept-Encoding头(即request.getHeader("Accept-Encoding"))检查浏览器是否支持gzip,为支持gzip的浏览器返回经gzip压缩的HTML页面,为其他浏览器返回普通页面。 |
Content-Length | 表示内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。如果你想要利用持久连接的优势,可以把输出文档写入 ByteArrayOutputStream,完成后查看其大小,然后把该值放入Content-Length头,最后通过byteArrayStream.writeTo(response.getOutputStream()发送内容。 |
Content-Type | 表示后面的文档属于什么MIME类型。Servlet默认为text/plain,但通常需要显式地指定为text/html。由于经常要设置Content-Type,因此HttpServletResponse提供了一个专用的方法setContentType。 |
Date | 当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。 |
Expires | 应该在什么时候认为文档已经过期,从而不再缓存它? |
Last-Modified | 文档的最后改动时间。客户可以通过If-Modified-Since请求头提供一个日期,该请求将被视为一个条件GET,只有改动时间迟于指定时间的文档才会返回,否则返回一个304(Not Modified)状态。Last-Modified也可用setDateHeader方法来设置。 |
Location | 表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302。 |
Refresh | 表示浏览器应该在多少时间之后刷新文档,以秒计。除了刷新当前文档之外,你还可以通过setHeader("Refresh", "5; URL=http://host/path")让浏览器读取指定的页面。 注意这种功能通常是通过设置HTML页面HEAD区的<META HTTP-EQUIV="Refresh" CONTENT="5;URL=http://host/path">实现,这是因为,自动刷新或重定向对于那些不能使用CGI或Servlet的HTML编写者十分重要。但是,对于Servlet来说,直接设置Refresh头更加方便。 注意Refresh的意义是"N秒之后刷新本页面或访问指定页面",而不是"每隔N秒刷新本页面或访问指定页面"。因此,连续刷新要求每次都发送一个Refresh头,而发送204状态代码则可以阻止浏览器继续刷新,不管是使用Refresh头还是<META HTTP-EQUIV="Refresh" ...>。 注意Refresh头不属于HTTP 1.1正式规范的一部分,而是一个扩展,但Netscape和IE都支持它。 |
Server | 服务器名字。Servlet一般不设置这个值,而是由Web服务器自己设置。 |
Set-Cookie | 设置和页面关联的Cookie。Servlet不应使用response.setHeader("Set-Cookie", ...),而是应使用HttpServletResponse提供的专用方法addCookie。参见下文有关Cookie设置的讨论。 |
WWW-Authenticate | 客户应该在Authorization头中提供什么类型的授权信息?在包含401(Unauthorized)状态行的应答中这个头是必需的。例如,response.setHeader("WWW-Authenticate", "BASIC realm=\"executives\"")。 注意Servlet一般不进行这方面的处理,而是让Web服务器的专门机制来控制受密码保护页面的访问(例如.htaccess)。 |
7、HTTP 状态码
当浏览者访问一个网页时,浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含HTTP状态码的信息头(server header)用以响应浏览器的请求。
HTTP状态码的英文为HTTP Status Code。
下面是常见的HTTP状态码:
-
200 - 请求成功
-
301 - 资源(网页等)被永久转移到其它URL
-
302 - 资源(网页等)被临时转移到其它URL
-
403 - 服务器理解请求客户端的请求,但是拒绝执行此请求
-
404 - 请求的资源(网页等)不存在
-
500 - 内部服务器错误
HTTP状态码分类
HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码共分为5种类型:
HTTP状态码列表:
状态码 | 状态码英文名称 | 中文描述 |
---|---|---|
100 | Continue | 继续。客户端应继续其请求 |
101 | Switching Protocols | 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议 |
200 | OK | 请求成功。一般用于GET与POST请求 |
201 | Created | 已创建。成功请求并创建了新的资源 |
202 | Accepted | 已接受。已经接受请求,但未处理完成 |
203 | Non-Authoritative Information | 非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本 |
204 | No Content | 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档 |
205 | Reset Content | 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域 |
206 | Partial Content | 部分内容。服务器成功处理了部分GET请求 |
300 | Multiple Choices | 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择 |
301 | Moved Permanently | 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替 |
302 | Found | 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI |
303 | See Other | 查看其它地址。与301类似。使用GET和POST请求查看 |
304 | Not Modified | 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源 |
305 | Use Proxy | 使用代理。所请求的资源必须通过代理访问 |
306 | Unused | 已经被废弃的HTTP状态码 |
307 | Temporary Redirect | 临时重定向。与302类似。使用GET请求重定向 |
400 | Bad Request | 客户端请求的语法错误,服务器无法理解 |
401 | Unauthorized | 请求要求用户的身份认证 |
402 | Payment Required | 保留,将来使用 |
403 | Forbidden | 服务器理解请求客户端的请求,但是拒绝执行此请求 |
404 | Not Found | 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面 |
405 | Method Not Allowed | 客户端请求中的方法被禁止 |
406 | Not Acceptable | 服务器无法根据客户端请求的内容特性完成请求 |
407 | Proxy Authentication Required | 请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权 |
408 | Request Time-out | 服务器等待客户端发送的请求时间过长,超时 |
409 | Conflict | 服务器完成客户端的PUT请求是可能返回此代码,服务器处理请求时发生了冲突 |
410 | Gone | 客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置 |
411 | Length Required | 服务器无法处理客户端发送的不带Content-Length的请求信息 |
412 | Precondition Failed | 客户端请求信息的先决条件错误 |
413 | Request Entity Too Large | 由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息 |
414 | Request-URI Too Large | 请求的URI过长(URI通常为网址),服务器无法处理 |
415 | Unsupported Media Type | 服务器无法处理请求附带的媒体格式 |
416 | Requested range not satisfiable | 客户端请求的范围无效 |
417 | Expectation Failed | 服务器无法满足Expect的请求头信息 |
500 | Internal Server Error | 服务器内部错误,无法完成请求 |
501 | Not Implemented | 服务器不支持请求的功能,无法完成请求 |
502 | Bad Gateway | 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应 |
503 | Service Unavailable | 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中 |
504 | Gateway Time-out | 充当网关或代理的服务器,未及时从远端服务器获取请求 |
505 | HTTP Version not supported | 服务器不支持请求的HTTP协议的版本,无法完成处理 |
二、nginx 服务
1、nginx 介绍
Nginx (engine x) 是一个高性能的 HTTP 和 反向代理 服务,也是一个IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。2011年6月1日,nginx 1.0.4发布。
Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。
在高连接并发的情况下,Nginx是Apache服务器不错的替代品。
创始人伊戈尔·赛索耶夫
2、为什么选择 nginx
Nginx 是一个高性能的 Web 和反向代理服务器, 它具有有很多非常优越的特性:
单机环境下参考服务器配置。 并发连接数在7000+ -8000左右。 集群模式20000+
作为 Web 服务器:相比 Apache,Nginx 使用更少的资源,支持更多的并发连接,体现更高的效率,这点使 Nginx 尤其受到虚拟主机提供商的欢迎。能够支持高达 50,000 个并发连接数的响应,感谢 Nginx 为我们选择了 epoll and kqueue 作为开发模型.
作为负载均衡服务器:Nginx 既可以在内部直接支持 Rails 和 PHP,也可以支持作为 HTTP代理服务器 对外进行服务。Nginx 用 C 编写, 不论是系统资源开销还是 CPU 使用效率都比 Perlbal 要好的多。
作为邮件代理服务器: Nginx 同时也是一个非常优秀的邮件代理服务器(最早开发这个产品的目的之一也是作为邮件代理服务器),Last.fm 描述了成功并且美妙的使用经验。
Nginx 安装非常的简单,配置文件 非常简洁(还能够支持perl语法),Bugs非常少的服务器: Nginx 启动特别容易,并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还能够在 不间断服务的情况下进行软件版本的升级。
3、IO多路复用
1、I/O multiplexing【多并发】
第一种方法就是最传统的多进程并发模型 (每进来一个新的I/O流会分配一个新的进程管理。)
第二种方法就是I/O多路复用 (单个线程,通过记录跟踪每个I/O流(sock)的状态,来同时管理多个I/O流 。)
I/O multiplexing 这里面的 multiplexing 指的其实是在单个线程通过记录跟踪每一个Sock(I/O流)的状态来同时管理多个I/O流。发明它的原因,是尽量多的提高服务器的吞吐能力。
在同一个线程里面, 通过拨开关的方式,来同时传输多个I/O流
2、一个请求到来了,nginx使用epoll接收请求的过程是怎样的?
ngnix会有很多连接进来, epoll会把他们都监视起来,然后像拨开关一样,谁有数据就拨向谁,然后调用相
应的代码处理。
-
select, poll, epoll 都是I/O多路复用的具体的实现,其实是他们出现是有先后顺序的。
I/O多路复用这个概念被提出来以后, 相继出现了多个方案
-
select是第一个实现 (1983 左右在BSD里面实现的)。
select 被实现以后,很快就暴露出了很多问题。
• select 会修改传入的参数数组,这个对于一个需要调用很多次的函数,是非常不友好的。
• select 如果任何一个sock(I/O stream)出现了数据,select 仅仅会返回,但是并不会告诉你是那个sock上有数据,于是你只能自己一个一个的找,10几个sock可能还好,要是几万的sock每次都找一遍...
• select 只能监视1024个链接。
• select 不是线程安全的,如果你把一个sock加入到select, 然后突然另外一个线程发现,这个sock不用,要收
回,这个select 不支持的,如果你丧心病狂的竟然关掉这个sock, select的标准行为是不可预测的
-
于是14年以后(1997年)一帮人又实现了poll, poll 修复了select的很多问题,比如
• poll 去掉了1024个链接的限制,于是要多少链接呢, 主人你开心就好。
• poll 从设计上来说,不再修改传入数组,不过这个要看你的平台了,所以行走江湖,还是小心为妙。
其实拖14年那么久也不是效率问题, 而是那个时代的硬件实在太弱,一台服务器处理1千多个链接简直就是神一样的存在了,select很长段时间已经满足需求。
但是poll仍然不是线程安全的, 这就意味着,不管服务器有多强悍,你也只能在一个线程里面处理一组I/O流。
你当然可以那多进程来配合了,不过然后你就有了多进程的各种问题。
-
于是5年以后, 在2002, 大神 Davide Libenzi 实现了epoll.
epoll 可以说是I/O 多路复用最新的一个实现,epoll 修复了poll 和select绝大部分问题, 比如:
• epoll 现在是线程安全的。
• epoll 现在不仅告诉你sock组里面数据,还会告诉你具体哪个sock有数据,你不用自己去找了。
3、异步,非阻塞
$ pstree |grep nginx |-+= 81666 root nginx: master process nginx | |--- 82500 nobody nginx: worker process | \--- 82501 nobody nginx: worker process
1个master进程,2个work进程
每进来一个request,会有一个worker进程去处理。但不是全程的处理,处理到什么程度呢?处理到可能发生阻塞的地方,比如向上游(后端)服务器转发request,并等待请求返回。那么,这个处理的worker不会这么一直等着,他会在发送完请求后,注册一个事件:“如果upstream返回了,告诉我一声,我再接着干”。于是他就休息去了。这就是异步。此时,如果再有request 进来,他就可以很快再按这种方式处理。这就是非阻塞和IO多路复用。而一旦上游服务器返回了,就会触发这个事件,worker才会来接手,这个request才会接着往下走。这就是异步回调。
4、nginx 的内部技术架构
Nginx服务器,以其处理网络请求的高并发、高性能及高效率,获得了行业界的广泛认可,近年已稳居web服务器部署排名第二的位置,并被广泛用于反向代理和负载均衡。
Nginx是如何实现这些目标的呢?答案就是其独特的内部技术架构设计。看懂下面这张图,就明白了Nginx的内部技术架构。
简要说明几点:
1)nginx启动时,会生成两种类型的进程,一个是主进程(Master),一个(windows版本的目前只有一个)或多个工作进程(Worker)。主进程并不处理网络请求,主要负责调度工作进程,也就是图示的三项:加载配置、启动工作进程及非停升级。所以,nginx启动以后,查看操作系统的进程列表,我们就能看到至少有两个nginx进程。
2)服务器实际处理网络请求及响应的是工作进程(worker),在类unix系统上,nginx可以配置多个worker,而每个worker进程都可以同时处理数以千计的网络请求。
3)模块化设计。nginx的worker,包括核心和功能性模块,核心模块负责维持一个运行循环(run-loop),执行网络请求处理的不同阶段的模块功能,如网络读写、存储读写、内容传输、外出过滤,以及将请求发往上游服务器等。而其代码的模块化设计,也使得我们可以根据需要对功能模块进行适当的选择和修改,编译成具有特定功能的服务器。
4)事件驱动、异步及非阻塞,可以说是nginx得以获得高并发、高性能的关键因素,同时也得益于对Linux、Solaris及类BSD等操作系统内核中事件通知及I/O性能增强功能的采用,如kqueue、epoll及event ports。
5)代理(proxy)设计,可以说是nginx深入骨髓的设计,无论是对于HTTP,还是对于FastCGI、memcache、Redis等的网络请求或响应,本质上都采用了代理机制。所以,nginx天生就是高性能的代理服务器
5、nginx安装部署和配置管理
1、nginx部署-Yum安装
访问nginx的官方网站:nginx news
Nginx版本类型
Mainline version: 主线版,即开发版
Stable version: 最新稳定版,生产环境上建议使用的版本
Legacy versions: 遗留的老版本的稳定版
Yum安装nginx
配置Yum源的官网:nginx: Linux packages
1、配置nginx的Yum源
Installation instructions
Before you install nginx for the first time on a new machine, you need to set up the nginx packages repository. Afterward, you can install and update nginx from the repository.
安装说明
在新计算机上首次安装nginx之前,需要设置nginx软件包存储库。 之后,您可以从存储库安装和更新nginx。
RHEL/CENTOS
Install the prerequisites:
sudo yum install yum-utils -y
To set up the yum repository, create the file named /etc/yum.repos.d/nginx.repo
with the following contents:
[nginx-stable] name=nginx stable repo baseurl=http://nginx.org/packages/centos/$releasever/$basearch/ gpgcheck=1 enabled=1 gpgkey=https://nginx.org/keys/nginx_signing.key [nginx-mainline] name=nginx mainline repo baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/ gpgcheck=1 enabled=0 gpgkey=https://nginx.org/keys/nginx_signing.key
By default, the repository for stable nginx packages is used. If you would like to use mainline nginx packages, run the following command:
sudo yum-config-manager --enable nginx-mainline
To install nginx, run the following command:
sudo yum install nginx -y
When prompted to accept the GPG key, verify that the fingerprint matches 573B FD6B 3D8F BC64 1079 A6AB ABF5 BD82 7BD9 BF62
, and if so, accept it.
当提示您接受GPG密钥时,请验证指纹是否匹配573B FD6B 3D8F BC64 1079 A6AB ABF5 BD82 7BD9 BF62
,如果匹配 ,请接受它。
这里我们用稳定版本
[root@nginx-server yum.repos.d]# yum install -y nginx [root@nginx-server yum.repos.d]# nginx -V //格式化打印 nginx version: nginx/1.16.0 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC) built with OpenSSL 1.0.2k-fips 26 Jan 2017 TLS SNI support enabled configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie' [root@nginx-server yum.repos.d]# nginx -v nginx version: nginx/1.16.0
关闭防火墙和selinux:
[root@nginx-server ~]# getenforce Enforcing [root@nginx-server ~]# sed -i '/SELINUX/s/enforcing/disabled/' /etc/selinux/config [root@nginx-server ~]# systemctl stop firewalld [root@nginx-server ~]# systemctl disable firewalld
启动并设置开机启动
[root@nginx-server ~]# systemctl start nginx [root@nginx-server ~]# systemctl enable nginx
浏览器输入ip访问:
6、nginx 编译安装与配置使用
1、安装编译环境
yum -y install gcc gcc-c++
2、安装pcre软件包(使nginx支持http rewrite模块)
yum install -y pcre pcre-devel
3、安装openssl-devel(使nginx支持ssl)
yum install -y openssl openssl-devel
4、安装zlib
yum install -y zlib zlib-devel
5、创建用户nginx
useradd nginx
passwd nginx
6、安装nginx
[root@localhost ~]# wget http://nginx.org/download/nginx-1.16.0.tar.gz [root@localhost ~]# tar xzf nginx-1.16.0.tar.gz -C /usr/local/ [root@localhost ~]# cd nginx-1.16.0 [root@localhost nginx-1.16.0]# ./configure --prefix=/usr/local/nginx --group=nginx --user=nginx --sbin-path=/usr/local/nginx/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/tmp/nginx/client_body --http-proxy-temp-path=/tmp/nginx/proxy --http-fastcgi-temp-path=/tmp/nginx/fastcgi --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_gzip_static_module --with-pcre --with-http_realip_module --with-stream [root@localhost nginx-1.16.0]# make && make install [root@localhost nginx-1.16.0]# mkdir /tmp/nginx
7、Nginx 编译参数
# 查看 nginx 安装的模块 [root@localhost ~]#/usr/local/nginx/sbin/nginx -V # 模块参数具体功能 --with-cc-opt='-g -O2 -fPIE -fstack-protector //设置额外的参数将被添加到CFLAGS变量。(FreeBSD或者ubuntu使用) --param=ssp-buffer-size=4 -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now' --prefix=/usr/local/nginx //指向安装目录 --conf-path=/etc/nginx/nginx.conf //指定配置文件 --http-log-path=/var/log/nginx/access.log //指定访问日志 --error-log-path=/var/log/nginx/error.log //指定错误日志 --lock-path=/var/lock/nginx.lock //指定lock文件 --pid-path=/run/nginx.pid //指定pid文件 --http-client-body-temp-path=/var/lib/nginx/body //设定http客户端请求临时文件路径 --http-fastcgi-temp-path=/var/lib/nginx/fastcgi //设定http fastcgi临时文件路径 --http-proxy-temp-path=/var/lib/nginx/proxy //设定http代理临时文件路径 --http-scgi-temp-path=/var/lib/nginx/scgi //设定http scgi临时文件路径 --http-uwsgi-temp-path=/var/lib/nginx/uwsgi //设定http uwsgi临时文件路径 --with-debug //启用debug日志 --with-pcre-jit //编译PCRE包含“just-in-time compilation” --with-ipv6 //启用ipv6支持 --with-http_ssl_module //启用ssl支持 --with-http_stub_status_module //获取nginx自上次启动以来的状态 --with-http_realip_module //允许从请求标头更改客户端的IP地址值,默认为关 --with-http_auth_request_module //实现基于一个子请求的结果的客户端授权。如果该子请求返回的2xx响应代码,所述接入是允许的。如果它返回401或403中,访问被拒绝与相应的错误代码。由子请求返回的任何其他响应代码被认为是一个错误。 --with-http_addition_module //作为一个输出过滤器,支持不完全缓冲,分部分响应请求 --with-http_dav_module //增加PUT,DELETE,MKCOL:创建集合,COPY和MOVE方法 默认关闭,需编译开启 --with-http_geoip_module //使用预编译的MaxMind数据库解析客户端IP地址,得到变量值 --with-http_gunzip_module //它为不支持“gzip”编码方法的客户端解压具有“Content-Encoding: gzip”头的响应。 --with-http_gzip_static_module //在线实时压缩输出数据流 --with-http_image_filter_module //传输JPEG/GIF/PNG 图片的一个过滤器)(默认为不启用。gd库要用到) --with-http_spdy_module //SPDY可以缩短网页的加载时间 --with-http_sub_module //允许用一些其他文本替换nginx响应中的一些文本 --with-http_xslt_module //过滤转换XML请求 --with-mail //启用POP3/IMAP4/SMTP代理模块支持 --with-mail_ssl_module //启用ngx_mail_ssl_module支持启用外部模块支持
8、修改配置文件/etc/nginx/nginx.conf
# 全局参数设置 worker_processes 4; #设置nginx启动进程的数量,一般设置成与逻辑cpu数量相同 error_log logs/error.log; #指定错误日志 worker_rlimit_nofile 102400; #设置一个nginx进程能打开的最大文件数 pid /var/run/nginx.pid; events { worker_connections 1024; #设置一个进程的最大并发连接数 } # http 服务相关设置 http { include mime.types; default_type application/octet-stream; log_format main 'remote_addr - remote_user [time_local] "request" ' 'status body_bytes_sent "$http_referer" ' '"http_user_agent" "http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; #设置访问日志的位置和格式 sendfile on; #是否调用sendfile函数输出文件,一般设置为on,若nginx是用来进行磁盘IO负载应用时,可以设置为off,降低系统负载 gzip on; #是否开启gzip压缩,将注释去掉开启 keepalive_timeout 65; #设置长连接的超时时间 # 虚拟服务器的相关设置 server { listen 80; #设置监听的端口 server_name localhost; #设置绑定的主机名、域名或ip地址 charset koi8-r; # 设置编码字符 location / { root /var/www/nginx; #设置服务器默认网站的根目录位置,需要手动创建 index index.html index.htm; #设置默认打开的文档 } error_page 500 502 503 504 /50x.html; #设置错误信息返回页面 location = /50x.html { root html; #这里的绝对位置是/usr/local/nginx/html } } }
nginx.conf的组成:nginx.conf一共由三部分组成,分别为:全局块、events块、http块。在http块中又包含http全局块、多个server块。每个server块中又包含server全局块以及多个location块。在统一配置块中嵌套的配置快,各个之间不存在次序关系。
9、检测nginx配置文件是否正确
[root@localhost ~]# /usr/local/nginx/sbin/nginx -t [root@localhost ~]# mkdir -p /tmp/nginx
10、启动nginx服务
[root@localhost ~]# /usr/local/nginx/sbin/nginx
11、通过 nginx 命令控制 nginx 服务
nginx -c /path/nginx.conf # 以特定目录下的配置文件启动nginx: nginx -s reload # 修改配置后重新加载生效 nginx -s reopen # 重新打开日志文件 nginx -s stop # 快速停止nginx nginx -s quit # 完整有序的停止nginx nginx -t # 测试当前配置文件是否正确 nginx -t -c /path/to/nginx.conf # 测试特定的nginx配置文件是否正确 注意: nginx -s reload 命令加载修改后的配置文件,命令下达后发生如下事件 1. Nginx的master进程检查配置文件的正确性,若是错误则返回错误信息,nginx继续采用原配置文件进行工作(因为worker未受到影响) 2. Nginx启动新的worker进程,采用新的配置文件 3. Nginx将新的请求分配新的worker进程 4. Nginx等待以前的worker进程的全部请求已经都返回后,关闭相关worker进程 5. 重复上面过程,直到全部旧的worker进程都被关闭掉
12、实现nginx开机自启
[root@localhost ~]# vim /etc/init.d/nginx #!/bin/sh # # nginx - this script starts and stops the nginx daemon # # chkconfig: - 85 15 # description: Nginx is an HTTP(S) server, HTTP(S) reverse \ # proxy and IMAP/POP3 proxy server # processname: nginx # config: /etc/nginx/nginx.conf # config: /etc/sysconfig/nginx # pidfile: /var/run/nginx.pid # Source function library. . /etc/rc.d/init.d/functions # Source networking configuration. . /etc/sysconfig/network # Check that networking is up. [ "$NETWORKING" = "no" ] && exit 0 nginx="/usr/local/nginx/sbin/nginx" prog=$(basename $nginx) NGINX_CONF_FILE="/etc/nginx/nginx.conf" [ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx lockfile=/var/lock/nginx make_dirs() { # make required directories user=`nginx -V 2>&1 | grep "configure arguments:" | sed 's/[^*]*--user=\([^ ]*\).*/\1/g' -` options=`$nginx -V 2>&1 | grep 'configure arguments:'` for opt in $options; do if [ `echo $opt | grep '.*-temp-path'` ]; then value=`echo $opt | cut -d "=" -f 2` if [ ! -d "$value" ]; then # echo "creating" $value mkdir -p $value && chown -R $user $value fi fi done } start() { [ -x $nginx ] || exit 5 [ -f $NGINX_CONF_FILE ] || exit 6 make_dirs echo -n $"Starting $prog: " daemon $nginx -c $NGINX_CONF_FILE retval=$? echo [ $retval -eq 0 ] && touch $lockfile return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog -QUIT retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { configtest || return $? stop sleep 1 start } reload() { configtest || return $? echo -n $"Reloading $prog: " killproc $nginx -HUP RETVAL=$? echo } force_reload() { restart } configtest() { $nginx -t -c $NGINX_CONF_FILE } rh_status() { status $prog } rh_status_q() { rh_status >/dev/null 2>&1 } case "$1" in start) rh_status_q && exit 0 $1 ;; stop) rh_status_q || exit 0 $1 ;; restart|configtest) $1 ;; reload) rh_status_q || exit 7 $1 ;; force-reload) force_reload ;; status) rh_status ;; condrestart|try-restart) rh_status_q || exit 0 ;; *) echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}" exit 2 esac
b、添加权限
chmod +x /etc/init.d/nginx
c、重新加载系统启动文件
systemctl daemon-reload
d、启动并设置开机自启
systemctl start nginx [root@localhost ~]# /sbin/chkconfig nginx on ---开机启动
10、nginx 日志文件详解
nginx 日志文件分为 **log_format** 和 **access_log** 两部分 log_format 定义记录的格式,其语法格式为 log_format 样式名称 样式详情 配置文件中默认有
log_format main 'remote_addr - remote_user [time_local] "request" ' 'status body_bytes_sent "$http_referer" ' '"http_user_agent" "http_x_forwarded_for"';
7、nginx 高级应用
1.使用alias实现虚拟目录;
location /test { alias /var/www/qianfeng/; index index.html; } location /test { root /var/www/qianfeng/; index index.html; }
2、通过 stub_status 模块监控 nginx 的工作状态
1)、通过 nginx -V 命令查看是否已安装 stub_status 模块
2)、编辑 /etc/nginx/nginx.conf 配置文件
#添加以下内容~~ location /nginx-status { stub_status on; access_log /var/log/nginx/nginxstatus.log; #设置日志文件的位置 auth_basic "nginx-status"; #指定认证机制(与location后面的内容相同即可) auth_basic_user_file /etc/nginx/htpasswd; #指定认证的密码文件 }
3).创建认证口令文件并添加用户qianfeng和zdgg,密码用md5加密
[root@localhost ~]# yum install -y httpd-tools #htpasswd 是开源 http 服务器 apache httpd 的一个命令工具,用于生成 http 基本认证的密码文件 htpasswd -c -m /etc/nginx/htpasswd qianfeng # -c 创建解密文件,-m MD5加密 htpasswd -m /etc/nginx/htpasswd zsgg
4)、重启服务
5)、客户端访问 http://ip/nginx-status 即可
Active connections: 2 server accepts handled requests 27 27 40 Reading: 0 Writing: 1 Waiting: 1 Active connections – 活跃的连接数量 server accepts handled requests — 总共处理了27个连接 , 成功创建27次握手, 总共处理了40个请求。 reading — 读取客户端的连接数。 writing — 响应数据到客户端的数量。 waiting — 开启 keep-alive 的情况下,这个值等于 active – (reading+writing), 意思就是 Nginx 已经处理完正在等候下一次请求指令的驻留连接。
3、使用 limit_rate 限制客户端传输数据的速度
1、编辑/etc/nginx/nginx.conf
location / { root /var/www/nginx/; index index.html index.htm; limit_rate 2k; #对每个连接的限速为2k/s }
重启服务
注意要点:
-
配置文件中的每个语句要以 ; 结尾
-
使用 htpasswd 命令需要先安装 httpd-tools
8、nginx 虚拟主机配置
什么是虚拟主机? 虚拟主机是一种特殊的软硬件技术,它可以将网络上的每一台计算机分成多个虚拟主机,每个虚拟主机可以独立对外提供www服务,这样就可以实现一台主机对外提供多个web服务,每个虚拟主机之间是独立的,互不影响。
nginx可以实现虚拟主机的配置,nginx支持三种类型的虚拟主机配置。 1、基于域名的虚拟主机 (server_name来区分虚拟主机——应用:外部网站) 2、基于ip的虚拟主机, (一台主机绑定多个ip地址) 3、基于端口的虚拟主机 (端口来区分虚拟主机——应用:公司内部网站,外部网站的管理后台)
1、 基于域名的虚拟主机
1、配置通过域名区分的虚拟机
[root@localhost ~]# cat /etc/nginx/nginx.conf worker_processes 4; #error_log logs/error.log; worker_rlimit_nofile 102400; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; server { listen 80; server_name web.testpm.com; location / { root /var/www/nginx/; index index.html index.htm; limit_rate 2k; } } server { listen 80; server_name web.1000phone.com; location / { root /1000phone/html; index index.html index.htm; } } }
2、 为 域名为 web.1000phone.com 的虚拟机,创建 index 文件
[root@localhost ~]# mkdir -p /1000phone/html [root@localhost ~]# vim /1000phone/html/index.html <html> <p> this is my 1000phone </p> </html>
3、重新加载配置文件
# 如果编译安装的执行 [root@nginx]# /usr/local/nginx/sbin/nginx -s reload # 如果 yum 安装的执行 [root@nginx]# nginx -s reload
4、客户端配置路由映射 在 C:\Windows\System32\drivers\etc\hosts 文件中添加两行(linux:/etc/hosts)
10.0.105.199 web.testpm.com 10.0.105.199 web.1000phone.com
5、 测试访问
浏览器输入:http://web.testpm.com/
浏览器输入:http://web.1000phone.com/
6、补充:如果配置不能正常访问,
问题描述: 配置完 nginx 两个虚拟机后,客户端能够访问原始的server ,新增加的 server 虚拟机 不能够访问,报错如下页面
解决过程:
-
查看报错日志(找到错误日志)
[root@localhost ~]# cat /var/log/nginx/error.log 2017/06/15 04:00:57 [error] 6702#0: *14 "/root/html/index.html" is forbidden (13: Permission denied), client: 10.219.24.1, server: web.1000phone.com, request: "GET / HTTP/1.1", host: "web.1000phone.com"
2.检查权限
[root@localhost html]# ll drwxr-xr-x. 2 root root 4096 Jun 15 03:59 html [root@localhost nginx]# ll total 8 -rw-r--r--. 1 root root 537 Jun 15 03:59 50x.html -rw-r--r--. 1 root root 616 Jun 15 03:51 index.html 说明:发现目录权限没有问题
3.检查nginx启动进程
[root@localhost nginx]# ps -ef | grep nginx root 2079 1 0 12:16 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx -c /etc/nginx/nginx.conf nobody 2080 2079 0 12:16 ? 00:00:00 nginx: worker process nobody 2081 2079 0 12:16 ? 00:00:00 nginx: worker process nobody 2082 2079 0 12:16 ? 00:00:00 nginx: worker process 说明:发现nginx的work process是 nobody 的
4.修改 nginx.conf 文件
打开nginx.conf文件所在的目录,查看文件的属性 (root root) [root@nginx]# ll drwxr-xr-x. 2 root root 4096 Jun 15 04:08 conf 在nginx.conf文件的第一行加上 user root root; [root@nginx]# cat conf/nginx.conf user root;
重新 reload nginx进程
2、 基于ip的虚拟主机
[root@localhost ~]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:0c:29:17:f1:af brd ff:ff:ff:ff:ff:ff inet 10.0.105.199/24 brd 10.0.105.255 scope global dynamic ens33 valid_lft 81438sec preferred_lft 81438sec inet6 fe80::9d26:f3f0:db9c:c9be/64 scope link valid_lft forever preferred_lft forever [root@localhost ~]# ifconfig ens33:1 10.0.105.201/24 [root@localhost ~]# ifconfig ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 10.0.105.199 netmask 255.255.255.0 broadcast 10.0.105.255 inet6 fe80::9d26:f3f0:db9c:c9be prefixlen 64 scopeid 0x20<link> ether 00:0c:29:17:f1:af txqueuelen 1000 (Ethernet) RX packets 9844 bytes 1052722 (1.0 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 5567 bytes 886269 (865.4 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 ens33:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 10.0.105.201 netmask 255.255.255.0 broadcast 10.0.105.255 ether 00:0c:29:17:f1:af txqueuelen 1000 (Ethernet) 2、配置通过ip区分的虚拟机 [root@localhost ~]# cat /etc/nginx/nginx.conf user root; worker_processes 4; #error_log logs/error.log; worker_rlimit_nofile 102400; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; server { listen 10.0.105.199:80; server_name web.testpm.com; location / { root /var/www/nginx/; index index.html index.htm; limit_rate 2k; } server { listen 10.0.105.201:80; server_name web.testpm.com; location / { root /1000phone/html/; index index.html index.htm; } } } 3、重新加载配置文件 [root@localhost ~]# /usr/local/nginx/sbin/nginx -s reload 4、 测试访问 浏览器输入:http://10.0.105.199 浏览器输入:http://10.0.105.201 5、补充 -- 删除绑定的vip [root@localhost ~]# ifconfig ens33:1 10.0.105.201/24 down 重启一下nginx [root@localhost ~]# systemctl restart nginx
3、 基于端口的虚拟主机
[root@localhost ~]# cat /etc/nginx/nginx.conf
user root;
worker_processes 4;
worker_rlimit_nofile 102400;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name web.testpm.com;
location / {
root /var/www/nginx/;
index index.html index.htm;
limit_rate 2k;
}
server {
listen 8080;
server_name web.1000phone.com;
location / {
root /1000phone/html/;
index index.html index.htm;
}
}
}
重新加载配置文件:
[root@localhost ~]# /usr/local/nginx/sbin/nginx -s reload
测试访问:
浏览器输入:http://web.testpm.com/
浏览器输入:http://web.1000phone.com:8080