0%

首先,奉上varnish4.0官方手册,获取最新版请前往官方站点http://varnish-cache.org/docs/index.html

varnish简介:

varnish是一款HTTP反向代理软件,或干脆称它为HTTP/web加速器。varnish能够将文件或文件碎片缓存到内存中,从而减少响应时长并节省了RS主机的宽带等资源。另外,其不单单是一款反向代理HTTP的程序,还可以作为:

  • web application firewall,
  • DDoS attack defender,
  • load balancer,
  • integration point,
  • single sign-on gateway,
  • authentication and authorization policy mechanism,
  • quick fix for unstable backends, and
  • HTTP router

另外,需要注意,多台varnish在前端做负载均衡集群,应该使用hash url算法将用户请求调度到不同的varnish服务器上,以保证最大命中率。

相关概念:

程序在运行过程中具有局限性特征,本次被访问的数据可能在很短时间内被再次访问(时间局限性);本次被访问的数据的周边数据也可能会被再次访问(空间局限性)。

数据中有一定比例的数据被经常访问,占用了所有访问量的较大部分(数据热区)。

缓存命中率:hit/(hit+miss),分为文档命中率(按照文档的命中数量进行衡量)、字节命中率(按照命中的大小进行衡量)

缓存处理步骤

接收请求 –> 解析请求(提取请求的url及各种首部) –> 查询缓存(key) –> 新鲜度检测 –> 构建响应报文 –> 发送响应 –> 记录日志

CDN调度方式

  • 通过DNS服务,将不同来源的用户请求解析到不同缓存服务器

  • 设置一台全局负载均衡调度服务器(GSLB),所有的用户请求到转发到GSLB,GSLB根据自己的数据库信息,将用户请求调度到不同服务器

同类程序比较

  • squid:八爪鱼,成熟稳定,较大负载非常稳定。
  • varnish:轻量级,性能较好,但较大负载可能不稳定。两者间微妙的关系正如httpd与nginx。

缓存控制机制

在HTTP/1.0时,引入了缓存过期首部(Expires),可以指定资源在到达某特定时间后过期。如”Expires:Fri, 20 May 2016 02:03:18 GMT”。

在HTTP/1.1时,引入了新的缓存控制首部(Cache-Control),可更加精细的控制资源缓存情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Cache-Control:
cahe-request-directive=
no-cache
| no-store
| max-age
| max-stale
| min-fresh
cache-response-directive=
public
| private
| no-cache
| no-store
| must-revalidate
| max-age
| s-max-age

varnish简介:

varnish对资源的新鲜度检测机制:

当缓存项到期或前端客户端要求(如客户端访问时使用了Shift+F5)从后端服务器取资源时,试想一下,如果资源未改变,从后端取完整数据显然不够明智。于是varnish有以下有效性再验证(revalidate)方法:

  • 原始内容未改变 –> 仅响应首部(不用附带body部分);响应码为304(Not Modified)

  • 原始内容发生了改变 –> 正常响应;响应码为200

  • 原始内容消失 –> 则响应为404;此时缓存中的缓存项也应该被删除

另外,可以通过条件式请求首部,已达到有效性再验证的目的:

1
2
3
4
If-Modified-Since:基于原始内容的最近一个修改的时间戳进行;
If-Unmodified-Since
If-Match
If-None-Match:基于Etag的比较进行;

程序结构

Management:提供命令行、子进程管理、初始化功能

VCL compiler:varnish configure language compilter,VCL编译器,通过调用C编译器和共享库来编译vcl配置文件供子进程使用。(每次修改配置文件后都需要重新编译配置文件)

Child/cache:提供命令行、存储/哈希、日志/状态、请求管理、后端主机管理、worker线程、对象过期功能。

Log file:varnish默认会将日志记录在共享内存区域(shared memory log),若想保留到文件中,需手动配置。

另外,varnish提供CLI、Telnet、Web(收费版)三种管理接口。

varnish程序架构

简而言之,varnish请求工作流程如下:(需要注意,varnish的多个状态引擎之间存在相关性但又彼此隔离;每个引擎 使用return(X)来退出当前状态,并转入下一个状态。不同状态引擎return(X)中的X不尽相同)

可缓存资源 –> 命中 –> 本地缓存直接响应
命中 –> 后端主机 –> 可缓存资源 –> 先缓存,再响应
缓存,直接响应
不可缓存资源 –> 后端主机 –> …

安装与配置:

epel源安装varnish4.0:

1
[root@varnish-server ~]# yum -y install varnish varnish-docs</pre>

配置文件:

/etc/varnish/default.vcl #配置缓存策略

语法:

  • 注释:// # //
  • 定义子例程:sub $name(如sub vcl_recv、sub vcl_backend_response等)
  • 不支持循环,支持条件判断
  • 有内建变量
  • 有终止语句(return(X)),但没有返回值。用以告知下一步交由哪个引擎来处理
  • 操作符:= == != ~(正则表达式比较) && ||

/etc/varnish/varnish.params #配置进程工作特性

varnish.params配置文件中的定义非常容易理解,仅需要注意以下条目

1
2
3
4
5
6
VARNISH_LISTEN_PORT=80   #很多时候我们都需要将监听端口修改为80
VARNISH_STORAGE="file,/var/lib/varnish/varnish_storage.bin,1G" #定义缓存存储方式
· malloc[,size]
· file[,path[,size[,granularity]]]
· persistent,path,size
DAEMON_OPTS="-p thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300" #定义运行时特性

varnish内建变量

varnish有丰富的内建变量,但各引擎对不同变量的使用权限不同,在不允许使用的引擎使用会报错,官方表格如下:

各引擎对内建变量的使用限制

查看具体有哪些内建变量以及变量的含义,请自行man vcl

内建变量含义整理

1
2
3
4
5
6
7
8
9
10
req.*:request,由客户发来的http请求相关;
req.http.*:请求报文各首部;
bereq.*:backend request,由varnish向backend主机发出的http请求;
bereq.http.*
beresp.*:backend response,由backend主机发来的http响应报文;
beresp.http.*
resp.*:response,由varnish响应给client的http的响应报文;
resp.http.*:响应报文的各首部;
obj.*:object,存储在缓存空间中的缓存对象属性;只读;
client.*, server.*, storage.*:可用在所有的client side的sub routines中;

参考自:http://www.varnish-cache.org/docs/4.0/users-guide/vcl-built-in-subs.html

常用内建变量整理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bereq:
bereq.http.HEADERS:
bereq.method:请求方法;
bereq.url:请求的url;
bereq.proto:协议版本;
bereq.backend:指明要调用的后端主机;
beresp:
beresp.proto:
beresp.status:响应的状态码;
beresp.reason:
beresp.backend.name:
beresp.http.HEADERS:
beresp.ttl:后端服务器响应中的内容的余下的生存时长;
obj
obj.hits:此对象从缓存中命中的次数;
obj.ttl:对象的ttl值;
server:
server.ip
server.hostname
req.method:请求方法;
req.url:请求的url;

一大波示例:

简单示例:自定义响应报文首部(X-cache),用以标识缓存是否命中

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@varnish ~]# vim /etc/varnish/default.vcl
backend default {
.host = "172.18.31.22"; #定义后端主机IP,也可以定义为FQDN
.port = "80"; #定义后端主机web服务Port
}
sub vcl_deliver {
if (obj.hits>0) { #调用内建变量。obj.hits表示本资源命中次数
set resp.http.X-cache = "HIT via " + server.ip + " " + obj.hits;
} else {
set resp.http.X-cache = "MISS via " + server.ip + " " + obj.hits;
}
}
[root@varnish ~]# systemctl reload varnish

另外,除了使用reload之外,我们也可以使用varnishadm来连接管理接口来管理配置文件。

1
2
3
4
5
6
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082   #连接管理接口,-S指定使用的密钥文件
help #获取命令帮助
vcl.list #查看配置文件列表,正在启用状态的为”active”,可被使用的状态为”available”
vcl.show CONFIG #查看配置文件内容
vcl.load test1 default.vcl #编译配置文件为test1。然后可使用vcl.use test1来启用此配置文件
vcl.use CONFIG #指定启用哪个配置文件,使用状态的配置文件为”active”

简单示例:设置某资源不查询缓存

1
2
3
4
5
6
7
8
9
10
在vcl_recv{}内定义
if (req.url ~ "(?i)^/login" || req.url ~ "(?i)^/admin"){ #对请求url进行匹配。(?i)表示忽略大小写,对以login或admin开头的资源不查询缓存
return(pass);
}
#在后端http服务器上建立测试文件
[root@client ~]# cd /var/www/html/
[root@client html]# for i in {admin,ADMIN,login,LOGIN};do echo "$i/index.html" > $i/index.html;done
[root@client html]# chown -R apache.apache *
[root@client html]# chmod -R 755 *
[root@varnish ~]# systemctl reload varnish #重新加载varnish配置

网页测试,多次刷新。可以看到特定目录下的资源不会被缓存命中

简单示例:对css格式资源,取消cookie标识,设置缓存时长为2小时

1
2
3
4
5
6
7
#在sub vcl_backend_response {}内添加
if (beresp.http.cache-control !~ "s-maxage") {
if (bereq.url ~ "(?i)\.css$") {
set beresp.ttl = 3600s;
unset beresp.http.Set-Cookie;
}
}

简单示例:缓存对象修建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#在sub vcl_recv{}内定义,当客户端请求方法为”PURGE”时,交由purge引擎处理
if (req.method == "PURGE") {
if (!client.ip ~ purgers) {
return(synth(405,"Purging not allow for"+ client.ip));
}
return(purge);
}
#这么危险的操作,必须设置访问控制列表噻
acl purgers {
"127.0.0.1"/8;
"172.18.31.22"/32;
}
#定义purge引擎操作
sub vcl_purge {
return (synth(200, "Purged"));
}
#使用curl命令测试
curl -X PURGE http://IP/XX #使用curl命令指定使用PURGE方法来访问某资源

这时,浏览器再次访问此资源,可以看到此资源是由backend主机响应的,由此确定其已经从varnish服务器删除

简单示例:实现动静资源分离

1
2
3
4
5
6
7
8
9
10
11
12
#新建一个后端主机区块
backend php_server {
.host = "172.18.31.23";
.port = "80";
}
#在sub vcl_recv {}内添加
if (req.url ~ "(?i)\.php$") { #将所有对.php结尾的资源的请求转发向后端主机,否则转发到默认后端主机
set req.backend_hint = phpserver;
} else {
set req.backend_hint = default;
}
#浏览器访问不同资源类型,查看后端主机访问日志,就会发现确实有效

参考自:http://www.varnish-cache.org/docs/4.0/users-guide/vcl-backends.html

注意!上例会出现一个问题!当动态资源产生静态资源时,无法正常在页面显示。想要做到彻底的动静分离需要考虑将动态资源产生静态资源的处理(共享存储等),这里仅给出动态资源带参数的访问静态资源的解决方案:

将上面的匹配语句替换为:

1
if (req.url ~ "(?i)\.php[;?#][^\.]+$" || req.url ~ "(?i)\.php$")</pre>

简单示例:实现负载均衡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import directors;   #加载directorys
backend default {
.host = "172.18.31.22";
.port = "80";
}
backend phpserver {
.host = "172.18.31.23";
.port = "80";
}
sub vcl_init { #将上面两个backend定义到一个后端主机组
new web = directors.round_robin(); #轮询方式,其他方式还有directors.fallback() (遍历所有)、directors.random()(随机)、directors.hash()(哈希,根据客户端身份或session);详细请man vmod_directors
web.add_backend(default);
web.add_backend(phpserver);
}
sub vcl_recv {
set req.backend_hint = web.backend(); #将请求发送给后端主机组
}

简单示例:backend健康状态检测

1
2
3
4
5
6
7
8
9
10
backend server1 {
.host = "172.18.31.22 ";
.probe = {
.url = "/";
.timeout = 1s;
.interval = 5s;
.window = 5;
.threshold = 3;
}
}

varnish命令行工具

varnishadm

用以管理运行中的varnish实例

1
2
3
4
5
6
7
8
9
10
11
vcl.load <configname> <filename>  #编译varnish配置文件
vcl.inline <configname> <quoted_VCLstring>
vcl.use <configname> #启用编译后的配置文件
vcl.discard <configname>
vcl.list #查看所有可用配置文件类表
param.show [-l] [<param>] #显示运行时参数
param.set <param> <value> #设置运行时参数
storage.list
vcl.show [-v] <configname> #显示配置文件内容
backend.list [<backend_expression>] #显示后端主机
backend.set_health <backend_expression> <state> #设置后端主机健康状态信息

varnishtop

获取资源日志信息

-X <[taglist:]regex> 显示不匹配内容
-I <[taglist:]regex> 显示匹配内容

1
[root@varnish ~]# varnishtop -I "ReqURL:/"  #仅显示键位”ReqURL”,值为”/”的统计信息

varnishncsa

以apache/NCSA格式显示日志

也可以启用varnishncsa.service服务来将日志保存到文件中

varnishlog

以原始请求记录格式显示日志

也可以启用varnishlog.service服务来将日志保存到文件中

varnishstat

显示varnish的缓存统计数据

memcached简介:

memcached是一款自由&开放、高性能、通用的分布式内存对象缓存系统,用以加速动态web应用程序,减轻数据库负载。memcached是一个将database calls、API calls或page rendering以键值对**的形式存储于内存小区块的程序。

同类程序还有redis。memcached将键值对仅存储于内存中,重启memcached程序将导致数据丢失,而redis在存储于内存的同时,会周期性的将数据同步于辅助内存上。

官方站点:http://memcached.org/

memcached特性:

  • K/V缓存:可序列化数据。通常用来补充mysql,增加结构化数据请求响应速度。可存储项有key、value、flag、expire time
  • 功能实现一半依赖服务端,一半依赖于客户端。这里的客户端指的是各web程序,目前memcached支持C/C++、Perl、PHPPython、Ruby、Java、C#、Postgres、Chicken Scheme、Lua、MySQL和Protocol等语言客户端。
  • 分布式缓存:互不通信的分布式集群。
  • O1的执行效率,查询速度与数据量无关。
  • 清理过期数据:在缓存项过期或缓存空间用尽时使用LRU(最近最少算法)清理过期缓存。

memcached服务端

CentOS7上安装

1
[root@zabbix-server yum.repos.d]# yum -y install memcached

配置文件

仅有一个工作特性配置文件

/etc/sysconfig/memcached #用以定义工作端口、用户、最大连接数、缓存大小等。

监听端口

TCP/11211,UDP/11211

服务启动

服务启动有两种方式,

  • memcached [options]
    -d 以守护进程方式启动
    -c <num>:最大并发连接数,默认为1024
    -m <num> 最大使用num MB内存作为缓存,默认64MB
    -u <username> 运行用户
    -l <ip_addr> 监听IP
    -p <num> 监听的TCP端口,默认11211
    -U <num> 监听的UDP端口,默认11211
    -M 存空间耗尽时,向请求者返回错误信息,而不是基于LRU算法进行缓存清理</
    -t <threads> 处理用于请求的线程数
    -f <factor> growth factor,增长因子
  • systemctl start memcached

管理

可借助telnet客户端连接来管理,memcached默认没有认证机制,但可借助于SASL进行认证;

1
2
3
4
5
6
7
telnet memcached_IP 11211
stats [items|slabs|sizes|...]:显示统计信息
set,add,replace,append,prepend:存储管理
get KEY:获取数据
delete KEY:删除数据
incr/decr KEY NUM:原数据进行加减运算
flush_all:清空所有数据

php客户端配置:

CentOS7上安装php-fpm以及php-pecl-memcache或php-pecl-memcached(这里以php-pecl-memcache为例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@php ~]# yum -y install httpd php-fpm php-pecl-memcache
#新建httpd配置文件,将php页面传递给php-fpm服务处理
[root@php ~]# cat /etc/httpd/conf.d/fcgi.conf
ProxyRequests Off
ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/var/www/html/$1
#修改php配置文件,将session保存到memcached服务器
[root@php ~]# vim /etc/php.ini
session.save_handler = memcache
session.save_path = "tcp://172.18.20.58:11211?persistent=1&weight=1&timeout=1&retry_interval=15"
#新建php测试页面
[root@php ~]# cd /var/www/html/
[root@php html]# cat test.php
<?php
$mem = new Memcache;
$mem->connect("172.18.250.58", 11211); #这里设置memcached服务器的IP与Port
$mem->set('hello', 'hello world', 0, 60);
$val = $mem->get('hello');
echo $val;
#启动服务:
[root@php ~]# systemctl start httpd
[root@php ~]# systemctl start php-fpm

页面访问httpd服务,若浏览器显示”hello world”则表示可以正常使用memcached服务。

登录memcached服务确认下:

1
2
3
4
5
6
7
8
9
10
11
12
[root@localhost ~]# telnet 172.18.250.58 11211
Trying 172.18.250.58...
Connected to 172.18.250.58.
Escape character is '^]'.
stats
....省略部分输出
STAT cmd_get 45
STAT cmd_set 45
......
STAT get_hits 45
STAT get_misses 0
....省略部分输出

后记:

到此,将php程序部署到httpd服务器上,即可将session保存到memcached服务器了。另外如果需要memcached工具程序,可以安装libmemcached程序。

php.ini中memcache配置项总结

memcache.allow_failover boolean
是否在发生错误时(对用户)透明的转移到其他服务器。默认“1”

memcache.max_failover_attempts integer
定义在写入和获取数据时最多尝试的服务器次数(即:故障转移最大尝试数),仅和 memcache.allow_failover结合使用。默认“20”

memcache.chunk_size integer
数据传输块大小,这个值越小网络I/O次数越多,如果发现莫名的速度降低, 可以尝试将此值调至32768。默认“8912”

memcache.default_port string
在尝试连接memcache的时候如果没有单独指定端口默认使用的TCP端口号,默认为“11211”

memcache.hash_strategy string
控制key到服务器的映射(分布式)策略。值 consistent(一致性hash算法)允许服务器增减而不会(大量)导致健的重新映射 (译注:参见http://tech.idv2.com/2008/07/24/memcached-004/),设置为 standard则使用余数方式进行key的映射。默认“standard”

memcache.hash_function string
控制在key-server映射时使用哪个hash函数。crc32 标明使用标准CRC32进行hash,fnv则说明使用FNV-1a。FNV-1a比CRC32速度稍低,但是散列效果更好。默认“crc32”

session.save_handler string
当值为memcache时标记使用memcache作为session处理器。默认“files”

session.save_path string
定义一个逗号分割的用于session存储的服务器url列表,例如: “tcp://host1:11211, tcp://host2:11211”。默认“”
每个url可以包含参数,这些参数于方法Memcache::addServer()的参数相同。比如: “tcp://host1:11211?persistent=1&weight=1&timeout=1&retry_interval=15”,可配置持久连接、权重、超时时长、重试间隔。

对于各参数需求的memcache(注意不是memcached)版本要求请参考PHP官方文档:http://php.net/manual/zh/memcache.ini.php

http协议回顾

http协议为应用层协议,其本身是statelss(无状态跟踪)。为了能够让服务端能够识别客户端,防止反复进行身份认证,会在客户端留下cookie文件,而服务端可以使用session关联至客户端。

默认情况下,客户端每一个http资源(一个页面会包含多个资源)请求都需要进行tcp三次握手四次断开,浪费了大量资源,为了解决这一问题,可以在服务端打开keepalive

http事务:

即完整的一次请求与响应过程。

request:请求报文

1
2
3
<headers> ... #可以有多个
#空行
<entity-body> #数据部分,可能为空

response:响应报文

1
2
3
<headers> ... #可以有多个
#空行
<entity-body> #数据部分

常用method(请求方法):

GETHEADPUTPOSTDELETETRACEOPTIONS

version格式:

1
HTTP/major.minor  #如HTTP/1.21

status code:

|分类|常见状态码
|——-|——————–|——————|———————|
|2xx|200:OK| | |
|3xx|301:永久重定向|302:临时重定向|304:未重定向|
|4xx|401:Unauthorized|403:Forbidden|404:Not found|
|5xx|500:Internal Server Error|502:Bad Gateway| |

I/O模型

IO models.PNG

应用程序调用内核(system call)访问存储设备中的数据,数据会先①由内核从存储设备加载至内核空间;然后再②从内核空间复制到用户空间。

同步/异步:关注的是消息通知机制

同步:synchronous

调用者等待被调用者返回消息;

异步:asynchronous

被调用者通过状态、通知或回调通知调用者;

阻塞/非阻塞:关注的是调用者在结果返回之前所处的状态

阻塞:block

调用结果返回前,调用者会被挂起;

非阻塞:nonblock

调用结果返回前,调用者不会被挂起,可继续处理其他任务;

I/O类型:

网络IO:本质是socket存取;

磁盘IO:本质是数据流;

无论网络IO还是磁盘IO,都会经过上面①②两个步骤。

I/O模型:

同步阻塞:blocking

在整个过程等待内核操作完成,并且被挂起,不能处理其他任务;

同步非阻塞:nonblocking

在①步骤主动检查内核是否准备好数据,非阻塞状态,在第②步骤仍然被阻塞;

I/O复用:I/O multiplexing

单个进程同时管理跟踪多个sock,在不同时间片跟踪在不同sock上;

常见系统调用:select、poll、epoll(linux独有)、kqueue(BSD上对epoll的实现)等

信号驱动I/O:singnal driven I/O

数据准备好(可从内核空间复制到进程空间),内核发出信号通知进程;

异步I/O:asynchronous I/O

数据准备完成(已完成内核空间复制到进程空间),内核发出信号通知进程;

nginx简介

官方站点:nginx.org

nginx是一个免费、开源、高性能的http和反向代理服务器

次版本号为偶数时,为稳定版。如1.8.x等。

特征:

高度模块化设计,较好扩展性

高可靠性

基于master/worker模型

支持热部署

不停机更新配置文件、更换日志文件、更新服务程序版本

低内存消耗

1w个keep-alive连接模式下的非活动连接仅消耗2.5M内存

event-drivenaiommap

基本功能:

静态资源web服务器

虚拟主机、keepalive、访问日志、url rewrite、路径别名、基于IP与用户的访问控制、支持速率限制及并发数限制等

http协议反向代理服务器

pop3/imap4协议反向代理服务器

FastCGI(LNMP),uwsgi等协议

模块化(非DSO),著名的有zip,SSL等

nginx程序架构:

2016-04-29 11-00-55屏幕截图.png

master/worker模型

master进程:仅有一个。加载配置文件、管理worker进程、平滑升级等

worker进程:可有多个。通过事件驱动机制,并发响应http服务、http代理、fcgi代理等。通过IO多路复用完成cache loader与cache manager。

模块类型

core module

standard module

standard HTTP modules

optional HTTP modules

mail modules

3rd party modules

nginx配置

官方源目前并没有收录nginx,所以需要使用epel源来安装

编译安装:

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
[root@ns1 ~]# yum groupinstall "Development Tools" "Server Platform Development"
 #需要单独安装部分软件开发包,以支持重写、https、压缩
[root@ns1 ~]# yum -y install pcre-devel openssl-devel zlib-devel
 #获取源码包并解压
[root@ns1 ~]# wget 
[root@ns1 ~]# tar -xzf nginx-1.8.1.tar.gz
[root@ns1 ~]# cd nginx-1.8.1/
 #官方configure选项
./configure 
--prefix=/usr/local
--sbin-path=/usr/sbin/nginx
--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 #当客户端请求报文的body部分太大,内存容量难以胜任时,使用磁盘目录临时存放
--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-http_ssl_module  #https相关
--with-http_realip_module
--with-http_addition_module
--with-http_sub_module
--with-http_dav_module
--with-http_flv_module
--with-http_mp4_module
--with-http_gunzip_module
--with-http_gzip_static_module
--with-http_random_index_module
--with-http_secure_link_module
--with-http_stub_status_module  #nginx状态信息页面。很多时候需要脚本调用页面输出信息来分析nginx状态
--with-http_auth_request_module  #认证请求相关
--with-threads
--with-stream
--with-stream_ssl_module
--with-http_slice_module
--with-file-aio
--with-http_v2_module
--with-debug  #如果需要开启debug级别的日志记录信息,需要此条目
[root@ns1 nginx-1.8.1]# make -j 4; make install

自带管理工具:

nginx -t 检查配置文件语法

nginx 启动服务

nginx -s {reload|stop|quit} 重新加载配置文件、平滑终止服务、立即停止服务

配置文件:

主配置文件:conf/nginx.conf

建议可以添加”include conf.d/*.conf”以使子配置文件生效,子配置文件及目录需手动创建。

其他配置文件:

fastcgi、scgi、uwsgi等相关配置

mime.types 定义了文件类型

配置指令(必须以分号结尾)

directive value1 [value2 ...];

支持使用变量:

内置变量:模块引入,可直接调用;

自定义变量:set VAR value;

引用变量:$VAR_NAME

配置详解:

参考官方站点:http://nginx.org/en/docs/

main block:全局配置

[toggle Title=展开全局配置条目]

正常运行必背
1
2
3
user USERNAME [GROUPNAME];  #指定运行worker进程的用户和组
pid FILE;  #pid文件路径
worker_rlimit_nofile NUMBER;  #单个worker进程能够打开的最大文件数
性能优化相关
1
2
3
4
worker_processes  NUMBER|auto;  #worker进程数量(通常应设置为CPU核心数-1,给系统运行留一个核心),最好将worker绑定到特定cpu核心。auto值在1.8版本以后可用
worker_cpu_affinity CPUMASK ...;  #绑定worker到特定cpu。这里的CPUMASK为cpu掩码。如4核心cpu则掩码有0001/0010/0100/1000
worker_cpu_affinity auto [CPUMASK];
worker_priority NICE;  #调整worker的nice值。取值范围[-20,19]
调试、定位问题相关
1
2
3
4
5
6
7
8
daemon on|off;  #是否以守护进程方式启动,守护进程方式会放入后台(默认是daemon方式)。调试时设置off。这样就可以在前台显示错误信息了
master_process on | off;  #是否以master/worker模型启动。正常启动应设置为on,默认方式为on,调试设置为off。
error_log file | stderr | syslog:server=address[,parameter=value] | memory:size [debug | info | notice | warn | error | crit | alert | emerg];  #错误日志文件的记录方式,及其日志级别
    file /LOG_FILE;
    stderr  发送到标准错误输出
    syslog:server=address[,parameter=value]  发送到syslog服务器
    memory:size 
    日志级别:debug级别需要在configure的时候指明--with-debug选项

事件驱动相关:

1
2
3
4
5
events {
worker_connections  1024;  #设置单个worker进程最大并发连接数。注意还受限于worker_rlimit_nofile(单个worker能够打开的最大文件数)设置
use METHOD;  #可选参数有{select|poll|kqueue|epoll|/dev/poll},但对linux来说,可用的仅由epoll
accept_mutex on|off;  #是否打开轮训响应,默认开启。打开后,worker会轮训响应新连接
}

http协议相关:

1
http {
套接字相关:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
server {
    #配置listen、server_name、root等条目
    ...
}  #设置虚拟主机,可以有多个
listen address[:port] [default_server] [ssl] [backlog=number] [rcvbuf=size] [sndbuf=size];  #配置监听IP与端口
listen port [default_server] [ssl];
listen unix:path [default_server] [ssl];  #监听到unix socket上,仅用于本机不同进程间通讯
    default_server  #设置为默认虚拟主机
    ssl  #使用https
    backlog  #后缓队列长度
    rcvbuf  #接受缓冲区大小
    sndbuf  #发送缓冲区大小
server_name name ...;  #服务名,可用空格分隔多个
    支持使用通配符(*符号)和正则表达式(以~开头来标识)来表示
        server_name www.systemd.cn;
        server_name *.systemd.cn;
        server_name www.systemd.*;
        server_name ~^.*\.systemd\..*$;
    匹配次序:
        精确匹配 --> 左侧*通配 --> 右侧*通配 --> 正则模式匹配
tcp_nodelay  on|off;  #在keepalive打开的前提下,延时发送。(多个小资源会组合成一个大数据包后发送,节约了带宽,但会降低客户端体验)
sendfile on | off;  #是否开启sendfile功能。开启后响应报文直接由内核封装后发出,即省略了内核转发给nginx进程 --> nginx进程封装响应报文再传递给内核步骤
路径相关:
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
root PATH;  #定义web资源路径,注意相对路径与绝对路径。可定义在http、server、location(推荐)、if in localtion语句内
    如定义在location内,则表示在location定义的目录的子目录
location [ = | ^~ | ~ | ~* ] uri {
    ...
}  #对用户请求资源的不同路径(类型)进行匹配,从而进行不同设定
    =  #uri精确匹配
    ^~  #锚定uri的左半部分做匹配检查
    ~  #做正则模式匹配,区分大小写
    ~*  #做正则模式匹配,不区分大小写
    匹配优先级:=  ^=  ~/~*  无符号
    注意:当本location中定义了root路径时,location后跟的uri是相对此路径的。未定义时,继承上级root的定义。
location @name {
    ...
}
alias PATH;  #定义链接路径。仅使用在location中。不能与root一起使用!
    如:
    localtion /bbs/ {
alias /www/web/vhost1/; 将uri "/bbs/"映射到系统路径"/www/web/vhost1/"
    }  #用户访问http://IP/bbs/会被映射到系统路径/www/web/vhost1/
index file ...;  #设置主页文件,可设置在http,server,location
error_page code ... [=[response]] uri;  #错误重定向。
    如:
    error_page 404 = 200 /404.html;  #将不存在的页面重定向到404.html,并将网页状态码修改为200。
try_files file ... uri;  #依次尝试显示不同资源,直到找到资源。应定义在server或location中。
try_files file ... =code;
客户端请求的相关
1
2
3
4
5
6
7
8
9
keepalive_timeout timeout [header_timeout];  #保持连接超时时长。0表示禁止长连接;默认75s
keepalive_requests NUMBER;  #在一次长连接允许请求的最大资源数,默认为100
keepalive_disable none | browser ...;  #对那种浏览器关闭keepalive功能
send_timeout time;  #发送响应报文的超时时长。特指服务端响应报文距客户端下次请求报文的时间差。默认60s
client_body_buffer_size size;  #接收客户端请求报文body部分缓冲区大小;默认16k,超过此大小则被暂存到磁盘上client_body_temp_path指定目录
client_body_temp_path path [level1 [level2 [level3]]];  #设定存储客户端请求报文的body部分的临时存储路径及子目录结构和数量。level为数字
    如:
    client_body_temp_path /var/tmp/nginx/body/ 1 2
    则表示在/var/tmp/nginx/body/目录下,会随机创建1位16进制字符子目录(文件名随机0-f);而在子目录下,随机创建2位16进制字符的子目录(文件名随机00-ff)
客户端请求限制:
1
2
3
4
5
6
7
8
9
limit_rate rate;  #限制响应给客户端的传输速率,单位bytes/s,0表示无限制
limit_except method ... { ... };  #限制客户端使用除特定方法之外的其他方法。仅在location中配置
    如:
    location /admin/ {
        limit_except GAT POST {
            allow 172.18.0.0/16;
            deny all;
        }
    }  #仅允许172.18.0.0/16网段使用除GAT、POST之外的其他方法,其他仅能使用GAT、POST这两种方法
文件操作优化:
1
2
3
4
5
6
7
aio on | off | threads[=pool];  #是否启用aio功能(异步IO)
directio size | off;  #当文件大小大于设定的size后,会启动directio
open_file_cache off|on;  #文件缓存功能是否开启
open_file_cache max=N [inactive=time];  #设置文件缓存项上限,达到上限则使用LRU算法(最近最少使用)实现缓存管理;设置缓存过期时长,即设置LRU算法中的最近是多少时长
open_file_cache_errors on | off;  #是否缓存请求错误的文件信息
open_file_cache_min_uses number;  #最近最少使用标准,即LRU算法中最少使用次数。小于此number会被认为是非活动项
open_file_cache_valid time;  #缓存项有效性的检查频率。默认为60s

ip访问控制:依赖ngx_http_access_module

1
2
allow address |CIDR | unix: |all;  #允许特定客户端访问,可在http, server, location, limit_except配置。多条自上而下直到匹配上,所以一般在随后一条设置默认策略
deny address |CIDR | unix: |all;  #进制特定客户端访问

basic认证机制:依赖ngx_http_auth_basic_module

1
2
3
4
5
6
7
auth_basic string | off;  #启用basic认证的系统提示字符,或设置关闭basic认证
auth_basic_user_file file;  #认证文件
    文件格式:
        明文:username:password:注释
        密文:htpasswd命令生成
            htpasswd -c -m /FILE username  #第一次生成认证文件并添加第一个用户
            htpasswd -m /FILE username  #存在认证文件,添加新用户

nginx基本状态信息:依赖ngx_http_stub_status_module

1
2
3
4
5
Active connections: 3   #处于活动状态的客户端连接数量
server accepts handled requests
 157 157 300      #已接收客户端连接总数,已处理完成的客户端请求总数,客户端总请求数
Reading: 0 Writing: 1 Waiting: 2  
#处于读取客户端请求报文首部的连接数,处于向客户端发送响应报文过程的连接数,处于等待客户端发出请求的空闲连接数(当这个值太大时,可能是由于keep-lived设置超时时长太长导致)

限制请求报文referer(防盗链):依赖ngx_http_referer_module

1
2
3
4
5
6
7
8
9
10
11
12
13
valid_referers none | blocked | server_names | STRING ...;  #匹配请求报文referer字段(由何链接跳转到本链接)
    none:请求报文不包含referer字段
    blocked:请求报文包含referer字段,但没有值
    server_names:域名匹配,server_name后跟域名匹配。可使用正则(以~开头)、通配符(*)进行匹配。
    STRING:子定义字符串。可使用正则(以~开头)、通配符(*)进行匹配。
    注意:匹配不到的会自动存放到$invalid_referer内置变量中
    如:
    location ~.*\.(gif|jpg|png|swf|flv)$ {
        valid_referers none blocked server_name *systemd.cn ~.*linux.*;
        if ($invalid_referer) {
            return 404;
        }
    }  #对本站特定格式图片资源,匹配请求报文referer字段为空或没有值或来自systemd.cn域名或包含linux字符;对匹配不到的请求报文回应404。即仅允许特定站点引用本站图片资源。

https:依赖ngx_http_ssl_module

ssl:Secure SocketLayer HTTPS(Hyper TextTransfer Protocol over Secure Socket Layer)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ssl on | off;  #是否启用当前虚拟主机ssl功能
ssl_certificate file;  #当前虚拟主机pem格式证书文件
ssl_certificate_key file;  #当前虚拟主机pem格式私钥文件
ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2];  #ssl协议版本
ssl_session_cache off | none | [builtin[:size]] [shared:name:size];  #ssl会话缓存机制。
    off:关闭
    none:(默认值)优雅的告诉客户端可能不支持缓存机制
    builtin:使用openssl内建的缓存机制,各worker独立不共享缓存数据
    shared:各worker共享缓存数据。
        name:缓存空间名称;
        size:每1MB内存可以存储4000个session,根据需要调整size
builtin与shared可同时使用:
如:
ssl_session_cache builtin 1024 shared ssl-session-sharecache 10M;
ssl_verify_client;  #验证客户端证书,一般不需要此条目
ssl_ciphers CIPHPERS;  #指定ssl加密算法
ssl_session_timeout TIME;  #会话超时时长,指ssl_session_cache中缓存条目有效时长

日志:依赖ngx_http_log_module

1
2
3
4
5
6
7
8
9
10
11
12
13
access_log path [format [buffer=size [flush=time]] [if=condition]];
access_log path format gzip[=level] [buffer=size] [flush=time] [if=condition];
access_log syslog:server=address[,parameter=value] [format [if=condition]];
  #上面3条的format为log_format条目中的NAME,即引用特定格式
  flush:设置刷写到磁盘的时长。即多久将数据写入磁盘
access_log off;
log_format name string ...;  #设置日志格式。使用内建变量进行标识STRING字段。如$time_local表示本地时间
open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];  #启用日志缓存
    max:最大缓存条目,默认10个。会使用LRU(最近最少访问)算法自动计算。
    inactive:非活动时长
    min_uses:最少使用次数。小于此次数被认为非活动
    valid:验证缓存条目有效性的频率
open_log_file_cache off;

资源重定向:依赖ngx_http_rewrite_module

将客户端对某资源的请求重定向到另一个资源,将新资源响应给客户端。

首先需要明白一点,同一个location内的如果有多条rewrite条目,那么在未匹配到最终结果之前,会循环匹配。

如:

c –> d

a –> b

b –> c

客户端请求a资源时,a –> b –> c –>d,因为d没有rewrite条目了,所以返回最终结果d给客户端。使用flag可控制这种默认循环过程。

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
rewrite regex replacement [flag];  #将regex能匹配到的客户端请求uri,注意是uri,而不是url,替换为replacement字符串。
    注意!regex为正则表达式,replacement为普通字符串。多个rewrite条目会逐个检查,flag用以控制检查方式。
    如:
    rewrite (.*)admin\.html $1a.html;
    rewrite ^\/admin\/admin\.html /admin/a.html last;
    flag取值:
        last  #匹配到此条,不再继续下面条目的匹配,跳到此location第1条rewrite条目开始下一轮匹配。类似shell脚本中的continue。
        break  #匹配到此条,返回客户端新的uri,由客户端浏览器主动发起对新uri的资源请求(不需要用户参与)。类似shell脚本中的break。
        redirect  #返回状态码为临时重定向,与break类似,但返回状态码为302。
        permanent  #返回状态码为永久重定向,与break类似,但返回状态码为301。
rewrite_log on | off;  #是否启用重写日志。开启后,日志信息会被发往错误日志
if (condition) { ... };  #条件判断,当满足condition时,执行语句块中操作。
    condition可以是比较表达式、文件目录存在性判断
        ==, !=
        ~  模式匹配,区分字母大小写;
        ~*   模式匹配,不区分字符大小写;
        !~   模式不匹配,区分字母大小写;
        !~*  模式不匹配,不区分字母大小写;
        -f, !-f  是/不是文件
        -d, !-d  是/不是目录
        -e, !-e  存在/不存在
        -x, !-x  可执行/不可执行
return code [text];  #rewrite匹配不到时,返回给客户端响应码及文本信息
return code URL;
return URL;
set $variable value;  #设置用户自定义变量

资源压缩:依赖ngx_http_gzip_module

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
gzip on | off;  #启用或禁用gzip压缩响应报文;
gzip_comp_level level;  #指定压缩比,1-9,默认为1;
gzip_disable regex ...;  #regex是匹配客户端浏览器类型的模式,表示对所有匹配到的浏览器不执行压缩响应;
gzip_min_length length;  #触发启用压缩功能的响应报文的最小长度;
gzip_http_version 1.0 | 1.1;  #设定启用压缩响应功能时,协议的最小版本;
gzip_types mime-type ...;  #指定仅执行压缩的资源内容类型;默认为text/html;
gzip_proxied off | expired | no-cache | no-store | private | no_last_modified | no_etag | auth | any ...;  #作为代理服务器时,对何种类型报文进行压缩
    如:expired:响应报文包含"Expired"项并有值(设置报文过期时长),则启用压缩
    实例:
    gzip on;
    gzip_http_version 1.0;
    gzip_comp_level 6;
    gzip_disable msie6;
    gzip_min_length 2;
    gzip_types text/plain text/css text/xml application/x-javascript  application/xml  application/json application/java-script;

fastcgi:依赖ngx_http_fastcgi_module

fastcgi中会将匹配到的uri放入到$fastcgi_script_name变量中。如访问http://IP/zbog/index.php。$fastcgi_script_name内容为/zbog/index.php。所以在设定fastcgi_param时候需要特别注意。

最好保证root设定的文档目录与fastcgi_param中$fastcgi_script_name之前的路径一致。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#定义在一个location内
location ~ \.php$ {
    root html;
    fastcgi_pass 127.0.0.1:9000;  #php-fpm主机地址及端口
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /usr/local/nginx/html/$fastcgi_script_name;  #将nginx匹配到的请求资源映射到php-fpm的路径
    include fastcgi_params;  #指明子配置文件
}
fastcgi_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];
    path:文件系统路径,用于存储缓存的文件数据;
    max_size=size:定义此路径下的多大空间用于存储缓存数据;
    levels=#[:#[:#]]:缓存目录层级定义;
        levels=1:2
    keys_zone=name:size
        内存中用于缓存k/v映射关系的空间名称及大小;
    inactive=time
    注意:只能定义在http上下文。
fastcgi_cache zone | off;  #是否启用cache,如果启用,数据缓存于哪个cache中。ZONE为fastcgi_cache_path中设置的keys_zone名称。
fastcgi_cache_key string;  #定义要使用的缓存键;
    如: fastcgi_cache_key  $request_uri;
fastcgi_cache_methods GET | HEAD | POST ...;  #缓存哪些类型的请求的相关数据;
fastcgi_cache_min_uses number;  #最近最少使用量,少于此值被认为非活动
fastcgi_cache_valid [code ...] time;  #对不同响应码设定其可缓存时长

proxy:ngx_http_proxy_module(反代+缓存)

代理服务器会拆解所有封装,然后重新封装。所以其能够添加的规则/限制条件会很多;由于其工作在应用层,所以受限于能够打开的socket数量,故仅适用于并发请求不太多的情况。所以nginx通常用作反代服务器,后端使用apache。

正向代理:类似SNAT,在用户空间对远程server上资源转发给Client(常伴随着缓存)

反向代理:类似DNAT,作为前端主机。

涉及到与Client的会话保持、keepalive、延时发送;与后端Server的会话保持、keepalive。

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
28
29
30
31
32
proxy_pass URL;  #将location匹配到的/uri转发到URL/uri
proxy_pass URL/; #将location匹配到的/uri转发到URL/
#↑↑ 可应用在location,if in location,limit_except
#自定义的upstream NAME调用方法:proxy_pass http://NAME
#注意URL带"/"与不带意义不同:
location /uri/ {
proxy_pass http://b.com/new_uri/;
#表示:http://a.com/bbs/ --> http://b.com/new_uri/
proxy_pass http://b.com/new_uri;
#表示:http://a.com/bbs/ --> http://b.com/new_uri/bbs
}

proxy_set_header FIELD VALUE; #设定向后端主机发送的请求报文的首部及其值。
#实现后端主机日志记录真正访问的Client IP,而不是代理服务器的:
proxy_set_header X-Client-IP $remote_addr; #自定义变量传递给后端主机
#修改后端apache Server: 获取传递过来的自定义变量
LogFormat:LogFormat "%{X-Client-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

#缓存相关选项(缓存要先定义,后调用)
#内存中缓存的key-value: url -> 内容校验码
#磁盘缓存目录: 文件名即为资源的校验码
proxy_cache_path path [levels=levels] keys_zone=name:size [inactive=time] [max_size=size] ; #指明缓存路径,目录结构,仅定义在http内
proxy_cache zone|off; #调用上面定义的key_zone
proxy_cache_key string; #定义缓存键,一般定义为uri,
#如 proxy_cache_key $request_uri;
proxy_cache_key $scheme$proxy_host$request_uri
proxy_cache_valid [code ...] time; #为不同的响应码设定其缓存时长,不指定则不缓存。
#如 proxy_cache_valid 200 302 10m;
proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | off ...; #当代理服务器与后端服务器连接发生错误时,使用代理服务器上缓存资源回应客户端。
proxy_connect_timeout TIME; #与后端服务器建立链接的超时时长,默认60s,最长75s
proxy_read_timeout TIME; #等待后端主机响应报文的超时时长,默认60s
proxy_send_timeout TIME; #向后端主机发送请求报文的超时时长,默认60s

首部管理:ngx_http_headers_module

为响应给Client的报文中添加/修改首部信息

1
2
3
4
5
add_header name value [always];   #向响应报文添加自定义首部,并赋值
#如:add_header X-Via $server_addr;

expires [modified] time;
expires epoch | max | off; #用于添加Expire及Cache-Control首部或修改首部的值;

服务器组:ngx_http_upstream_module

将多个后端主机定义为服务器组,而后可由proxy_pass, fastcgi_pass, memcached_pass等进行引用;同样使用NAME来调用。

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
upstream NAME {   #定义后端服务器组;引入新的上下文;只能用于http上下文
server address [parameters]; #定义服务器的地址和相关的参数
# address格式:
# IP[:port]
# HOSTNAME[:port]
# unix:/PATH/TO/SOME_SOCK_FILE
# parameters格式:
# weight=number #服务器权重
# max_fails=number #最大失败尝试次数
# fail_timeout=time #设置服务器不可用超时时长
# backup #备用主机
# down #手动标记其不再处理任何用户请求

ip_hash; #使用源地址哈希算法(Client地址)
least_conn; #最少连接算法
keepalive CONNECTIONS; #与后端主机的最少连接,通常后端有多少主机设置几个。
}

health_check [parameters]; #定义后端主机健康监测。仅用在location上下文,nginx2.0及以上版本才支持。
# 可用参数:
interval=NUMBER 监测频度,默认5s
fails=NUMBER 判定为失败的检测次数
passes=NUMBER 判定为成功的检测次数
uri=uri 执行健康检测时请求的uri
match=NAME 基于哪个match做健康检测
port=NUMBER 向服务器的那个port发起健康检测

match name { ... } #仅能用于http上下文 ;对后端主机做健康状态检测时,定义其结果判断标准
status:期望的响应码;
status CODE
status ! CODE
status CODE-CODE
header:基于响应首部进行判断
header HEADER=VALUE
header HEADER!=VALUE
header [!] HEADER
header HEADER ~ VALUE
body:期望的响应报文的主体部分应该有的内容;
body ~ "CONTENT"
body !~ "CONTENT"

hash key [consistent]; #定义调度方法,可自定义基于何种信息(key)进行绑定
# 如:
hash $remote_addr #定义绑定远程Client IP进行调度。较粗糙,同一公网地址的Client无法会被调度到同一后端主机
hash $request_uri #根据uri,同一页面由后端同台主机进行响应
hash $cookie_username #根据cookie,最精细

补充:内置变量的调用,向客户端展示缓存命令与否:add_header X-Cache $upstream_cache_status;
}

mail相关

1
mail { ... }

ansible简介:

ansible is Simple IT Automation。

ansible是一个简单的自动化运维工具,能够轻松实现配置、命令管理等常见运维工作。另外,它是一种Python语言开发的agentless工具,通过ssh服务连接被管理端,不需要在被管理端额外安装监管程序。这也意味着ansible主机的安全至关重要。

阅读全文 »

DHCP服务及相关介绍:

DHCP服务实现将主机的网络参数进行动态分配,实现同一地址重复使用。

  • bootp:boot protocol(早期用在无盘工作站),在主机开机时分配IP地址信息,以便连接网络存储;主机开机后会一直拥有此地址。
  • dhcp:可理解为引入了“租约”的bootp。当某主机关机或主动释放地址后,可将此地址分配给其他主机使用。实现同一地址的反复使用。也可实现为特定主机保留固定地址。
  • arp:address resolving protocol,实现局域网内将IP解析为MAC。
  • rarp:reverse adress resolving protocol,实现局域网内将MAC解析为IP。

DHCP请求流程:

整个过程都是基于广播进行的。

  1. DHCP discover:客户端发送广播请求dhcp服务;
  2. DHCP offer:DHCP服务器响应客户端,并发送分配给此客户端的网络参数,包括IP、MASK、GW等。(当局域网有多台DHCP服务器时,客户端会使用最先收到的offer,收到offer广播的其他DHCP服务器将不再广播offer)
  3. DHCP request:客户端发送请求广播。
  4. DHCP ack:DHCP服务器发送确认信息。

DHCP续租流程:

整个过程都是基于单播/广播进行的。

  • 当客户端发现租约期限到50%时,向DHCP服务器发送续租请求。

  • 客户端得不到DHCP服务器响应,在租约期限到75%时,再次向DHCP服务器发送续租请求。

  • 客户端仍然得到不到DHCP服务器响应,在租约期限到87.5时,继续向DHCP服务器发送续租请求。

  • 客户端还是得不到DHCP服务器响应,广播请求(DHCP请求流程),寻找新的DHCP服务器。

  • 当客户端发现租约期限到50%时,向DHCP服务器发送续租请求。

  • DHCP服务器拒绝(DHCP nak),直接广播请求(DHCP请求流程),寻找新的DHCP服务器。

CentOS上DHCP安装配置:

CentOS上有两个软件包可以提供DHCP服务:

  • dhcp包:(ISC,named)
    dhcpd:dhcp服务
    dhcrelay:dhcp中继服务

  • dnsmasq包:同时提供dhcp和dns服务,轻量级软件,仅适用于少量客户机的。

监听端口:

  • Server端:67/udp
  • Client端:68/udp #仅在网卡在dhcp获取地址时自动启动并以守护进程运行。
安装与使用:
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
[root@dhcp ~]# yum -y install dhcp
[root@dhcp ~]# cp /usr/share/doc/dhcp-4.1.1/dhcpd.conf.sample /etc/dhcp/dhcpd.conf
#配置文件:/etc/dhcp/dhcpd.conf(注意以”;”结尾)
option domain-name "DOMAIN-NAME"; #指定域
option domain-name-servers IP,[IP],[IP]; #指定全局DNS(linux系统最多配置3个dns,windows最多2个)
option routers IP; #全局指定网关
default-lease-time 43200; #租期
max-lease-time 86400; #最长租期
filename “filename” ; #指明引导文件名称
next-server IP|FQDN;
subnet NET netmask MASK { #定义子网,可定义多个
range 开始IP 结束IP; #地址范围
option #仅本子网有效的选项
}
host HOST_ID { #定义mac绑定,可定义多个,建议使用主机名作为HOST_ID
hardware ethernet MAC;
fixed-address IP; #这里的绑定IP不要出现在subnet内
}
group {
filename "FILENAME"; #指明引导文件名称
next-server IP|FQDN; #指明引导文件所在的服务器主机IP
host HOST_ID1 {hardware ethernet MAC1;}
host HOST_ID2 {hardware ethernet MAC2;}
...
}

客户端使用:
dhclient -d #请求dhcp服务并在前端显示

查看已分配的地址:
/var/lib/dhcpd/dhcpd.leases

tftp server

监听在69/udp
安装:yum -y install tftp-server

以守护进程启动方式:
CentOS6:
chkconfig tftp on
service xinetd restart

CentOS7:
systemctl start tftp.socket
默认共享文件根目录:/var/lib/tftpboot/

PXE服务器配置

preboot excution environment,Intel主导开发
dhcp + tftp + http|ftp + kickstart来实现。

工作流程:

Client –> dhcp Server(获取网络参数、tftp文件服务器地址和网络引导文件目录)
Client –> tftp文件服务器(获取网络引导文件,一般为pxelinux.0),此处的pxelinux.0等同于grub引导程序
Client –>tftp文件服务器获取Kernel、initrd以及kickstart文件,内核启动
Client –> 安装程序(boot.msg,第一进程)启动。根据kickstart定义使用固定IP或再次向dhcp Server发送请求,获取网络参数。(前一次是引导程序获取的,在内核接管所有工作时就无效了;本次是内核获取,用以访问网络上的repo源)
Client –> 安装程序根据kickstart文件中的定义,进行自动化安装

CentOS6配置过程:

dhcp服务器

在正常工作的dhcp服务的基础上添加:

1
2
filename ”pxelinux.0”;
next-server tftp服务IP;
tftp服务器

安装syslinux软件以提供pxelinux.0等文件:

1
2
3
4
5
6
7
8
9
10
11
12
yum -y install syslinux
cp /media/cdrom/image/pxeboot/{vmlinuz,initrd.img} /var/lib/tftpboot/ #复制光盘内vmlinuz和initrd.img(务必于欲安装的系统版本一致):
cp /media/cdrom/isolinux/{boot.msg,vesamenu.c32,splash.png} /var/lib/tftpboot #复制安装框架
mkdir /var/lib/tftpboot/pxelinux.cfg/
cp /media/cdrom/isolinux/isolinux.cfg /var/lib/tftpboot/pxelinux.cfg/default #创建安装控制文件
vim /var/lib/tftpboot/pxelinux.cfg/default #修改控制文件自定义菜单
timeout 600 #默认菜单超时时间为60秒,建议修改
label linux
menu label ^Auto Install CentOS system
menu default
kernel vmlinuz
append initrd=initrd.img ks=http://192.168.31.42/ks.cfg #指明kickstart文件所在位置,可以是http、ftp
制作ks.cfg文件
1
2
3
4
5
6
yum -y install system-config-kickstart
system-config-kickstart运行程序并自行配置(需要图形化界面),完成后保存在/root/ks.cfg
注意:Basic Configuration --> Perform installation in interactive mode表示交互式安装,自动化安装不要勾选。
Installation Method -- Installation source选择http,填入
HTTP Server:192.168.31.42
HTTP Directory:/cdrom
构建repo源以及ks.cfg文件(这里用httpd来提供)
1
2
3
ln -sv /media/cdrom /var/www/html/cdrom
cp /root/ks.cfg /var/www/html/
service httpd start

CentOS 7配置过程:

与CentOS6配置过程一致,但需要注意在创建/var/lib/tftpboot/pxelinux.cfg/default文件是,需要指定为
menu default

自动安装小技巧:

上面的安装方法有一个最最让人苦恼的地方:不管是谁,只要在开机时使用了PXE启动,就会被自动化安装上新系统!太不安全了。

PXE实现为特定主机安装系统:

原理:仅为特定mac地址的设备指定filename,next-server。
将filename和next-server条目放入group{}内,而不是放到subnet或全局。

1
2
3
4
5
group {
filename "pxelinux.0";
next-server 192.168.31.42;
host test { hardware ethernet 00:0c:29:b0:a8:13; } #可以有多个
}

此时,不再列表中的主机,即使PXE启动,也不会获取到网络引导文件,自然不会被误伤了。

相关概念介绍:

http是应用层协议,依赖于传输层tcp协议进行传输。
互联网数字分配机构(IANA,The Internet Assigned Numbers Authority)规定了不同应用的端口使用范围:
0-1023:永久分配给固定应用使用,特权端口,只有管理员能够启动应用进行监听;
1024-41951: 注册端口,分配给某应用使用。
41952+: 客户端程序随机使用的端口,称之为动态端口或私有端口。其范围定义在/proc/sys/net/ipv4/ip_local_port_range文件中

BSD Socket:


BSD Socket是IPC(Inter-Process Communication,进程间通信)的一种实现,允许位于不同主机(或同一台主机)上的进程之间进行通信。

按照Socket API分类:(Socket API:封装了内核中socket通信相关的系统调用)

SOCK_STREAM:流式套接字,tcp套接字
SOCK_DGRAM:数据包式套接字,udp套接字
SOCK_RAW:原始套接字(实现于系统核心,除了处理普通的网络报文之外,还可以处理一些特殊协议报文以及操作IP层以及其以上的数据。)其有以下特征:
⇒ 可以处理ICMP、IGMP等网络报报文
端口对SOCK_RAW而言没有任何意义
⇒ 设置IP_HDRINCL选项后,SOCK_RAW可以操作IP头数据,以完成数据传输。接收报文也一样,内核不识别的IP报文会传递给SOCK_RAWW

根据Socket Domain分类:(Socket Domain:套接字所使用的格式)

AF_INET:Address Family,监听在IPv4地址上
AF_INET6:监听在IPv6地址上
AF_UNIX:用于同一主机上不同进程基于socket套接字通讯(如mysql就是通过这种方式,效率比前两者高),这样的socket叫做Unix_SOCK,其监听在”localhost”或”127.0.0.1”地址上。

TCP FSM:TCP有限状态机

TCP Finite State Machine,TCP有限状态机,3次握手 –已建立连接–> 4次断开的详细过程

TCP协议特征:

  • 面向连接的、可靠的传输层协议;
  • TCP协议建立在不可靠的网络层IP协议上,IP不能提供任何可靠机制,TCP的可靠性完全由自己实现;
  • 端到端的通信;
  • 全双工方式传输;(两条虚连接线路)

TCP采用的最基本的可靠性技术:

  • 将数据打包成段,计算校验和(CRC32)
  • 确认与超时重传
  • 排序,将完整数据包打包成段写入逻辑序号,以便恢复
  • 流量控制(即头部滑动窗口大小,window)
  • 拥塞控制,慢启动和拥塞避免算法

HTTP协议介绍:

http全称为hyper text transfer protocol,是一种应用层协议,默认80/tcp。
html:hyper text mark language,超文本标记语言

1
2
3
4
5
6
7
8
9
<html>
<head>
<title>
</title>
</head>
<body>
<a href="http://....">...</a>
</body>
</html>

css:Cascading Style Sheet,层叠样式表,能够控制html的输出样式
js:JavaScript,客户端脚本,通过客户端浏览器进行解析运行,可以实现动态功能

http协议版本:

http/0.9
http/1.0:引入了cache,MIME,method
MIME:Multipurpose Internet Mail Extesion,是一种邮件协议,引入到http协议后使http能够传输非文本数据
method:数据传输的请求方法(如提交表单用到的post方法,获取资源使用的get方法,其他还有head、put、delete、trace、options等)
http/1.1:增强了缓存功能
http/2.0:

http工作模式:

C/S架构,Server/Client
Client端发送http request(http请求报文)
Server端发送http response(http响应报文)
一次http request与http response的过程叫做一次http事务。

web resource(web 资源)分类:

静态资源
无需服务端做额外处理,如:.jpg .png .gif .html .txt .js .css .mp3 .avi等等

动态资源
服务端需要通过执行程序进行处理,发送给客户端程序的执行结果,如:.php .jsp等等

注意!一个页面中展示的资源一般有多个,而默认情况下,每一个资源的获取都需要单独请求,需要单独建立连接、断开连接,这也是为什么需要keepalived的原因。

保持连接(长连接):keepalived
保持客户端与服务器之间的连接,不是每个资源都进行tcp的三次握手四次断开。

非保持连接(短连接):
每个资源的都需要tcp的三次握手四次断开的步骤。(注意四次断开第3步服务器回应客户端断开请求后,不会立即请求与客户端断开,而是等待一段时间,而如果这段时间客户端再次请求了与服务端连接,则会继续使用此虚连接)

URL,资源标识符

Uniform Resource Locator,用于描述服务器某资源的位置
格式:Scheme://Server_IP[:Port][/PATH]
基本语法
<scheme>://<user>:<password>@<host>:<port>/<path><params>?<query>#<frag>
<params>:参数值传递。如:http://www.grub2.com/bbs/hello;gender=f
?<query>:查询语句使用到的变量值传递。如:http://www.grub2.com/bbs/search?username=tom&title=abc
#<frag>:传递本页锚定标识

类型
相对URL,一般在本地站点资源 的引用时使用,避免由于站点域名改变等而导致资源无法访问;
绝对URL,一般在其他站点资源的引用时使用。

HTTP协议特征 :

stateless:无状态追踪
在未设置”KeepAlive On”时,由于每个资源都需要经过tcp的”三次握手四次断开”,所以服务器无法持续追踪访问者来源,即不能判断不同请求是否由同一客户端发出。即使设置了”KeepAlive On”之后,由于”KeepAliveTimeout 15”的设置,服务器也不可能花费太多时间与一个客户端保持持久连接,而连接一旦断开,依旧无法分辨客户端是谁。而假如是需要登录才能访问的资源,这种情况将反复提示用户输入账号信息。

使用cookie识别客户端:
为了使服务器识别不同的客户端,服务端会在客户端留下一些记录信息,后续访问时,客户端将cookie信息发给服务端,服务器便能够识别了。

另外cookie还有胖cookie与瘦cookie的分别,胖cookie记录了用户的浏览记录等大量信息,而瘦cookie仅记录客户端标识信息,配合客户端的session来 保存用户信息。

服务端session:
关联至客户端cookie。动态网站用于保存客户端状态信息的。

HTTP事务:

http协议的一次请求与响应的过程。理解http事务及http报文语法格式,以便对报文进行分析后,进行不同的操作。
http request报文格式

1
2
3
4
<method><request-URL><version>
<headers> ...
空行
<entity-body>

常见method

1
2
3
4
5
6
7
8
#method   #请求方法,标明客户端希望服务器端对资源的执行动作
GET #从服务器获取一个资源;这时<entity-body>部分通常为空
HEAD #请求只从服务器获取资源响应首部,而不需要服务器端发送<entity-body>
POST #向服务器发送要处理的数据,而这些数据都是存放在<entity-body>中的
PUT #将请求的主体部分直接存储在服务器上,而不是交给服务器处理,数据在<entity-body>中。这时客户端应该对服务器有存取权限才行。
DELETE #请求删除服务器上的指定资源
TRACE #追踪请求报文到达服务器过程中经过的代理服务器
OPTIONS #请求服务器返回对指定资源支持使用的请求方法

可以使用telnet命令来模拟http request请求:

1
2
3
4
telnet IP Port
method /URL Version
Host:IP/FQDN
回车

http response报文格式

1
2
3
4
<version><status code><reason-phrase>
<headers> ...
空行
<entity-body>

version格式:
HTTP/<major>.<minor> #如:HTTP/1.1

status code:以三位数字标记请求过程状态码
1xx:
100-101:信息提示
2xx:
200-206:成功
3xx:
300-305:资源重定向
4xx:
400-415:客户端错误
5xx:
500-505:服务端错误


#常见状态码
200 #成功(OK)。请求数据已通过响应报文的entity-body发出。
301 #永久重定向(Moved Permanently)。请求的URL指定资源已被删除;但会通过响应报文的首部指明Location的值,以标明资源现在所处的新位置。
302 #临时重定向。与301类似,但通过响应报文首部指明的Location的值指明的是资源的临时新位置。
304 #客户端发出条件式请求请求获取资源是否发生过修改,而服务器上的资源未发生改变的响应。
401 #需要认证(Unauthorized)。资源存在,需要客户端提供认证信息。
403 #请求被禁止(Forbidden)。权限不足
404 #资源找不到(Not Found)。
500 #服务器内部错误(Internal Server Error)。
502 #代理服务器从后端服务器收到了一条伪响应(Bad Gateway)。

reason-phrase:状态码所标记状态的简短描述

如:200 –> OK 404 –> NOT FOUND

headers:

每个请求/响应报文可包含0或多个headers。每个headers都有名称,后跟冒号 可选空格 值。(多个值空格隔开)

常见首部:

#通用首部
#可以用在请求/相应报文首部
Date #报文创建时间
Connection #连接状态,如keep-alive、close
Via #报文经过的中间节点
Cache-Control #控制缓存
Pragma #与http1.0兼容的控制缓存相关

#请求首部
#仅可以用在请求报文首部
Accept #可接收媒体类型
Accept-Charset #可接收编码格式
Accept-Encoding #可接收编码格式,如gzip
Accept-Language #可接收的语言
Client-IP #客户端IP
Host #请求的服务器名称和端口号
Referer #当前请求资源的上级资源,常用来分析网站入口来源
User-Agent #客户端代理,即浏览器类型,可通过此条显示不同网页给客户端

#条件式请求首部   #
  Expect   #期望发送的信息
  If-Modified-Since   #指定时间至今,请求的资源是否发生过修改。
  If-Unmodified-Since   #
  If-None-Match   #本地缓存中存储的资源Etag标签是否不匹配服务器中的资源Etag标签。
  If-Match   #

#安全请求首部   #
  Authorization   #向服务器发送认证信息,如账号密码
  Cookie   #客户端向服务器发送cookie
  Cookie2   #

#代理请求首部   #
  Proxy-Authorization   #向代理服务器认证

#响应首部
#信息类 #
Age #相应持续时长
Server #服务程序名称及版本

#协商首部 #
当某资源有多种表示方法时使用
Accept-Ranges #服务器可接收的请求类型范围
Vary #服务器查看的其他首部列表

#安全响应首部 #
Set-Cookie #向客户端设置cookie
Set-Cookie2 #
WWW-Authenticate #服务端对客户端的质询认证表单

#实体首部
#描述<entity-body>部分
Allow #列出对此资源可使用的请求方法
Location #回应客户端真正的实体位置
Content-Encoding #资源编码格式
Content-Language #
Content-Length #
Content-Location #资源真正的实体位置,与Location一样
Content-Type #返回格式为 major/minor

#缓存相关 #
Etag #资源扩展标签
Expires #资源过期时间
Last-Modified #最后修改时间

#扩展首部

entity-body:

真正的数据部分,可能为空。如请求方法为GAT时,通常都为空。