Nginx之旅-基础篇-中

HTTP请求

大家都知道nginx作为webserverhttp的代理,处理的就是http请求。
http请求是是建立在tcp基础上的。

一个完整的http请求包括requestresponse两部分。
request组成:请求行, 请求头, 请求数据
response组成:状态行, 消息报头, 响应正文

我们在终端下发起一个HTTP请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[root@hongshaorou ~]# curl -v www.baidu.com > /dev/null
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* About to connect() to www.baidu.com port 80 (#0)
* Trying 180.97.33.108...
* Connected to www.baidu.com (180.97.33.108) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: www.baidu.com
> Accept: */*
>
< HTTP/1.1 200 OK
< Accept-Ranges: bytes
< Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
< Connection: Keep-Alive
< Content-Length: 2381
< Content-Type: text/html
< Date: Tue, 04 Dec 2018 14:35:14 GMT
< Etag: "588604f7-94d"
< Last-Modified: Mon, 23 Jan 2017 13:28:23 GMT
< Pragma: no-cache
< Server: bfe/1.0.8.18
< Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/
<
{ [data not shown]
100 2381 100 2381 0 0 32949 0 --:--:-- --:--:-- --:--:-- 33069
* Connection #0 to host www.baidu.com left intact

大于号部分是请求部分,小于号部分是响应部分

Nginx虚拟主机

多套业务服务如何配置?

是多个主机还是一个主机配置多个虚拟主机?答案是虚拟主机。

虚拟主机配置多个服务

虚拟主机:在同一个Nginx上运行多套单独服务,这些服务是相互独立的。

虚拟主机配置方式主要有三种

方法一:基于主机多IP的方式

就是在一个主机上配置多个IP,只用同一个Nginx来针对不同的IP来提供对外服务。

基于多IP

方法二:基于端口的配置方式

不同的虚拟主机监听的端口是不一样的,通过端口区分不同的虚拟主机。

基于端口

方法三:基于多个host名称方式(多域名方式)

根据不同的主机名(域名)进行配置

基于多host名称

监听的还是一个IP和端口

基于主机多IP的方式

该方式重点是在主机上实现多IP的绑定,主机多IP也分两种方式:

多网卡多IP

单网卡多IP

我们使用本地虚拟机实现单网卡多IP的方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 添加一个局域网内没有被使用的ip 将其添加到 设备 eth1 上
[vagrant@docker-host ~]$ sudo ip a add 192.168.205.16/24 dev eth1

# 这时候查看下 网络设备 发现 eth1 上有两个IP
[vagrant@docker-host ~]$ ip a
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:ca:d8:c8 brd ff:ff:ff:ff:ff:ff
inet 192.168.205.10/24 brd 192.168.205.255 scope global noprefixroute eth1
valid_lft forever preferred_lft forever
inet 192.168.205.16/24 scope global secondary eth1
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:feca:d8c8/64 scope link
valid_lft forever preferred_lft forever
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[vagrant@docker-host conf.d]$ pwd
/etc/nginx/conf.d

[vagrant@docker-host conf.d]$ ls
default.conf.bak vserver1.conf vserver2.conf

# 指定IP
[vagrant@docker-host conf.d]$ head vserver1.conf
server {
listen 192.168.205.10:80; # 指定具体地址 的 80 端口
server_name localhost;

location / {
root /usr/share/nginx/html;
index index.html index.htm;

[vagrant@docker-host conf.d]$ head vserver2.conf
server {
listen 192.168.205.16:80; # 指定具体地址 的 80 端口
server_name localhost;

location / {
root /usr/share/nginx/html;
index index.html index.htm;

重启Nginx服务

1
2
nginx -s stop -c /etc/nginx/nginx.conf # 停止
nginx -c /etc/nginx/nginx.conf # 启动
基于多端口的配置

基于端口的配置和基于IP的类似,不过我们要注意设置的端口不要和其他虚拟主机的端口以及本地程序的端口有冲突。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[vagrant@docker-host conf.d]$ ss -luntp
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
udp UNCONN 0 0 127.0.0.1:323 *:*
udp UNCONN 0 0 *:946 *:*
udp UNCONN 0 0 *:68 *:*
udp UNCONN 0 0 *:111 *:*
udp UNCONN 0 0 ::1:323 :::*
udp UNCONN 0 0 :::946 :::*
udp UNCONN 0 0 :::111 :::*
tcp LISTEN 0 100 127.0.0.1:25 *:*
tcp LISTEN 0 128 *:111 *:*
tcp LISTEN 0 128 192.168.205.16:80 *:*
tcp LISTEN 0 128 192.168.205.10:80 *:*
tcp LISTEN 0 128 *:22 *:*
tcp LISTEN 0 100 ::1:25 :::*
tcp LISTEN 0 128 :::111 :::*
tcp LISTEN 0 128 :::22 :::*

我们可以使用ss -luntp (centos6使用netstat -luntp)查找本地正在被使用的端口。

我们设置端口配置虚拟主机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[vagrant@docker-host conf.d]$ head vserver1.conf
server {
listen 80;
server_name localhost;

location / {
root /usr/share/nginx/html;
index index.html index.htm;

[vagrant@docker-host conf.d]$ head vserver2.conf
server {
listen 81;
server_name localhost;

location / {
root /usr/share/nginx/html;
index index.html index.htm;
1
2
3
4
5
6
7
8
# 检查配置语法是否有误
[vagrant@docker-host conf.d]$ sudo nginx -tc /etc/nginx/nginx.conf
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

# 重启服务
[vagrant@docker-host conf.d]$ sudo nginx -s stop -c /etc/nginx/nginx.conf
[vagrant@docker-host conf.d]$ sudo nginx -c /etc/nginx/nginx.confs

这样我们可以指定端口访问对于的虚拟主机:http://192.168.205.10:81/ http://192.168.205.10:80/

基于HOST域名的配置

将域名和主机IP对于关系设置到本机的/etc/hosts

1
2
192.168.205.10  1.imooc.com
192.168.205.10 2.imooc.com

修改虚拟机的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[vagrant@docker-host conf.d]$ head vserver1.conf
server {
listen 80;
server_name 1.imooc.com;

location / {
root /usr/share/nginx/html;
index index.html index.htm;
[vagrant@docker-host conf.d]$ head vserver2.conf
server {
listen 80;
server_name 2.imooc.com;

location / {
root /usr/share/nginx/html;
index index.html index.htm;
Nginx日志类型

包括:error.log access_log
error.log主要是处理http请求错误和nginx本身服务错误状态,按照不同的错误级别记录
access_log 主要是记录处理每次http请求访问的状态

日志主要实现方式是使用 log_format

nginx记录的每次信息都可以当做一个变量,log_format就是将这些变量组合起来,记录到日志中去

我们看一下log_format的配置

1
2
3
Syntax: log_format name [escape=default|json] string …;
Default: log_format combined "...";
Context: http (约束log_format的配置位置)

1
2
3
4
5
6
7
8
9
# 配置错误日志
error_log /var/log/nginx/error.log warn;


# 配置成功日志
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;

上面的error.log后面表示错误等级。

下面的access.log后面的main表示使用上面的log_format

Nginx大致有三类变量能够记录在log_format

  • HTTP请求变量- arg_PARAMETER(请求参数) http_HEADER(请求头信息) send_http_HEADER(服务端返回)
  • 内置变量- Nginx内置的
  • 自定义变量- 自己定义的

对于nginx的内置变量,我们可以查看官网信息:

我们看一下默认的log_format

1
2
3
4
5
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;

我们看到默认的格式,基本都是单引号''包裹着一些变量,还包括 中划线-方括号[]作为分隔符一起打印。
每个变量都有这含义:

1
2
3
4
5
6
7
8
9
remote_addr:对应客户端的地址
remote_user:是请求客户端请求认证的用户名,如果没有开启认证模块的话是值为空。
time_local:表示nginx服务器时间
request:表示request请求头的行
status:表示response的返回状态
body_bytes_sent:表示从服务端返回给客户端的body数据大小
http_referer:表示请求的上一级页面
http_user_agent:表示agent信息
http_x_forwarded_for:会记录每一级请求中信息
知识就是财富
如果您觉得文章对您有帮助, 欢迎请我喝杯水!