C++文件服务器项目—Nginx—3
- 前言
- 1. Nginx一些基本概念
- 1.1 Nginx初步认识
- 1.2 正向代理概念理解
- 1.3 反向代理概念理解
- 2. Nginx的安装与配置
- 2.1 Nginx与相关依赖库的安装
- 2.2 Nginx相关的指令
- 2.3 Nginx的配置
- 2.4 location指令的提取
- 3. Nginx的使用
- 3.1 部署静态网页
- 3.2 访问http://ip:port/login.html
- 3.3 访问http://ip:port/hello/reg.html
- 3.4 访问http://ip:port/upload/
- 4. Nginx作为反向代理服务器
- 4.1 准备实验环境
- 4.2 反向代理设置
- 4.3 反向代理总结与测试
- 5. Nginx实现负载均衡
- 5.1 分析反向代理的缺陷
- 5.2 负载均衡设置
- 5.3 负载均衡总结与测试
- 6. 需要了解的知识
- 6.1 IP和域名的关系
- 6.2 URL和URI
- 6.3 DNS解析过程
- 6.4 http协议报文分析
- 7. Location语法
前言
本文重点介绍nginx的安装与配置,实现反向代理和负载均衡。源码地址:gopherWxf git
本专栏知识点是通过零声教育的线上课学习,进行梳理总结写下文章,对c/c++linux课程感兴趣的读者,可以点击链接 C/C++后台高级服务器课程介绍 详细查看课程的服务。
1. Nginx一些基本概念
1.1 Nginx初步认识
Nginx介绍:又名engine x,是一个框架,作者是俄罗斯人,开源的框架,C语言编写,淘宝基于nginx开源出了Tengine。
Nginx能干什么:1. 作为web服务器(-解析http协议)、2. 反向代理服务器(实现web服务器的负载均衡) 、3.邮件服务器(解析邮件相关的协议: pop3/smtp/imap)。
Nginx的优势:
-
更快
- 高峰期(数以万计的并发时)nginx可以比其它web服务器更快的响应请求
-
高扩展
-
高可靠
- 经过大批网站检验
- www.sina.com.cn
- www.xunlei.com
- www.163.com
- 每个worker进程相对独立, 出错之后可以快速开启新的worker
- worker进程是在后台干活的进程
- worker进程的个数是可以控制的
-
低内存消耗
- 一般情况下,10000个非活跃的HTTP Keep-Alive连接在nginx中仅消耗 2.5M内存
-
单机支持10万以上的并发连接
-
热部署
- master和worker的分离设计,可实现7x24小时不间断服务的前提下升级nginx可执行文件
-
最自由的BSD许可协议
- BSD许可协议允许用户免费使用nginx, 修改nginx源码,然后再发布
1.2 正向代理概念理解
正向代理是位于客户端和原始服务器之间的服务器,为了能够从原始服务器获取请求的内容,客户端需要将请求发送给代理服务器,然后再由代理服务器将请求转发给原始服务器,原始服务器接受到代理服务器的请求并处理,然后将处理好的数据转发给代理服务器,之后再由代理服务器转发发给客户端,完成整个请求过程。
正向代理的典型用途就是为在防火墙内的局域网客户端提供访问Internet的途径,最具代表性的就是学校的校园网
,通常需要账号密码登陆才能访问外网;挂vpn
访问github,谷歌等。可以看到,正向代理是为用户服务的,比较偏向于客户端。
1.3 反向代理概念理解
反向代理方式是指代理原始服务器来接受来自Internet的链接请求,然后将请求转发给内部网络上的原始服务器,并将从原始服务器上得到的结果转发给Internet上请求数据的客户端。那么顾名思义,反向代理就是位于Internet和原始服务器之间的服务器,对于客户端来说就表现为一台服务器,客户端所发送的请求都是直接发送给反向代理服务器,然后由反向代理服务器统一调配。
举个例子:三个客户端想要同时访问服务器,会给服务器造成一定的压力。
即使增加了服务器,但是我们也无法限制客户端去访问那一台服务器,这就操作了服务器的请求分配不均匀。
这个时候,如果能有一个代理出现,客户端先走到代理,再由代理去分配具体走到哪个服务器上,这样,服务器接收到的请求就比较均匀了。
这么中间这个代理就是反向代理服务器!
下面来总结一下反向代理服务器:
- 客户端给服务器发送请求, 连接服务器, 用户不知道服务器地址, 只有反向代理服务器的地址是公开的
- 那么客户端只能将请求直接发给反向代理服务器
- 反向代理服务器将请求转发给后边的web服务器
- web服务器 N 台,那么反向代理服务器转发请求会轮询分配请求(当然也可以设置权重,后续介绍)
- web服务器收到请求进行处理, 得到结果
- web服务器将处理结果发送给反向代理服务器
- 反向代理服务器将拿到的结果转发给客户端
2. Nginx的安装与配置
2.1 Nginx与相关依赖库的安装
对应的安装包已经放在前言的源码链接中,需要的自取。
Nginx依赖openssl,zlib,pcre这些库。所以首先我们要把这三个库给安装好
Nginx官方地址: http://nginx.org/
Nginx相关依赖:
- OpenSSL: http://www.openssl.org/
tar -zxvf openssl-1.1.1g.tar.gz
cd openssl-1.1.1g
./config
make
make install
ldconfig
- ZLib下载: http://www.zlib.net/
tar -zxvf zlib-1.2.11.tar.gz
cd zlib-1.2.11
./configure
make
make install
ldconfig
- PCRE下载: http://www.pcre.org/
tar -zxvf pcre-8.44.tar.gz
cd pcre-8.44
ls
./configure
make
make install
ldconfig
三个依赖库安装好之后,就可以进行nginx的安装了,这三个库对应的源码安装目录需要根据自己的电脑的库安装包的位置进行指定。
./configure --with-openssl=../openssl-1.1.1g --with-pcre=../pcre-8.44 --with-zlib=../zlib-1.2.11
make
make install
ldconfig
总结:
tar -zxvf nginx-1.16.1.tar.gz
cd nginx-1.16.1
./configure --with-openssl=../openssl-1.1.1g --with-pcre=../pcre-8.44 --with-zlib=../zlib-1.2.11
make
make install
ldconfig
来看一些make install 都做了哪些操作,如下图。这里最重要的是记住/usr/local/nginx
是nginx安装的根目录,usr/local/nginx/config
是nginx的一些配置文件,/usr/local/nginx/sbin
是nginx的启动目录。
2.2 Nginx相关的指令
conf -> 存储配置文件的目录
html -> 默认的存储网站(服务器)静态资源的目录 [图片, html, js, css]
logs -> 存储log日志
sbin -> 启动nginx的可执行程序
root@wxf:/
root@wxf:/usr/local/nginx/sbin
/usr/local/nginx/sbin
root@wxf:/usr/local/nginx/sbin
ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx
root@wxf:/
sudo nginx
sudo nginx -s stop
sudo nginx -s quit
sudo nginx -s reload
ps -aux | grep nginx
curl localhost
2.3 Nginx的配置
- Nginx配置文件的位置
/usr/local/nginx/conf/
nginx.conf
vi /usr/local/nginx/conf/nginx.conf
- Nginx配置文件的组织格式
- http模块->http相关的通信配置
- server模块 ->
每个server对应的是一台web服务器
- mail模块 ->处理邮件相关的动作
- 常用配置项介绍
注意下面的配置项,是把nginx当作一台web服务器来使用,与后续介绍的反向代理不同。
- 错误提示: nginx操作xxx文件时候失败, 原因: Permission denied
- 将nobody -> root
-
worker_processes 1;
error_log logs/error.log;
pid logs/nginx.pid;
events {
use epoll;
worker_connections 1024;
}
http{
server{
listen 80;
server_name localhost;
charset utf8;
// location 模块, 处理客户端的请求
location {指令} {
}
// location 模块, 处理客户端的请求
location {指令} {
}
// location 模块, 处理客户端的请求
location {指令} {
}
}
}
2.4 location指令的提取
上面的配置文件中,location后面跟的都是一个指令,这个指令是什么呢?
假设现在有一个客户端发送一个请求,http://192.168.10.100:80/login.html
。web服务器收到这个请求之后就需要处理客户端的请求,这个时候我们将协议,ip:端口,尾部的文件名都去掉
。剩下的就是服务器要处理的location指令。
http://192.168.10.100:80/login.html
服务器要处理的指令如何从url中提取?
- 去掉协议: http
- 去掉IP/域名+端口: 192.168.10.100:80
- 最后如果是文件名, 去掉该名字: login.html
- 剩下的: /
服务器要处理的location指令:
location /
{
处理动作
}
上述说的是静态请求,那么动态请求呢?get带参数怎么办?其实直接把?以及?之后的全部去掉即可
- 静态请求:客户端访问服务器的静态网页, 不涉及任何数据的处理, 如下面的URL:
http://localhsot:80/login.html
- 去掉协议: http://
- 去掉IP/域名+端口: localhsot:80
- 最后如果是文件名, 去掉该名字: login.html
- 剩下的: /
- 服务器要处理的location指令:
location /
{
处理动作
}
http://localhsot:80/hello/login.html
- 去掉协议: http://
- 去掉IP/域名+端口: localhsot:80
- 最后如果是文件名, 去掉该名字: login.html
- 剩下的: /hello/
- 服务器要处理的location指令:
location /hello/
{
处理动作
}
- 动态请求:客户端会将数据提交给服务器
http://localhost/login?user=zhang3&passwd=123456&age=12&sex=man
- http: 协议
- localhost: 域名
- /login: 服务器端要处理的指令
- ? : 连接符, 后边的内容是客户端给服务器提交的数据
- & : 分隔符
- user/zhang3...等:键值对,数据
- 去掉协议
- 去掉域名/IP
- 去掉端口
- 去掉末尾的文件(此处没有)
- 去掉?和它后边的内容
- 剩下的: /login
- 服务器要处理的location指令:
location /login
{
处理动作
}
POST /upload/UploadAction HTTP/1.1
GET /?username=tom&phone=123&email=hello%40qq.com&date=2018-01-01&sex=male&class=3&rule=on HTTP/1.1
1. 找请求行的第二部分
- 如果是post, 处理指令就是请求行的第二部分(/upload/UploadAction)
- 服务器要处理的location指令:
location /upload/UploadAction
{
处理动作
}
- 如果是get, 处理指令就是请求行的第二部分, ? 以前的内容(/)
- 服务器要处理的location指令:
location /
{
处理动作
}
3. Nginx的使用
3.1 部署静态网页
nginx默认存放静态资源的目录是
/usr/local/nginx/html
自己创建新的目录应该与这个html同级别
才行
mkdir /usr/local/nginx/mydir
将源码中写好的html网页yundisk目录放到/usr/local/nginx/
目录下。那么这个yundisk目录和html目录现在是同级的。yundisk里面存储的是静态资源。
3.2 访问http://ip:port/login.html
3.3 访问http://ip:port/hello/reg.html
3.4 访问http://ip:port/upload/
4. Nginx作为反向代理服务器
4.1 准备实验环境
- 需要客户端 - 1个
- 反向代理服务器 -> 1个
- ubuntu192.168.109.101作为反向代理服务器
- web服务器 -> 2个
- ubuntu192.168.109.102 - 默认主页修改为gopherwxf
- ubuntu192.168.109.103 - 默认主页修改为wuxufei
- 因为反向代理没有绑定域名,所以修改windows的hosts文件,自己加域名
- 192.168.109.101 ubuntu101to102.com
- 192.168.109.101 ubuntu101to103.com
4.2 反向代理设置
找101机器上上对应的nginx的配置文件
- vi /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name ubuntu101to102.com;
location / {
proxy_pass http://reverse.proxy1.com;
}
}
upstream reverse.proxy1.com
{
server 192.168.109.102:80;
}
server {
listen 80;
server_name ubuntu101to103.com;
location / {
proxy_pass http://reverse.proxy2.com;
}
}
upstream reverse.proxy2.com
{
server 192.168.109.103:80;
}
}
4.3 反向代理总结与测试
5. Nginx实现负载均衡
5.1 分析反向代理的缺陷
反向代理虽然能代理到不同的web服务器上,但是server_name必须要不同。那有100台呢?要取100个名字吗?而且如果这100台服务器干的都是相同的内容,这么这个server_name就是冗余了。
负载均衡就是实现入口资源的平均分配,那么这个入口地址server_name就应该是一样的了,而不是一个web服务器对应一个地址,这样是指定了。100台服务器都用同一个server_name,至于最终转发到哪台服务器,交给负载均衡来处理,用户不去关心。
负载均衡就直接把server_name换成一个唯一的域名即可(相同服务的web服务器用同一个域名,如果有别的服务器处理别的业务,则它们共用另一个)。
不止server_name是冗余的,proxy_pass也是冗余的,再观察,其实server也是冗余的。我们只需要在upstream里面把web服务器的ip加上去就行了,不需要额外再写server模块。
5.2 负载均衡设置
server {
listen 80;
server_name reverse.proxy.com;
location / {
proxy_pass http://linux.com;
}
location /hello/ {
proxy_pass http://linux.com;
}
location /upload/ {
proxy_pass http://linux.com;
}
}
upstream linux.com
{
server 192.168.109.102:80;
server 192.168.109.103:80;
}
web服务器需要做什么?
location /
{
root xxx;
index xxx;
}
location /hello/
{
root xx;
index xxx;
}
location /upload/
{
root xxx;
index xx;
}
location /
{
root xxx;
index xxx;
}
location /hello/
{
root xx;
index xxx;
}
location /upload/
{
root xxx;
index xx;
}
5.3 负载均衡总结与测试
6. 需要了解的知识
6.1 IP和域名的关系
- 什么是域名?
www.baidu.com
www.jd.com
www.taobao.com
- 什么是IP地址?
点分十进制的字符串
例如:
192.168.109.101
192.168.109.102
192.168.109.103
- 域名和IP地址的关系?
域名绑定IP
一个域名只能绑定一个IP
一个IP地址被多个域名绑定
6.2 URL和URI
-
概念:
-
URL(Uniform Resource Locator): 统一资源定位符
-
表示资源位置的字符串
- 基本格式: “协议://IP地址/路径和文件名”
- ftp://ftp.is.co.za/rfc/rfc1808.txt
- http://www.ietf.org/rfc/rfc2396.txt
- telnet://192.0.2.16:80/
-
URN(Uniform Resource Name): 统一资源名称
-
URI(Uniform Resource Identifier): 统一资源标识符
- 是一个紧凑的字符串用来标示抽象或物理资源, URL是URI的一种
- URI可以没有协议, 没有地址(IP/域名)
- 让URI能成为URL就必须拥有”协议“,”ip or 域名“,e.g.
http://
or ftp://
。
- files.hp.com
- tel:+1-816-555-1212
- ftp://ftp.is.co.za/rfc/rfc1808.txt (also a URL)
- http://www.ietf.org/rfc/rfc2396.txt (also a URL)
- telnet://192.0.2.16:80/ (also a URL)
6.3 DNS解析过程
-
DNS解析的过程
- 在浏览器中输入www.magedu.com域名,操作系统会先检查自己本地的hosts文件是否有这个网址映射关系,如果有,就先调用这个IP地址映射,完成域名解析。
- 如果hosts里没有这个域名的映射,则查找本地DNS解析器缓存,是否有这个网址映射关系,如果有,直接返回,完成域名解析。
- Windows和Linux系统都会在本地缓存dns解析的记录,提高速度。
- 如果hosts与本地DNS解析器缓存都没有相应的网址映射关系,首先会找
TCP/IP
参数中设置的首选DNS服务器,在此我们叫它本地DNS服务器,此服务器收到查询时,如果要查询的域名,包含在本地配置区域资源中,则返回解析结果给客户机,完成域名解析,此解析具有权威性。 - 如果要查询的域名,不由本地DNS服务器区域解析,但该DNS服务器已缓存了此网址映射关系,则调用这个IP地址映射,完成域名解析,此解析不具有权威性。
- 如果本地DNS服务器本地区域文件与缓存解析都失效,则根据本地DNS服务器的设置(没有设置转发器)进行查询,如果未用转发模式,本地DNS就把请求发至13台根DNS,根DNS服务器收到请求后会判断这个域名(.com)是谁来授权管理,并会返回一个负责该顶级域名服务器的一个IP。本地DNS服务器收到IP信息后,将会联系负责 .com域的这台服务器。这台负责 .com域的服务器收到请求后,如果自己无法解析,它就会找一个管理 .com域的下一级DNS服务器地址(magedu.com)给本地DNS服务器。当本地DNS服务器收到这个地址后,就会找magedu.com域服务器,重复上面的动作进行查询,直至找到www.magedu.com主机。
- 如果用的是转发模式(设置转发器),此DNS服务器就会把请求转发至上一级ISP DNS服务器,由上一级服务器进行解析,上一级服务器如果不能解析,或找根DNS或把转请求转至上上级,以此循环。不管是本地DNS服务器用是是转发,还是根提示,最后都是把结果返回给本地DNS服务器,由此DNS服务器再返回给客户机。
-
域名解析服务器
-
Pod DNS+:
- 首选:119.29.29.29
- 备选:182.254.116.116
-
114DNS:
- 首选:114.114.114.114
- 备选:114.114.114.115
-
阿里 AliDNS:
-
首选:223.5.5.5
-
备选:223.6.6.6
-
hosts文件
-windows目录: "C:\Windows\System32\drivers\etc\hosts"
6.4 http协议报文分析
-
请求消息(Request)
- 客户端(浏览器)发送给服务器的数据格式
四部分: 请求行, 请求头, 空行, 请求数据
请求行
: 说明请求类型, 要访问的资源, 以及使用的http版本请求头
: 说明服务器要使用的附加信息空行
: 空行是必须要有的, 即使没有请求数据请求数据
: 也叫主体, 可以添加任意的其他数据
-
Get方式提交数据
第一行: 请求行
第2-9行: 请求头(键值对)
第10行: 空行
get方式提交数据, 没有第四部分, 提交的数据在请求行的第二部分, 提交的数据会全部显示在地址栏中
GET /?username=tom&phone=123&email=hello%40qq.com&date=2018-01-01&sex=male&class=3&rule=on HTTP/1.1
Host: 192.168.26.52:6789
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh,zh-CN;q=0.9,en;q=0.8
-
Post方式提交数据
第一行: 请求行
第2 -12行: 请求头 (键值对)
第13行: 空行
第14行: 提交的数据
POST / HTTP/1.1
Host: 192.168.26.52:6789
Connection: keep-alive
Content-Length: 84
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh,zh-CN;q=0.9,en;q=0.8
username=tom&phone=123&email=hello%40qq.com&date=2018-01-01&sex=male&class=3&rule=on
-
响应消息(Response)
-> 服务器给客户端发送的数据
- 四部分:
状态行, 消息报头, 空行, 响应正文
状态行
: 包括http协议版本号, 状态码, 状态信息消息报头
: 说明客户端要使用的一些附加信息空行
: 空行是必须要有的响应正文
: 服务器返回给客户端的文本信息
第一行:状态行
第2 -11行: 响应头(消息报头)
第12行: 空行
第13-18行: 服务器给客户端回复的数据
HTTP/1.1 200 Ok
Server: micro_httpd
Date: Fri, 18 Jul 2014 14:34:26 GMT
/* 告诉浏览器发送的数据是什么类型 */
Content-Type: text/plain; charset=iso-8859-1 (必选项)
/* 发送的数据的长度 */
Content-Length: 32
Location:url
Content-Language: zh-CN
Last-Modified: Fri, 18 Jul 2014 08:36:36 GMT
Connection: close
#include <stdio.h>
int main(void)
{
printf("hello world!\n");
return 0;
}
-
http状态码
状态代码有三位数字组成,第一个数字定义了响应的类别,共分五种类别:
- 1xx:指示信息–表示请求已接收,继续处理
- 2xx:成功–表示请求已被成功接收、理解、接受
- 3xx:重定向–要完成请求必须进行更进一步的操作
- 4xx:客户端错误–请求有语法错误或请求无法实现
- 5xx:服务器端错误–服务器未能实现合法的请求
7. Location语法
- 语法规则
location [=|~|~*|^~] /uri/
{
…
}
正则表达式中的特殊字符:
- . () {} [] * + ?
-
Location优先级说明
- 在nginx的location和配置中location的顺序没有太大关系。
- 与location表达式的类型有关。
- 相同类型的表达式,字符串长的会优先匹配。
-
location表达式类型
-
匹配模式及优先级顺序(高 -> 低):
location = /uri | =开头表示精确匹配,只有完全匹配上才能生效。 一旦匹配成功,则不再查找其他匹配项。 |
---|
location ^~ /uri | ^~ 开头对URL路径进行前缀匹配,并且在正则之前。 一旦匹配成功,则不再查找其他匹配项。 需要考虑先后顺序, 如: http://localhost/helloworld/test/a.html |
location ~ pattern location ~* pattern | ~ 开头表示区分大小写的正则匹配。 ~*开头表示不区分大小写的正则匹配。 |
location /uri | 不带任何修饰符,也表示前缀匹配,但是在正则匹配之后。 |
location / | 通用匹配,任何未匹配到其它location的请求都会匹配到,相当于switch中的default。 |
指令是:/ -> configuration A
指令是:/index.html -> configuration B
指令是:/documents/document.html -> configuration C
指令是:/images/1.gif -> configuration D
指令是:/documents/1.jpg -> configuration E
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)