正向代理举例:翻越万里长城去游览墙外的景色
反向代理举例:负载均衡php
正向代理和反向代理涉及三个主体:css
正向代理中,代理跟请求方是一家子,请求方说要啥,代理就给他啥。
反向代理中,代理跟被请求方是一家子,代理统筹规划让哪个被请求方来处理请求,对于请求方来讲,代理就是处理请求的人。大多数状况下,反向代理和被请求方在同一个服务器上。Nginx就是最经常使用的反向代理服务器。html
这里也提一下:动态代理和静态代理
正向代理和反向代理是代理服务器的两种类型
动态代理和静态代理是Java中的设计模式:代理模式。
Spring的两大核心:java
面向切面编程中大量使用动态代理,在每个方法调用前、调用后、抛异常时进行处理,跟装饰器模式很像。linux
nginx主要配置位于/etc/nginx目录下,nginx不只仅能够用于负载均衡HTTP请求,也能够用于基于TCP的其它协议的负载均衡。/etc/nginx/nginx.conf是nginx的跟配置,一切配置都是这个配置的子孙。nginx
/etc/nginx/nginx.confweb
users www-data;定义当前用户 worker_prosesses 4;定义worker数 pid /run/nginx.pid;定义pid文件 events{......} http{... http协议的相关配置 include xxx路径下的conf.d/*.conf; 可使用文件通配符来描述文件,可是必定是文件而非文件夹 } mail{ ....mail相关的一些配置 server{ listen localhost:xx; protocol pop3; proxy on; } server{ listen localhost:xxxx; protocol imap; proxy on; } }
能够发现,最外层是协议,协议内部有若干个server组成,每一个server监听一个端口,根据路径能够转发到本地的其它端口进行处理。include是简单的复制粘贴。正则表达式
需求说明:Tomcat和Gunicorn分别运行在8080端口和8000端口,如今要让它们共用80端口。
当使用:localhost/tomcat/myapp
时,至关于localhost:8080/myapp
当使用:localhost/gunicorn/myapp
时,至关于localhost:8000/myapp
sql
server { listen 80; server_name www.haha.com; access_log /var/log/nginx/reverse.log; location /tomcat { proxy_pass http://127.0.0.1:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location /gunicorn { proxy_pass http://127.0.0.1:8000/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
server_name描述了服务器地址部分,既能够是域名,也能够是IP地址。这一项不可省略。
设置proxy_set_header部分是将请求者的真实信息告知后台服务器shell
须要注意的是:
proxy_pass http://127.0.0.1:8000/myweb/
这样是错误的;/
,不然路径拼接时会由于少一个反斜杠而没法解析,致使404错误。负载均衡必然要用到反向代理,让Nginx做为大管家凌驾于处理请求的服务器之上,Nginx能够动态决定让哪一个服务器来处理请求。负载均衡问题源远流长:两台相同的处理机处理若干任务,怎么处理可以使得任务尽早完成?这是“双塔”问题;两台不一样的处理机处理若干任务,不一样处理机处理不一样任务花费时间不一样,怎样分配任务才能使得任务尽早完成?
负载均衡的核心问题就是:创建用户请求和服务器之间的映射。有以下几种方式:
轮盘赌的方式进行以下配置,首先定义一个upstream,它是多个server的集合。而后在location中就能够直接使用这个upstream。
upstream your_host_or_ip { server 127.0.0.3:8000 weight=5; server 127.0.0.3:8001 weight=5; server 192.168.0.1:8000; server 192.168.0.1:8001; } server { listen 80; server_name your_host_or_ip; access_log /var/log/nginx/my_access.log main; location / { proxy_pass http://your_host_or_ip; } }
须要注意的是,一台服务器有两种访问方式:ip地址和域名方式。ip地址方式确定只能有一种方式进行访问,由于ip地址是全网惟一的。而一台服务器能够绑定多个域名,这样就能够经过多个域名访问同一个服务器了。
当配置了upstream以后,upstream的名称确定跟服务器的名称(IP或者域名)相同,因此一个域名只能进行一个负载均衡,一个IP也只能进行一个负载均衡,而一台服务器能够进行多个负载均衡。
location配置:
直接写一个字符串,常规字符串匹配
~
表示执行一个正则匹配,区分大小写
~*
表示执行一个正则匹配,不区分大小写
^~
表示普通字符匹配。使用前缀匹配。若是匹配成功,则再也不匹配其余location。
=
进行普通字符精确匹配。也就是彻底匹配。
location配置的优先级:
在Nginx的location和配置中location的顺序没有太大关系。正location表达式的类型有关。相同类型的表达式,字符串长的会优先匹配。
如下是按优先级排列说明:
第一优先级:等号类型(=)的优先级最高。一旦匹配成功,则再也不查找其余匹配项。
第二优先级:^~
类型表达式。一旦匹配成功,则再也不查找其余匹配项。
第三优先级:正则表达式类型(~
~*
)的优先级次之。若是有多个location的正则能匹配的话,则使用正则表达式最长的那个。
第四优先级:常规字符串匹配类型。按前缀匹配。
下面示例一下四种地址类型:
location = / { # 仅仅匹配请求 / [ configuration A ] } location / { # 匹配全部以 / 开头的请求。可是若是有更长的同类型的表达式,则选择更长的表达式。若是有正则表达式能够匹配,则优先匹配正则表达式。 [ configuration B ] } location /documents/ { # 匹配全部以 /documents/ 开头的请求。可是若是有更长的同类型的表达式,则选择更长的表达式。 #若是有正则表达式能够匹配,则优先匹配正则表达式。 [ configuration C ] } location ^~ /images/ { # 匹配全部以 /images/ 开头的表达式,若是匹配成功,则中止匹配查找。因此,即使有符合的正则表达式location,也 # 不会被使用 [ configuration D ] } location ~* \.(gif|jpg|jpeg)$ { # 匹配全部以 gif jpg jpeg结尾的请求。可是 以 /images/开头的请求,将使用 Configuration D [ configuration E ] }
请求匹配实例:
/ -> configuration A /index.html -> configuration B /documents/document.html -> configuration C /images/1.gif -> configuration D /documents/1.jpg -> configuration E
应用举例:隐藏内在的地址
server { # 用 xxoo_admin 来掩饰 admin location / { # 使用break拿一旦匹配成功则忽略后续location rewrite /xxoo_admin /admin break; } # 访问真实地址直接报没权限 location /admin { return 403; } }
Nginx的反向代理像一个URL函数,输入是一个URL,输出也是一个URL。运行过程多是这样的:
用户发起请求url0 url1=f(url0) url2=f(url1) ...直到url再也不被重写,被路由到合适的请求处理结点
在配置文件的server块中写,如:
server { rewrite 规则 定向路径 重写类型; }
$index
来表示正则里的捕获分组须要注意:
下面举例说明4种重写类型
server { # 访问 /last.html 的时候,页面内容重写到 /index.html 中 rewrite /last.html /index.html last; # 访问 /break.html 的时候,页面内容重写到 /index.html 中,并中止后续的匹配 rewrite /break.html /index.html break; # 访问 /redirect.html 的时候,页面直接302定向到 /index.html中 rewrite /redirect.html /index.html redirect; # 访问 /permanent.html 的时候,页面直接301定向到 /index.html中 rewrite /permanent.html /index.html permanent; # 把 /html/*.html => /post/*.html ,301定向 rewrite ^/html/(.+?).html$ /post/$1.html permanent; # 把 /search/key => /search.html?keyword=key rewrite ^/search\/([^\/]+?)(\/|$) /search.html?keyword=$1 permanent; }
在/etc/nginx/fastcgi.conf中能够看到所有定义。
$args :这个变量等于请求行中的参数,同$query_string $content_length : 请求头中的Content-length字段。 $content_type : 请求头中的Content-Type字段。 $document_root : 当前请求在root指令中指定的值。 $host : 请求主机头字段,不然为服务器名称。 $http_user_agent : 客户端agent信息 $http_cookie : 客户端cookie信息 $limit_rate : 这个变量能够限制链接速率。 $request_method : 客户端请求的动做,一般为GET或POST。 $remote_addr : 客户端的IP地址。 $remote_port : 客户端的端口。 $remote_user : 已经通过Auth Basic Module验证的用户名。 $request_filename : 当前请求的文件路径,由root或alias指令与URI请求生成。 $scheme : HTTP方法(如http,https)。 $server_protocol : 请求使用的协议,一般是HTTP/1.0或HTTP/1.1。 $server_addr : 服务器地址,在完成一次系统调用后能够肯定这个值。 $server_name : 服务器名称。 $server_port : 请求到达服务器的端口号。 $request_uri : 包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。 $uri : 不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。 $document_uri : 与$uri相同。
如:
访问连接是:http://localhost:88/test1/test2/test.php
网站路径是:/var/www/html
$host:localhost $server_port:88 $request_uri:http://localhost:88/test1/test2/test.php $document_uri:/test1/test2/test.php $document_root:/var/www/html $request_filename:/var/www/html/test1/test2/test.php
if (表达式) { }
表达式的写法有不少:
~*
不区分大小写的匹配,!~区分大小写的不匹配表达式中可使用shell经常使用运算符:
下面看几个if语句的例子:
例子一:简单的if语句
# 若是文件不存在则返回400 if (!-f $request_filename) { return 400; } # 若是host不是xuexb.com,则301到xuexb.com中 if ( $host != 'xuexb.com' ){ rewrite ^/(.*)$ https://xuexb.com/$1 permanent; } # 若是请求类型不是POST则返回405 if ($request_method = POST) { return 405; } # 若是参数中有 a=1 则301到指定域名 if ($args ~ a=1) { rewrite ^ http://example.com/ permanent; }
例子二:在重写中使用if语句
# 访问 /test.html 时 location = /test.html { # 默认值为xiaowu set $name xiaowu; # 若是参数中有 name=xx 则使用该值 if ($args ~* name=(\w+?)(&|$)) { set $name $1; } # 301 rewrite ^ /$name.html permanent; }
举例说明运行结果:
/test.html => /xiaowu.html /test.html?name=ok => /ok.html?name=ok
service nginx configtest 用来检测配置是否正确
service nginx reload 从新加载配置
使用sudo service nginx
命令能够查看可用参数.
location /request_path/image/ { root /local_path/image/; }
这样配置的结果就是当客户端请求 /request_path/image/cat.png 的时候,
Nginx把请求映射为/local_path/image/request_path/image/cat.png
location /request_path/image/ { alias /local_path/image/; }
这时候,当客户端请求 /request_path/image/cat.png 的时候,
Nginx把请求映射为/local_path/image/cat.png
下面举一个例子,当访问myip/poem/authorImage/libai.jpg的时候会自动去文件夹/home/USER_NAME/authorImage/下去寻找libai.jpg。
location /poem/authorImage/ { alias /home/USER_NAME/authorImage/; autoindex on; }
须要注意的是,必须保证authorImage这个文件夹权限足够,不然Nginx没有权力访问这个文件夹。最简单可是不够安全的方式就是把/etc/nginx.conf文件开头的user www-data改成user root,这样把管理员权限赋予Nginx,Nginx就可以访问任意文件了。这样作的缺点就是,一旦Nginx被攻破,整个系统的文件资源可能都会受到威胁。
实际访问/var/ftp/in_ftp/ftp/space_1/111.jpg
location /myf_test/ { root /; rewrite ^/myf_test/(.*)$ /var/ftp/$1 break; }
www.ikscher.com/index.PHP?route=product/product&product_id=123
重定向到www.ikscher.com/product/product&product_id=123
if ($request_uri ~* "(.*)index\.php\?route=(.*)"){ set $host_ $1; set $last_ $2; rewrite (.*) $host_$last_? permanent; #这里的.*表明的是url的原先地址,即要转向的url地址。 }
注意:
www.ikscher.com/?route=product/product&product_id=123
,nginx在进行rewrite的正则表达式中只会将url中?前面的部分拿出来匹配,匹配完成后,?后面的内容将自动追加到url中(包含?),若是不让后面的内容追加上去,请在最后加上?便可。若是想要?后面的内容时请使用$query_string
在这里提醒一点,调试的时候在rewrite的最后一个配置项中不要使用break last这些,使用redirect能够看到转换后的地址。综合以上几点,使用的配置项为
rewrite (.)index.php(.) $1$query_string? permanent;
要求:abc.domian.com/sort/2 => abc.domian.com/index.PHP?act=sort&name=abc&id=2
规则配置:
if ($host ~* (.*)\.domain\.com) { set $sub_name $1; rewrite ^/sort\/(\d+)\/?$ /index.php?act=sort&cid=$sub_name&id=$1 last; }
要求:/123456/xxxx -> /xxxx?id=123456
规则配置:rewrite ^/(\d+)/(.+)/ /$2?id=$1 last;
设定nginx在用户使用ie的使用重定向到/nginx-ie目录
规则以下:
if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /nginx-ie/$1 break; }
/
目录自动加“/” ,这个功能通常浏览器自动完成
if (-d $request_filename){ rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent; }
禁止多个目录 location ~ ^/(cron|templates)/ { deny all; break; } 禁止以/data开头的文件,能够禁止/data/下多级目录下.log.txt等请求 location ~ ^/data { deny all; } 禁止单个文件 location ~ /data/sql/data.sql { deny all; }
给favicon.ico和robots.txt设置过时时间; 这里为favicon.ico为99天,robots.txt为7天并不记录404错误日志
location ~(favicon.ico) { log_not_found off; expires 99d; break; } location ~(robots.txt) { log_not_found off; expires 7d; break; }
设定某个文件的浏览器缓存过时时间;这里为600秒,并不记录访问日志
location ^~ /html/scripts/loadhead_1.js { access_log off; expires 600; break; }
Nginx还能够自定义某一类型的文件的保质期时间,具体写法看下文的代码:
location ~* \.(js|css|jpg|jpeg|gif|png|swf)$ { if (-f $request_filename) { expires 1h; break; } } //上段代码就将js|css|jpg|jpeg|gif|png|swf这类文件的保质期设置为一小时。
防盗链:若是你的网站是个下载网站,下载步骤应该是先通过你的主页找到下载地址,才能下载,为了防止某些网友直接访问下载地址彻底不经过主页下载,咱们就可使用防盗链的方式,具体代码以下:
location ~* \.(gif|jpg|swf)$ { valid_referers none blocked start.igrow.cn sta.igrow.cn; if ($invalid_referer) { rewrite ^/ http://$host/logo.png; } }
文件反盗链并设置过时时间
--<盗链屡次请求也会打开你的站点的图片啊,因此设置下缓存时间,不会每次盗链都请求并下载这张图片> location ~* ^.+\.(jpg|jpeg|gif|png|swf|rar|zip|css|js)$ { valid_referers none blocked *.jjonline.cn *.jjonline.com.cn *.lanwei.org *.jjonline.org localhost 42.121.107.189; if ($invalid_referer) { rewrite ^/ http://img.jjonline.cn/forbid.gif; return 417; break; } access_log off; break; }
说明:
这里的return 417为自定义的http状态码,默认为403,方便经过nginx的log文件找出正确的盗链的请求地址
rewrite ^/ http://img.jjonline.cn/forbid.gif;
显示一张防盗链图片
“access_log off;”不记录访问日志,减轻压力
“expires 3d”全部文件3天的浏览器缓存
location \ { allow 22.27.164.25; #容许的ipd deny all; auth_basic “KEY”; #认证的一些设置 auth_basic_user_file htpasswd; }
if (!-e $request_filename) { #proxy_pass http://127.0.0.1; #这里是跳转到代理ip,这个代理ip上有一个监听的web服务器 rewrite ^/ http://www.jjonline.cn/none.html; #跳转到这个网页去 #return 404; #直接返回404码,而后会寻找root指定的404.html文件 }
域名跳转
server { listen 80; server_name jump.jjonline.cn ;#须要跳转的多级域名 index index.html index.htm index.php; #入口索引文件的名字 root /var/www/public_html/; #这个站点的根目录 rewrite ^/ http://www.jjonline.cn/; #rewrite到这个地址,功能表现:在浏览器上输入jump.jjonline.cn并回车,不会有任何提示直接变成www.jjonline.cn access_log off; }
多域名转向
server { listen 80; server_name www.jjonline.cn www.jjonline.org; index index.html index.htm index.php; root /var/www/public_html/; if ($host ~ “jjonline\.org”) { rewrite ^(.*) http://www.jjonline.cn$1 permanent; } }
三级域名跳转
if ($http_host ~* “^(.*)\.i\.jjonline\.cn$”) { rewrite ^(.*) http://demo.jjonline.cn$1; break; }
server { listen 80; server_name mirror.jjonline.cn; index index.html index.htm index.php; root /var/www/public_html; rewrite ^/(.*) http://www.jjonline.cn/$1 last; access_log off; }
java静态代理和动态代理
Nginx location在配置中的优先级
nginx配置url重写
nginx 重写 rewrite 基础及实例