本章內容
Nginx介紹
Nginx安裝
Nginx各種模塊
實驗:實現LNMP
性能影響
有很多研究都表明,性能對用戶的行爲有很大的影響:
79%的用戶表示不太可能再次打開一個緩慢的網站
47%的用戶期望網頁能在2秒鐘以內加載
40%的用戶表示如果加載時間超過三秒鐘,就會放棄這個網站
頁面加載時間延遲一秒可能導致轉換損失7%,頁面瀏覽量減少11%
8秒定律:用戶訪問一個網站時,如果等待網頁打開的時間超過8秒,會有超過30%的用戶放棄等待
用戶速度體驗的1-3-10原則:
Httpd MPM
httpd MPM:
prefork:進程模型,兩級結構,主進程master負責生成子進程,每個子進程負責響應一個請求
worker:線程模型,三級結構,主進程master負責生成子進程,每個子進程負責生成多個線程,每個線程響應一個請求
event:線程模型,三級結構,主進程master負責生成子進程,每個子進程響應多個請求
Nginx介紹
Nginx:engine X ,2002年,開源,商業版
NGINX是免費,開源,高性能的HTTP和反向代理服務器,郵件代理服務器,通用TCP/UDP代理服務器
解決C10K問題(10K Connections)
官網:http://nginx.org
二次開發版:
Tengine, OpenResty(章亦春)
正向代理和反向代理
Nginx介紹
特性:
模塊化設計,較好的擴展性
高可靠性
支持熱部署:不停機更新配置文件,升級版本,更換日誌文件
低內存消耗:10000個keep-alive連接模式下的非活動連接,僅需2.5M內存
event-driven,aio,mmap,sendfile
基本功能:
靜態資源的web服務器 #重點掌握
http協議反向代理服務器 #重點掌握
pop3/imap4協議反向代理服務器
FastCGI(LNMP),uWSGI(python)等協議
模塊化(非DSO),如zip,SSL模塊
nginx的程序架構
web服務相關的功能:
虛擬主機(server)
支持 keep-alive 和管道連接
訪問日誌(支持基於日誌緩衝提高其性能)
url rewrite
路徑別名
基於IP及用戶的訪問控制
支持速率限制及併發數限制
重新配置和在線升級而無須中斷客戶的工作進程
Memcached 的 GET 接口
nginx架構
nginx支持epoll,apache使用select
nginx的程序架構
nginx的程序架構:
master/worker結構
一個master進程:
負載加載和分析配置文件、管理worker進程、平滑升級
一個或多個worker進程
處理並響應用戶請求
緩存相關的進程:
cache loader:載入緩存對象
cache manager:管理緩存對象
nginx模塊
nginx高度模塊化,但其模塊早期不支持DSO機制;1.9.11版本之後支持動態裝載和卸載
模塊分類:
核心模塊:core module
標準模塊:
•HTTP 模塊: ngx_http_*
HTTP Core modules 默認功能
HTTP Optional modules 需編譯時指定
•Mail 模塊 ngx_mail_*
•Stream 模塊 ngx_stream_*
第三方模塊
nginx的功用
靜態的web資源服務器
html,圖片,js,css,txt等靜態資源
結合FastCGI/uWSGI/SCGI等協議反向代理動態資源請求
http/https協議的反向代理
imap4/pop3協議的反向代理
tcp/udp協議的請求轉發(反向代理)
nginx的安裝
官方:
http://nginx.org/packages/centos/7/x86_64/RPMS
Fedora-EPEL:
https://mirrors.aliyun.com/epel/7/x86_64/
編譯安裝:
•yum install pcre-devel openssl-devel zlib-devel
•useradd -r nginx
•./configure --prefix=/usr/local/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 --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_dav_module --with-http_stub_status_module --with-threads --with-file-aio
•make && make install
改nginx源碼
可更改編譯安裝後的nginx的名稱和版本
./src/http/ngx_http_header_filter_module.c 第49行左右:改軟件名 "Server:nginx" CRLF; 安裝後會顯示在加了server_tokens後的隱藏的nginx版本
./src/core/nginx.h 第13和14行左右:版本號和軟件名:#define NGINX_VERSION和 #define NGINX_VER,安裝後會顯示在沒加server_tokens的時候的nginx版本號和名稱
編譯安裝nginx選項
編譯安裝nginx選項:
--prefix=/etc/nginx 安裝路徑
--sbin-path=/usr/sbin/nginx 指明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 指明pid文件安裝位置
--lock-path=/var/run/nginx.lock 鎖文件安裝位置
--http-client-body-temp-path=/var/cache/nginx/client_temp 客戶端body部分的臨時文件存放路徑,服務器允許客戶端使用put方法提交大數據時,臨時存放的磁盤路徑
--http-proxy-temp-path=/var/cache/nginx/proxy_temp 作爲代理服務器,服務器響應報文的臨時文件存放路徑
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp 作爲fastcgi代理服務器,服務器響應報文的臨時文件存放路徑
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp 作爲uwsgi代理服務器,服務器響應報文的臨時文件存放路徑
--http-scgi-temp-path=/var/cache/nginx/scgi_temp 作爲scgi反代服務器,服務器響應報文的臨時文件存放路徑
--user=nginx 指明以那個身份運行worker進程,主控master進程一般由root運行
--group=nginx
--with-http_ssl_module 表示把指定模塊編譯進來
nginx目錄結構和命令
ls /usr/local/nginx/
html是測試頁,sbin是主程序
ls /usr/local/nginx/sbin/
nginx 只有一個程序文件
ls /usr/local/nginx/html/
50x.html index.html 測試網頁
Nginx:默認爲啓動nginx
-h 查看幫助選項
-V 查看版本和配置選項(可看到TLS SNI support enabled,這個很有用,可在一臺機上搭建多個https主機,而apache做不到)
-t 測試nginx語法錯誤
-c filename 指定配置文件(default: /etc/nginx/nginx.conf)
-s signal 發送信號給master進程,signal可爲:stop, quit, reopen, reload
示例: nginx -s stop 停止
nginx -s reload 加載配置文件(實際中有時用這個,可不用systemd管理)
-g directives 在命令行中指明全局指令
nginx配置
官方文檔:https://nginx.org/en/docs[/variables]…
配置文件的組成部分:
主配置文件:nginx.conf
子配置文件 include conf.d/*.conf
fastcgi, uwsgi,scgi等協議相關的配置文件
mime.types:支持的mime類型
主配置文件的配置指令:
directive value [value2 ...];
注意:
(1) 指令必須以分號結尾
(2) 支持使用配置變量
內建變量:由Nginx模塊引入,可直接引用
自定義變量:由用戶使用set命令定義
set variable_name value;
引用變量:$variable_name
nginx配置文件
主配置文件結構:四部
main block:主配置段,即全局配置段,對http,mail都有效
event {
...
} 事件驅動相關的配置
http {
...
} http/https 協議相關配置段
mail {
...
} mail 協議相關配置段
stream {
...
} stream 服務器相關配置段
http協議相關的配置結構
http {
...
... 各server的公共配置
server { 每個server用於定義一個虛擬主機
...
}
server {
...
server_name 虛擬主機名
root 主目錄
alias 路徑別名
location [OPERATOR] URL { 指定URL的特性
...
if CONDITION {
...
}
}
}
}
nginx配置
Main 全局配置段常見的配置指令分類
正常運行必備的配置
優化性能相關的配置
用於調試及定位問題相關的配置
事件驅動相關的配置
幫助文檔
http://nginx.org/en/docs/
正常運行必備的配置:
幫助文檔:http://nginx.org/en/docs/ngx_core_module.html
1、user
Syntax: user user [group];
Default: user nobody nobody;
Context: main(只能放在main語句塊裏)
指定worker進程的運行身份,如組不指定,默認和用戶名同名
2、pid /PATH/TO/PID_FILE
指定存儲nginx主進程PID的文件路徑
3、include file | mask
指明包含進來的其它配置文件片斷
4、load_module file
模塊加載配置文件:/usr/share/nginx/modules/*.conf
指明要裝載的動態模塊路徑: /usr/lib64/nginx/modules
性能優化相關的配置:
1、worker_processes number | auto
worker進程的數量;auto通常應該爲當前主機的cpu的物理核心數
2、worker_cpu_affinity cpumask ...
worker_cpu_affinity auto [cpumask] 提高緩存命中率
CPU MASK:00000001:0號CPU
00000010:1號CPU
10000000:8號CPU
worker_cpu_affinity 0001 0010 0100 1000;
worker_cpu_affinity 0101 1010;
px axo pid,cmd,psr | grep nginx查看worker進程工作在哪顆CPU上
3、worker_priority number
指定worker進程的nice值,設定worker進程優先級:[-20,20]
4、worker_rlimit_nofile number
worker進程所能夠打開的文件數量上限,如65535(所有worker的總值,也是總最大併發連接數量上限,可調大)
事件驅動相關的配置:
events {
...
}
1、worker_connections number
每個worker進程所能夠打開的最大併發連接數數量,如10240(跟worker_rlimit_nofile number相乘即爲總最大併發連接數)
總最大併發數:worker_processes(worker進程數) * worker_connections
可以設定worker_rlimit_nofile等於總最大併發數
2、use method
指明併發連接請求的處理方法 ,默認自動選擇最優方法
use epoll;
3、accept_mutex on | off 互斥
處理新的連接請求的方法;on指由各個worker輪流處理新請求,Off指每個新請求的到達都會通知(喚醒)所有的worker進程,但只有一個進程可獲得連接,造成“驚羣”,影響性能,最好設成On
調試和定位問題:
1、daemon on|off
是否以守護進程方式運行nignx,默認是守護進程方式(如果變成off則爲前臺執行,經常改配置測試時可用,Ctrl+C即可停止,nginx即可開始,操作方便)
2、master_process on|off
是否以master/worker模型運行nginx;默認爲on
off 將不啓動worker
3、error_log file [level]
錯誤日誌文件及其級別;出於調試需要,可設定爲debug;但debug僅在編譯時使用了“--with-debug”選項時纔有效
方式:file /path/logfile;
stderr:發送到標準錯誤
syslog:server-address[,parameter=values]:發送到syslog memory:size 內存
level:debug|info|notice|warn|error|crit|alter|emerg
http協議的相關配置:
http {
... ...
server {
...
server_name
root
location [OPERATOR] /uri/ {
...
}
}
server {
...
}
}
ngx_http_core_module
與套接字相關的配置:
1、server { ... }
配置一個虛擬主機
server {
listen address[:PORT]|PORT;
server_name SERVER_NAME;
root /PATH/TO/DOCUMENT_ROOT;
}
2、listen PORT|address[:port]|unix:/PATH/TO/SOCKET_FILE
listen address[:port] [default_server] [ssl] [http2 | spdy] [backlog=number] [rcvbuf=size] [sndbuf=size]
default_server 設定爲默認虛擬主機
ssl 限制僅能夠通過ssl連接提供服務
backlog=number 超過併發連接數後,新請求進入後援隊列的長度
rcvbuf=size 接收緩衝區大小
sndbuf=size 發送緩衝區大小
注意:
(1) 基於port;
listen PORT; 指令監聽在不同的端口
(2) 基於ip的虛擬主機
listen IP:PORT; IP 地址不同
(3) 基於hostname
server_name fqdn; 指令指向不同的主機名
3、server_name name ...;
虛擬主機的主機名稱後可跟多個由空白字符分隔的字符串
支持*通配任意長度的任意字符
server_name *.wind.com www.wind.*
支持~起始的字符做正則表達式模式匹配,性能原因慎用
server_name ~^www\d+\.wind\.com$
說明:\d 表示 [0-9]
匹配優先級機制從高到低:
(1) 首先是字符串精確匹配 如:www.wind.com
(2) 左側*通配符 如:*.wind.com
(3) 右側*通配符 如:www.wind.*
(4) 正則表達式 如: ~^.*\.wind\.com$
(5) default_server
4、tcp_nodelay on | off;
在keepalived模式下的連接是否啓用TCP_NODELAY選項
當爲off時,延遲發送,合併多個請求後再發送
默認On時,不延遲發送
可用於:http, server, location
5、sendfile on | off;
是否啓用sendfile功能,在內核中封裝報文直接發送
默認Off
6、server_tokens on | off | build | string
是否在響應報文的Server首部顯示nginx版本(建議設爲off,商業版可以指定爲任意string,或者改源碼也可以)
定義路徑相關的配置
7、root
設置web資源的路徑映射;用於指明請求的URL所對應的文檔的目錄路徑,可用於http, server, location, if in location
server {
...
root /data/www/vhosts;
}
示例
http://www.wind.com/images/logo.jpg
--> /data/www/vhosts/images/logo.jpg
8、location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }
在一個server中location配置段可存在多個,用於實現從uri到文件系統的路徑映射;ngnix會根據用戶請求的URI來檢查定義的所有location,並找出一個最佳匹配,而後應用其配置
示例:
server {...
server_name www.wind.com;
location /images/ {
root /data/imgs/; #location中的root根優先級高一點
}
}
http://www.wind.com/images/logo.jpg
--> /data/imgs/images/logo.jpg
=:對URI做精確匹配;
location = / {
...
}
http://www.wind.com/ 匹配
http://www.wind.com/index.html 不匹配
^~:對URI的最左邊部分做匹配檢查,不區分字符大小寫
~:對URI做正則表達式模式匹配,區分字符大小寫
~*:對URI做正則表達式模式匹配,不區分字符大小寫
不帶符號:匹配起始於此uri的所有的uri
匹配優先級從高到低:
=, ^~, ~/~*, 不帶符號
示例:
root /vhosts/www/htdocs/
http://www.wind.com/index.html
--> /vhosts/www/htdocs/index.html
server {
root /vhosts/www/htdocs/
location /admin/ {
root /webapps/app1/data/
}
}
http://www.wind.com/admin/index.html
--> /webapps/app1/data/admin/index.html
location示例
location = / {
[ configuration A ]
}
http://www.wind.com/
location / {
[ configuration B ]
}
http://www.wind.com/index.html
location /documents/ {
[ configuration C ]
}
http://www.wind.com/documents/linux.txt
location ^~ /images/ {
[ configuration D ]
}
lhttp://www.wind.com/images/logo.jpeg
location ~* \.(gif|jpg|jpeg)$ {
[ configuration E ]
}
http://www.wind.com/documents/logo.jpg
9、alias path;
路徑別名,文檔映射的另一種機制;僅能用於location上下文
示例:
http://www.wind.com/bbs/index.php
location /bbs/ {
alias /web/forum/;
} --> /web/forum/index.html
location /bbs/ {
root /web/forum/;
} --> /web/forum/bbs/index.html
注意:location中使用root指令和alias指令的意義不同
(a) root,給定的路徑對應於location中的/uri/左側的/
(b) alias,給定的路徑對應於location中的/uri/右側的/
10、index file ...;
指定默認網頁文件,注意:ngx_http_index_module模塊
11、error_page code ... [=[response]] uri;
模塊:ngx_http_core_module
定義錯誤頁,以指定的響應狀態碼進行響應
可用位置:http, server, location, if in location
error_page 404 /404.html
error_page 404 =200 /404.html #404響應碼改爲200或302等,防止某些瀏覽器劫持,再加個location
location /404[.html] {
root /data/sitea/error/;
}
echo ' <h1>FBI WARNING!</h1>' > /data/sitea/error/404.html
12、try_files file ... uri;
try_files file ... =code;
按順序檢查文件是否存在,返回第一個找到的文件或文件夾(結尾加斜線表示爲文件夾),如果所有的文件或文件夾都找不到,會進行一個內部重定向到最後一個參數。只有最後一個參數可以引起一個內部重定向,之前的參數只設置內部URI的指向。最後一個參數是回退URI且必須存在,否則會出現內部500錯誤
location /images/ {
try_files $uri /images/default.gif;
}
location / {
try_files $uri $uri/index.html $uri.html =404;
}
定義客戶端請求的相關配置
13、keepalive_timeout timeout [header_timeout];
設定保持連接超時時長,0表示禁止長連接,默認爲75s
生產中75s有點太長了,可調短
14、keepalive_requests number;
在一次長連接上所允許請求的資源的最大數量
默認爲100
15、keepalive_disable none | browser ...
對哪種瀏覽器禁用長連接
16、send_timeout time;
向客戶端發送響應報文的超時時長,此處是指兩次寫操作之間的間隔時長,而非整個響應過程的傳輸時長
17、client_body_buffer_size size;
用於接收每個客戶端請求報文的body部分的緩衝區大小;默認爲16k;超出此大小時,其將被暫存到磁盤上的由下面client_body_temp_path指令所定義的位置
18、client_body_temp_path path [level1 [level2 [level3]]];
設定存儲客戶端請求報文的body部分的臨時存儲路徑及子目錄結構和數量
目錄名爲16進制的數字;
client_body_temp_path /var/tmp/client_body 1 2 2
1 1級目錄佔1位16進制,即2^4=16個目錄 0-f
2 2級目錄佔2位16進制,即2^8=256個目錄 00-ff
2 3級目錄佔2位16進制,即2^8=256個目錄 00-ff
例:
client_body_temp_path /var/tmp/client_body 1 2 2
[root@centos ~]#sha1sum anaconda-ks.cfg
52be534d26c21c12ffcab497533e918e9d0a5658 anaconda-ks.cfg
則anaconda-sk.cfg文件上傳後會被存在client_body_temp_path/8/65/a5目錄中
因爲如果文件數量很多,1億個文件,都放一個目錄的話,查詢效率會很低,系統以哈希值來區分,進3個目錄,每個目錄存的文件就只有100個了,查詢效率會變高
對客戶端進行限制的相關配置
19、limit_rate rate;
限制響應給客戶端的傳輸速率,單位是bytes/second
默認值0表示無限制
20、limit_except method ... { ... },僅用於location
限制客戶端使用除了指定的請求方法之外的其它方法
method:GET, HEAD, POST, PUT, DELETE
MKCOL, COPY, MOVE, OPTIONS, PROPFIND,
PROPPATCH, LOCK, UNLOCK, PATCH
limit_except GET {
allow 192.168.1.0/24;
deny all;
} 除了GET和HEAD 之外其它方法僅允許192.168.1.0/24網段主機使用
GET包含HEAD
文件操作優化的配置
21、aio on | off | threads[=pool];
是否啓用aio功能
22、directio size | off;
當文件大於等於給定大小時,例如directio 4m,同步(直接)寫磁盤,而非寫緩存
23、open_file_cache off;
open_file_cache max=N [inactive=time];
nginx可以緩存以下三種信息:
(1) 文件元數據:文件的描述符、文件大小和最近一次的修改時間
(2) 打開的目錄結構
(3) 沒有找到的或者沒有權限訪問的文件的相關信息
max=N:可緩存的緩存項上限;達到上限後會使用LRU算法實現管理
inactive=time:緩存項的非活動時長,在此處指定的時長內未被命中的或命中的次數少於open_file_cache_min_uses指令所指定的次數的緩存項即爲非活動項,將被刪除
24、open_file_cache_errors on | off;
是否緩存查找時發生錯誤的文件一類的信息
默認值爲off
25、open_file_cache_min_uses number;
open_file_cache指令的inactive參數指定的時長內,至少被命中此處指定的次數方可被歸類爲活動項
默認值爲1
26、open_file_cache_valid time;
緩存項有效性的檢查頻率
默認值爲60s
ngx_http_access_module
ngx_http_access_module模塊
實現基於ip的訪問控制功能
1、allow address | CIDR | unix: | all;
2、deny address | CIDR | unix: | all;
http, server, location, limit_except
自上而下檢查,一旦匹配,將生效,所以要將條件範圍小的置前
示例:
location / {
deny 192.168.1.1;
allow 192.168.1.0/24;
allow 10.1.1.0/16;
allow 2001:0db8::/32;
deny all;
}
ngx_http_auth_basic_module
ngx_http_auth_basic_module模塊
實現基於用戶的訪問控制,使用basic機制進行用戶認證
1、auth_basic string | off;
2、auth_basic_user_file file;
location /admin/ {
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.ngxpasswd;
}
用戶口令文件:
1、明文文本:格式name:password:comment
2、加密文本:由htpasswd命令實現
httpd-tools所提供
ngx_http_stub_status_module
ngx_http_stub_status_module模塊
用於輸出nginx的基本狀態信息
輸出信息示例:
Active connections: 291
server accepts handled requests
16630948 16630948 31070465
上面三個數字分別對應accepts,handled,requests三個值
Reading: 6 Writing: 179 Waiting: 106
Active connections:當前狀態,活動狀態的連接數
accepts:統計總值,已經接受的客戶端請求的總數
handled:統計總值,已經處理完成的客戶端請求的總數
requests:統計總值,客戶端發來的總的請求數
Reading:當前狀態,正在讀取客戶端請求報文首部的連接的連接數
Writing:當前狀態,正在向客戶端發送響應報文過程中的連接數
Waiting:當前狀態,正在等待客戶端發出請求的空閒連接數
1、stub_status;
示例:
location /status {
stub_status;
allow 172.16.0.0/16;
deny all;
}
ngx_http_log_module
ngx_http_log_module模塊
指定日誌格式記錄請求
1、log_format name string ...;
string可以使用nginx核心模塊及其它模塊內嵌的變量
2、access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log off;
訪問日誌文件路徑,格式及相關的緩衝的配置
buffer=size
flush=time
示例
log_format compression '$remote_addr-$remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" "$gzip_ratio"';
access_log /spool/logs/nginx-access.log compression buffer=32k;
3、open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];
open_log_file_cache off;
緩存各日誌文件相關的元數據信息
max:緩存的最大文件描述符數量
min_uses:在inactive指定的時長內訪問大於等於此值方可被當作活動項
inactive:非活動時長
valid:驗證緩存中各緩存項是否爲活動項的時間間隔
ngx_http_gzip_module
ngx_http_gzip_module
用gzip方法壓縮響應數據,節約帶寬
1、gzip on | off;
啓用或禁用gzip壓縮
2、gzip_comp_level level;
壓縮比由低到高:1 到 9
默認:1
3、gzip_disable regex ...;
匹配到客戶端瀏覽器不執行壓縮
4、gzip_min_length length;
啓用壓縮功能的響應報文大小閾值
5、gzip_http_version 1.0 | 1.1;
設定啓用壓縮功能時,協議的最小版本
默認:1.1
6、gzip_buffers number size;
支持實現壓縮功能時緩衝區數量及每個緩存區的大小
默認:32 4k 或 16 8k
7、gzip_types mime-type ...;
指明僅對哪些類型的資源執行壓縮操作;即壓縮過濾器
默認包含有text/html,不用顯示指定,否則出錯
8、gzip_vary on | off;
如果啓用壓縮,是否在響應報文首部插入“Vary: Accept-Encoding”
9、gzip_proxied off | expired | no-cache | no-store | private | no_last_modified | no_etag | auth | any ...;
nginx充當代理服務器時,對於後端服務器的響應報文,在何種條件下啓用壓縮功能
off:不啓用壓縮
expired,no-cache, no-store,private:對後端服務器的響應報文首部Cache-Control值任何一個,啓用壓縮功能
示例:
gzip on;
gzip_comp_level 6;
gzip_min_length 64;
gzip_proxied any;
gzip_types text/xml text/css application/javascript;
ngx_http_ssl_module
ngx_http_ssl_module模塊:
1、ssl on | off;
爲指定虛擬機啓用HTTPS protocol, 建議用listen指令代替
2、ssl_certificate file;
當前虛擬主機使用PEM格式的證書文件
3、ssl_certificate_key file;
當前虛擬主機上與其證書匹配的私鑰文件
4、ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2]; 支持ssl協議版本,默認爲後三個
5、ssl_session_cache off | none | [builtin[:size]] [shared:name:size];
none: 通知客戶端支持ssl session cache,但實際不支持
builtin[:size]:使用OpenSSL內建緩存,爲每worker進程私有
[shared:name:size]:在各worker之間使用一個共享的緩存
6、ssl_session_timeout time;
客戶端連接可以複用ssl session cache中緩存的ssl參數的有效時長,默認5m
示例:
server {
listen 443 ssl;
server_name www.wind.com;
root /vhosts/ssl/htdocs;
ssl on;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
}
ngx_http_rewrite_module(用得很多)
ngx_http_rewrite_module模塊:
將用戶請求的URI基於PCRE regex所描述的模式進行檢查,而後完成重定向替換
示例:
http://www.wind.com/hn --> http://www.wind.com/henan
http://www.wind.com --> https://www.wind.com/
1、rewrite regex replacement [flag]
將用戶請求的URI基於regex所描述的模式進行檢查,匹配到時將其替換爲replacement指定的新的URI
注意:如果在同一級配置塊中存在多個rewrite規則,那麼會自下而下逐個檢查;被某條件規則替換完成後,會重新一輪的替換檢查
隱含有循環機制,但不超過10次;如果超過,提示500響應碼,[flag]所表示的標誌位用於控制此循環機制
如果replacement是以http://或https://開頭,則替換結果會直接以重向返回給客戶端, 即永久重定向301
[flag]:
last:重寫完成後停止對當前URI在當前location中後續的其它重寫操作,而後對新的URI啓動新一輪重寫檢查;提前重啓新一輪循環,不建議在location中使用(類似shell腳本中的continue)
break:重寫完成後停止對當前URI在當前location中後續的其它重寫操作,而後直接跳轉至重寫規則配置塊之後的其它配置;結束循環,建議在location中使用(類似shell腳本中的break)
redirect:臨時重定向,重寫完成後以臨時重定向方式直接返回重寫後生成的新URI給客戶端,由客戶端重新發起請求;使用相對路徑,或者http://或https://開頭,狀態碼:302
permanent:重寫完成後以永久重定向方式直接返回重寫後生成的新URI給客戶端,由客戶端重新發起請求,狀態碼:301
2、return
return code [text];
return code URL;
例:return 301 http://www.baidu.com/ 注:code須是301,302,303,307或308才能跳轉,詳見官方文檔
return URL;
停止處理,並返回給客戶端指定的響應碼
3、rewrite_log on | off;
是否開啓重寫日誌, 發送至error_log(notice level)
4、set $variable value;
用戶自定義變量
注意:變量定義和調用都要以$開頭
5、if (condition) { ... }
條件滿足時,執行配置塊中的配置指令;server, location
condition:
比較操作符:
= 相同 != 不同
~:模式匹配,區分字符大小寫
~*:模式匹配,不區分字符大小寫
!~:模式不匹配,區分字符大小寫
!~*:模式不匹配,不區分字符大小寫
文件及目錄存在性判斷:
-e, !-e 存在(包括文件,目錄,軟鏈接)
-f, !-f 文件 -d, !-d 目錄 -x, !-x 執行
例:
www.a.com/images/a.jpg --> www.a.com/media/images/a.jpg
rewrite ^(images/.*)$ /media/$1
www.a.com/bbs/ --> www.a.com/forum
rewrite ^/bbs/(.*)$ /forum/$1 last|redirect|permanent;
實驗:http到https跳轉
方法1:
server {
listen 80 default_server;
server_name www.a.com;
root /data/sitea/;
location / {
rewrite / https://www.a.com/ redirect;
}
}
server {
listen 443 ssl;
server_name www.a.com;
root /data/siteassl/;
ssl_certificate /etc/nginx/conf.d/vhosts/a.crt;
ssl_certificate_key /etc/nginx/conf.d/vhosts/a.key;
}
方法2:
server {
listen 80 default_server;
listen 443 ssl ;
server_name www.a.com;
root /data/sitea/;
ssl_certificate /etc/nginx/conf.d/a.crt;
ssl_certificate_key /etc/nginx/conf.d/a.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
location / {
if ( $scheme = http ) {
rewrite / https://www.a.com/ redirect;
}
}
}
ngx_http_referer_module(用得多)
ngx_http_referer_module模塊:
用來阻止Referer首部無有效值的請求訪問,可防止盜鏈
1、valid_referers none|blocked|server_names|string ...;
定義referer首部的合法可用值,不能匹配的將是非法值
none:請求報文首部沒有referer首部
blocked:請求報文有referer首部,但無有效值
server_names:參數,其可以有值作爲主機名或主機名模式
arbitrary_string:任意字符串,但可使用*作通配符
regular expression:被指定的正則表達式模式匹配到的字符串,要使用~開頭,例如: ~.*\.wind\.com
示例1:
valid_referers none block server_names *.wind.com wind.* ~\.wind\. ~\.baidu\. ~\.google\.;
if ($invalid_referer) {
return 403 http://www.wind.com;
}
示例2:
在http://www.a.com/daolian.php上有一段盜鏈代碼:
盜鏈了http://www.b.com下的sky.jpg這張圖片,效果如圖:
現在在http://www.b.com/上加上了一串防盜鏈代碼:
valid_referers none block server_names *.b.com b.* ~\.b\.
~\.baidu\. ~\.google\.;
if ($invalid_referer) {
return 403 ;
}
加上之後,http://www.a.com/無法盜鏈了,效果如圖:
ngx_http_proxy_module
ngx_http_proxy_module模塊:
轉發請求至另一臺主機
1、proxy_pass URL;
Context:location, if in location, limit_except
注意:proxy_pass後面路徑不帶uri時,會將location的uri傳遞(附加)給後端主機
server {
...
server_name HOSTNAME;
location /uri/ {
proxy_pass http://host[:port]; 最後沒有/
}
...
}
上面示例:http://HOSTNAME/uri --> http://host/uri
如果上面示例中有 /,即:http://host[:port]/
意味着:http://HOSTNAME/uri --> http://host/ 即置換
proxy_pass後面的路徑是一個uri時,其會將location的uri替換爲proxy_pass的uri
server {
...
server_name HOSTNAME;
location /uri/ {
proxy_pass http://host/new_uri/;
}
...
}
http://HOSTNAME/uri/ --> http://host/new_uri/
如果location定義其uri時使用了正則表達式的模式,則proxy_pass之後必須不能使用uri; 用戶請求時傳遞的uri將直接附加至後端服務器之後
server {
...
server_name HOSTNAME;
location ~|~* /uri/ {
proxy_pass http://host; 不能加/
}
...
}
http://HOSTNAME/uri/ --> http://host/uri/
2、proxy_set_header field value;
設定發往後端主機的請求報文的請求首部的值
Context: http, server, location
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #用以多層代理的時候,把中間的代理服務器全加進去,以逗號隔開
請求報文的標準格式如下:
X-Forwarded-For: client1, proxy1, proxy2
後端服務器httpd.conf也要配一下:
# LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined 把原來這行復制然後註釋掉,%h改成%{X-Forwarded-for}i
LogFormat "%{X-Forwarded-for}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
3、proxy_cache_path;
定義可用於proxy功能的緩存;Context:http
proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];
4、proxy_cache zone | off; 默認off
指明調用的緩存,或關閉緩存機制;Context:http, server, location
5、proxy_cache_key string;
緩存中用於“鍵”的內容
默認值:proxy_cache_key $scheme$proxy_host$request_uri;
6、proxy_cache_valid [code ...] time;
定義對特定響應碼的響應內容的緩存時長
定義在http{...}中
示例:
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
示例:在http配置定義緩存信息
proxy_cache_path /var/cache/nginx/proxy_cache
levels=1:1:1 keys_zone=proxycache:20m
inactive=120s max_size=1g;
說明:proxycache:20m 指內存中緩存的大小,主要用於存放key(如:url)和metadata(如:使用次數,在磁盤中的路徑)
max_size=1g 指磁盤存入文件內容的緩存空間最大值
調用緩存功能,需要定義在相應的配置段,如server{...};
proxy_cache proxycache;
proxy_cache_key $request_uri;
proxy_cache_valid 200 302 301 1h;
proxy_cache_valid any 1m;
7、proxy_cache_use_stale;
proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | off ...
在被代理的後端服務器出現哪種情況下,可以真接使用過期的緩存響應客戶端
8、proxy_cache_methods GET | HEAD | POST ...;
對哪些客戶端請求方法對應的響應進行緩存,GET和HEAD方法總是被緩存
9、proxy_hide_header field;
默認nginx在響應報文不傳遞後端服務器的首部字段Date, Server, X-Pad, X-Accel-等,用於隱藏後端服務器特定的響應首部
10、proxy_connect_timeout time;
定義與後端服務器建立連接的超時時長,如超時會出現502錯誤,默認爲60s,一般不建議超出75s
11、proxy_send_timeout time;
將請求發送給後端服務器的超時時長;默認爲60s
12、proxy_read_timeout time;
等待後端服務器發送響應報文的超時時長,默認爲60s
ngx_http_headers_module模塊
ngx_http_headers_module模塊
向由代理服務器響應給客戶端的響應報文添加自定義首部,或修改指定首部的值
1、add_header name value [always];
添加自定義首部
add_header X-Via $server_addr;
add_header X-Cache $upstream_cache_status;
add_header X-Accel $server_name;
2、add_trailer name value [always];
添加自定義響應信息的尾部
ngx_http_fastcgi_module
ngx_http_fastcgi_module模塊
轉發請求到FastCGI服務器,不支持php模塊方式
1、fastcgi_pass address;
address爲後端的fastcgi server的地址
可用位置:location, if in location
2、fastcgi_index name;
fastcgi默認的主頁資源
示例:fastcgi_index index.php;
3、fastcgi_param parameter value [if_not_empty];
設置傳遞給 FastCGI服務器的參數值,可以是文本,變量或組合
示例1:
1)在後端服務器先配置fpm server和mariadb-server
2)在前端nginx服務上做以下配置:
location ~* \.php$ {
fastcgi_pass 後端fpm服務器IP:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name; #後端fpm服務器的php腳本目錄,這項很重要
include fastcgi_params;
…
}
示例2:通過/pm_status和/ping來獲取fpm server狀態信息
location ~* ^/(pm_status|ping)$ {
include fastcgi_params;
fastcgi_pass 後端fpm服務器IP:9000;
fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
}
4、fastcgi_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];
定義fastcgi的緩存;
path 緩存位置爲磁盤上的文件系統
max_size=size
磁盤path路徑中用於緩存數據的緩存空間上限
levels=levels:緩存目錄的層級數量,以及每一級的目錄數量
levels=ONE:TWO:THREE
示例:leves=1:2:2
keys_zone=name:size
k/v映射的內存空間的名稱及大小
inactive=time
非活動時長
5、fastcgi_cache zone | off;
調用指定的緩存空間來緩存數據
可用位置:http, server, location
6、fastcgi_cache_key string;
定義用作緩存項的key的字符串
示例:fastcgi_cache_key $request_rui;
7、fastcgi_cache_methods GET | HEAD | POST ...;
爲哪些請求方法使用緩存
8、fastcgi_cache_min_uses number;
緩存空間中的緩存項在inactive定義的非活動時間內至少要被訪問到此處所指定的次數方可被認作活動項
9、fastcgi_keep_conn on | off;
收到後端服務器響應後,fastcgi服務器是否關閉連接,建議啓用長連接
10、fastcgi_cache_valid [code ...] time;
不同的響應碼各自的緩存時長
示例:
注:也要放在context:http裏
http {
fastcgi_cache_path /var/cache/nginx/fcgi_cache levels=1:2:1 keys_zone=fcgicache:20m inactive=120s;
...
server {
location ~* \.php$ {
...
fastcgi_cache fcgicache;
fastcgi_cache_key $request_uri;
fastcgi_cache_valid 200 302 10m;
fastcgi_cache_valid 301 1h;
fastcgi_cache_valid any 1m;
...
}
}
實驗:實現LNMP,提供多個虛擬主機
http, 提供wordpress
https, 提供pma
拓撲圖如下
爲了演示,這裏把nginx服務器和php-fpm服務器拆開了,實際工作中一般不用拆開。以下是各服務器的配置:
1、MySQL服務器
#192.168.30.6
yum -y isntall mariadb-server #安裝MariaDB數據庫
mkdir -pv /data/binlog #創建用於獨立存放二進制日誌的目錄
chown -R mysql.mysql /data/binlog #更改目錄權限
vim /etc/my.cnf #修改配置文件,添加以下內容
log_bin=/data/binlog/mysql-bin
binlog_format=row
innodb_file_per_table
character_set_server=utf8
systemctl start mariadb #啓動數據庫
mysql_secure_installation #安全初始化,這裏爲了實驗方便就不做了
MariaDB [none]> create database wpdb; #創建wordpress數據庫
MariaDB [none]> grant all on wpdb.* to wpuser@'192.168.30.%' identified by 'centos'; #創建wordpress帳號
MariaDB [none]> grant all on *.* to pmauser@'192.168.30.%' identified by 'centos'; #創建pma帳號
MariaDB [none]> flush privileges; #刷新權限
2、php-fpm服務器
# 192.168.30.5
yum -y install php-fpm php-mysql
listen = 9000 #把默認的127.0.0.1去掉,否則會只監聽本機
listen.allowed_clients = 192.168.30.3 #把默認的127.0.0.1改成nginx服務器的IP,否則會只允許本機訪問
pm.status_path = /status
ping.path = /ping
ping.response = pong
systemctl start php-fpm
mkdir -pv /data/wind/ #創建主目錄
佈署phpMyadmin
下載pma:https://www.phpmyadmin.net/downloads/
tar xvf phpMyAdmin-4.0.10.20-all-languages.tar.xz -C /data/wind
cd /data/wind/
mv phpMyAdmin-4.0.10.20-all-languages pma
cd pma
cp config.sample.inc.php config.inc.php
vim config.inc.php
$cfg['blowfish_secret'] = 'abc1234'; #紅色的隨機數改一下
$cfg['Servers'][$i]['host'] = '192.168.30.6'; #MySQL服務器的地址改成192.168.30.6
yum -y install php-mbstring
佈署wordpress
下載地址:
官網:https://cn.wordpress.org/
解壓縮WordPress博客程序到/data/wind/wordpress下
tar xvf wordpress-4.9.4-zh_CN.tar.gz -C /data/wind/
cd /data/wind/wordpress
cp -a wp-config-sample.php wp-config.php
vim wp-config.php 修改相應選項
setfacl -R -m u:apache:rwx /data/wind/wordpress #增加acl權限
3、nginx服務器
#192.168.30.3
yum -y install nginx #安裝nginx
mkdir -pv /data/wind/
tar xvf wordpress-4.9.4-zh_CN.tar.gz -C /data/wind/
tar xvf phpMyAdmin-4.0.10.20-all-languages.tar.xz -C /data/wind
cd /data/wind/
mv phpMyAdmin-4.0.10.20-all-languages pma
# nginx服務器也要解壓一份wordpress和pma,因爲靜態頁面無法交給php-fpm服務器去處理,所以本機要放一份,不過可以只留下靜態頁面。實際工作中nginx服務器和php-fpm服務器不需要拆開,只解壓一份即可,這裏拆分開僅作爲演示用
cd /etc/pki/tls/certs
make wind.crt #爲了啓用https服務,自簽名一個證書wind.crt,順便也生成了一個私鑰wind.key
openssl rsa -in wind.key -out wind.key #爲了方便,去掉私鑰的密碼,需要輸一遍原密碼
mv /etc/pki/tls/certs/wind* /etc/nginx/conf.d/ #證書和私鑰移到另一個目錄
# nginx可以選擇啓不啓用fastcgi日誌,這裏不啓用
vim /etc/nginx/conf.d/wind.conf #爲LNMP單起一個配置文件
server {
listen 80 default_server; #80端口用於wordpress
server_name www.wind.com; #指定虛擬主機名
root /data/wind/wordpress; #設置web資源的路徑映射
index index.html index.php; #指定主頁
location ~* \.php$ { #起一個處理php文件的location
fastcgi_pass 192.168.30.5:9000; #指定php-fpm服務器
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /data/wind/wordpress$fastcgi_script_name;
#上一行中,/data/wind/wordpress換成$document_root也可以
include fastcgi_params;
}
location ~* ^/(status|ping)$ {
include fastcgi_params;
fastcgi_pass 192.168.30.5:9000;
fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
}
location / { #單起一個location,用以處理靜態頁面
}
}
server {
listen 443 ssl; #443端口用於pma
server_name www.wind.com;
root /data/wind/pma;
index index.html index.php
ssl_certificate /etc/nginx/conf.d/wind.crt;
ssl_certificate_key /etc/nginx/conf.d/wind.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
location ~* \.php$ {
fastcgi_pass 192.168.30.5:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location / {
}
}
# 由於在/etc/nginx/conf.d/wind.conf中定義了default_server,因此在/etc/nginx/nginx.conf中要把default_server去掉
vim /etc/nginx/nginx.conf
server {
listen 80 default_server; #刪掉這行的default_server字樣
listen [::]:80 default_server; #刪掉這行的default_server字樣
nginx -t #檢查nginx配置文件是否有問題
nginx #啓動nginx服務
4、客戶端
#192.168.30.2
curl 192.168.30.3 ping #測試php-fpm,如果回覆pong則php-fpm成功啓動
vim /etc/hosts
192.168.30.3 www.wind.com #添加這一行DNS配置
打開火狐瀏覽器,輸入http://www.wind.com,打開wordpress成功
輸入https://www.wind.com,打開pma成功
wordpress輸入註冊信息,安裝成功
pma輸入數據庫用戶名pmauser和密碼centos,登錄成功
ngx_http_upstream_module模塊
ngx_http_upstream_module模塊
用於將多個服務器定義成服務器組,而由proxy_pass, fastcgi_pass等指令進行引用
1、upstream name { ... }
定義後端服務器組,會引入一個新的上下文
默認調度算法是wrr
Context: http
upstream httpdsrvs {
server ...
server...
...
}
2、server address [parameters];
在upstream上下文中server成員,以及相關的參數;Context:upstream
address的表示格式:
unix:/PATH/TO/SOME_SOCK_FILE
IP[:PORT]
HOSTNAME[:PORT]
parameters:
weight=number 權重,默認爲1
max_conns 連接後端報務器最大併發活動連接數,1.11.5後支持
max_fails=number 失敗嘗試最大次數;超出此處指定的次數時,server將被標記爲不可用,默認爲1
fail_timeout=time 後端服務器標記爲不可用狀態的連接超時時長,默認10s
backup 將服務器標記爲“備用”,即所有服務器均不可用時才啓用
down 標記爲“不可用”,配合ip_hash使用,實現灰度發佈
3、ip_hash 源地址hash調度方法
4、least_conn 最少連接調度算法,當server擁有不同的權重時其爲wlc,當所有後端主機連接數相同時,則使用wrr,適用於長連接
5、hash key [consistent] 基於指定的key的hash表來實現對請求的調度,此處的key可以直接文本、變量或二者組合
作用:將請求分類,同一類請求將發往同一個upstream server,使用consistent參數,將使用ketama一致性hash算法,適用於後端是Cache服務器(如varnish)時使用
hash $request_uri consistent;
hash $remote_addr;
不加consistent:hash(1.html)%2= 0 1 2 --> 結果太少,容易發生哈希環偏斜
加consistent:hash(1.html) %2^32=大哈希環
6、keepalive 連接數N;
爲每個worker進程保留的空閒的長連接數量,可節約nginx端口,並減少連接管理的消耗
7、health_check [parameters];
健康狀態檢測機制;只能用於location上下文
常用參數:
interval=time檢測的頻率,默認爲5秒
fails=number:判定服務器不可用的失敗檢測次數;默認爲1次
passes=number:判定服務器可用的失敗檢測次數;默認爲1次
uri=uri:做健康狀態檢測測試的目標uri;默認爲/
match=NAME:健康狀態檢測的結果評估調用此處指定的match配置塊
注意:僅對nginx plus有效(付費)
8、match name { ... }
對backend server做健康狀態檢測時,定義其結果判斷機制;只能用於http上下文
常用的參數:
status code[ code ...]: 期望的響應狀態碼
header HEADER[operator value]:期望存在響應首部,也可對期望的響應首部的值基於比較操作符和值進行比較
body:期望響應報文的主體部分應該有的內容
注意:僅對nginx plus有效
ngx_stream_core_module模塊
nginx的其它的二次發行版:
Tengine:由淘寶網發起的Web服務器項目。它在Nginx的基礎上,針對大訪問量網站的需求,添加了很多高級功能和特性。Tengine的性能和穩定性已經在大型的網站如淘寶網,天貓商城等得到了很好的檢驗。它的最終目標是打造一個高效、穩定、安全、易用的Web平臺。從2011年12月開始,Tengine成爲一個開源項目,官網 http://tengine.taobao.org/
OpenResty:基於 Nginx 與 Lua 語言的高性能 Web 平臺
ngx_stream_core_module模塊
模擬反代基於tcp或udp的服務連接,即工作於傳輸層的反代或調度器
1、stream { ... }
定義stream相關的服務;Context:main
stream {
upstream mysqlsrvs {
server 192.168.22.2:3306;
server 192.168.22.3:3306;
least_conn;
}
server {
listen [10.1.0.6:]3306;
proxy_pass mysqlsrvs;
}
}
例如可以實現對後端多個MySQL數據庫的調度
2、listen格式
listen address:port [ssl] [udp] [proxy_protocol] [backlog=number] [bind] [ipv6only=on|off] [reuseport] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]];
ngx_stream_proxy_module模塊
ngx_stream_proxy_module模塊
可實現代理基於TCP,UDP (1.9.13), UNIX-domain sockets的數據流
1 proxy_pass address;
指定後端服務器地址
2 proxy_timeout timeout;
無數據傳輸時,保持連接狀態的超時時長
默認爲10m
3 proxy_connect_timeout time;
設置nginx與被代理的服務器嘗試建立連接的超時時長
默認爲60s
示例
stream {
upstream mysqlsrvs {
server 192.168.0.10:3306;
server 192.168.0.11:3306;
hash $remote_addr consistent;
}
server {
listen [172.16.100.100:]3306;
proxy_pass mysqlsrvs;
proxy_timeout 60s;
proxy_connect_timeout 10s;
}
}
練習
•nginx--> AMPs(wordpress)
•nginx--> FPMs(wordpress)
•自定義錯誤404和5xx錯誤頁,文本靜態內容傳輸壓縮
•實現動靜分離:動態資源存儲一組服務器、圖片資源存在一組服務器、靜態的文本類資源存儲在一組服務器
nginx-->images servers ( imgs.wind.com)
location ~* \.(jpg|png|gif|jpeg)$ {
...
}
nginx-->dynamic content servers (shop.wind.com)
location ~* \.php$ {
...
}