- 一、简介
- 2. 正向代理与反向代理
- 3. Nginx基本工作机制
- 二、Nginx安装
- 三、Nginx的配置
- 四、动静分离
- 五、Nginx配置Https
- 禁止在header中出现服务器版本,防止黑客利用版本漏洞攻击
- 如果是全站 HTTPS 并且不考虑 HTTP 的话,可以加入 HSTS 告诉你的浏览器本网站全站加密,并且强制用 HTTPS 访问
- nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
- nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
- 六、将nginx作为文件服务器
一、简介
1. 什么是Nginx
介绍
Nginx是一款高性能的http 服务器/反向代理服务器及电子邮件(IMAP/POP3/SMTP)代理服务器。由俄罗斯的程序设计师Igor Sysoev所开发,官方测试nginx能够支支撑5万并发链接,并且cpu、内存等资源消耗却非常低,运行非常稳定。开源、免费
常用服务器
- MS IIS ==> asp.net
- Weblogic、Jboss ==> 传统行业 ERP/物流/电信/金融
- Tomcat、Jetty ==> J2EE
- Apache、Nginx ==> 静态服务,反向代理
https://news.netcraft.com/archives/2020/05/26/may-2020-web-server-survey.html
Nginx的应用场景
- http服务器。Nginx是一个http服务可以独立提供http服务。可以做网页静态服务器。
- 虚拟主机。可以实现在一台服务器虚拟出多个网站。例如个人网站使用的虚拟主机。
- 反向代理,负载均衡。当网站的访问量达到一定程度后,单台服务器不能满足用户的请求时,需要用多台服务器集群可以使用nginx做反向代理。并且多台服务器可以平均分担负载,不会因为某台服务器负载高宕机而某台服务器闲置的情况
一般Java项目整体架构
2. 正向代理与反向代理
1. 正向代理
正向代理类似一个跳板机,通过一个中间服务器(代理服务器),代理访问外部资源返回数据到代理服务器,再由代理服务器发送至客户端。
客户端必须设置正向代理服务器,当然前提是要知道正向代理服务器的IP地址,还有代理程序的端口
正向代理的用途
- 访问原来无法访问的资源,如google
- 可以做缓存,加速访问资源
- 对客户端访问授权,上网进行认证
- 代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息
2. 反向代理
初次接触方向代理的感觉是,客户端是无感知代理的存在的,反向代理对外都是透明的,访问者者并不知道自己访问的是一个代理。因为客户端不需要任何配置就可以访问。
反向代理(Reverse Proxy)实际运行方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。
反向代理,负载均衡。当网站的访问量达到一定程度后,单台服务器不能满足用户的请求时,需要用多台服务器集群可以使用nginx做反向代理。并且多台服务器可以平均分担负载,不会因为某台服务器负载高宕机而某台服务器闲置的情况。
反向代理的作用:
- 保证内网安全,可以使用反向代理提供WAF功能,阻止web攻击
- 负载均衡,当网站的访问量达到一定程度后,单台服务器不能满足用户的请求时,需要用多台服务器集群可以使用nginx做反向代理。并且多台服务器可以平均分担负载,不会因为某台服务器负载高宕机而某台服务器闲置的情况
负载均衡的策略:轮询(默认)、随机、权重、就近
3. 正向代理与反向代理的区别
- 正向代理中,proxy和client同属一个LAN,对server透明;
- 反向代理中,proxy和server同属一个LAN,对client透明。
3. Nginx基本工作机制
1. Nginx显示首页过程
对应 /usr/local/nginx/conf/nginx.conf 中的配置
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
}
2. Nginx的进程模型
基本模型
Nginx使用Master进程和Worker进程模型
- 多进程相对于多线程,内存独立,减少线程安全的问题
使用ps命令查看正在运行的nginx进程
ps -ef | grep nginx
在配置文件中可以配置worker的数量
worker_processes 1;
Worker抢占机制
Nginx使用异步非阻塞的方式来处理请求
在nginx.conf中可以配置进程处理客户端的数量
events {
#默认使用linux的epoll模型
use epoll;
#一个worker可以处理的连接数量
worker_connections 1024;
}
同步与异步,阻塞与非阻塞
我们提到了阻塞与非阻塞、同步与异步,很多同学可能会认为同步就是阻塞,异步就是非阻塞,非也非也~~这一节咱们来聊一聊他们的概念,有啥区别,如果学习过的可以当做复习,如果不太清楚的,可以好好的了解一番,因为这些概念往往在面试过程中有可能会被面试官问到
四个概念两两组合,会形成4个新的概念,如下:
同步阻塞:客户端发送请求给服务端,此时服务端处理任务时间很久,则客户端则被服务端堵塞了,所以客户端会一直等待服务端的响应,此时客户端不能做其他任何事,服务端也不会接受其他客户端的请求。这种通信机制比较简单粗暴,但是效率不高。
同步非阻塞:客户端发送请求给服务端,此时服务端处理任务时间很久,这个时候虽然客户端会一直等待响应,但是服务端可以处理其他的请求,过一会回来处理原先的。这种方式很高效,一个服务端可以处理很多请求,不会在因为任务没有处理完而堵着,所以这是非阻塞的。
异步阻塞:客户端发送请求给服务端,此时服务端处理任务时间很久,但是客户端不会等待服务器响应,它可以做其他的任务,等服务器处理完毕后再把结果响应给客户端,客户端得到回调后再处理服务端的响应。这种方式可以避免客户端一直处于等待的状态,优化了用户体验,其实就是类似于网页里发起的ajax异步请求。
异步非阻塞:客户端发送请求给服务端,此时服务端处理任务时间很久,这个时候的任务虽然处理时间会很久,但是客户端可以做其他的任务,因为他是异步的,可以在回调函数里处理响应;同时服务端是非阻塞的,所以服务端可以去处理其他的任务,如此,这个模式就显得非常的高效了
以上四点,除了第三点,其余的分别为BIO/NIO/AIO,面试官如果问你“请简述一下BIO/NIO/AIO之间的概念与区别”,那么你就可以组织一下语言来回答,或者通过如下生活实例来阐述也是可以的:
BIO:我去上厕所,这个时候坑位都满了,我必须等待坑位释放了,我才能上吧?!此时我啥都不干,站在厕所里盯着,过了一会有人出来了,我就赶紧蹲上去。
NIO:我去上厕所,这个时候坑位都满了,没关系,哥不急,我出去抽根烟,过会回来看看有没有空位,如果有我就蹲,如果没有我出去接着抽烟或者玩会手机。
异步阻塞:我去上厕所,这个时候坑位都满了,没事我等着,等有了新的空位,让他通知我就行,通知了我,我就蹲上去。
AIO:我去上厕所,这个时候坑位都满了,没事,我一点也不急,我去厕所外面抽根烟再玩玩手机,等有新的坑位释放了,会有人通知我的,通知我了,我就可以进去蹲了
小结:异步的优势显而易见,大大优化用户体验,非阻塞使得系统资源开销远远小于阻塞模式,因为系统不需要创建新的进程(或线程),大大地节省了系统的资源,如此多出来的系统资源可以给其他的中间件去服务了。
二、Nginx安装
1. 普通安装方式
1. 安装前提条件
GCC
nginx是C语言开发,建议在linux上运行,本教程使用Centos7作为安装环境。
安装nginx需要先将官网下载的源码进行编译,编译依赖gcc环境,如果没有gcc环境,需要安装gcc
yum install gcc-c++
PCRE
PCRE(Perl Compatible Regular Expressions)是一个Perl库,包括 perl 兼容的正则表达式库。nginx的http模块使用pcre来解析正则表达式,所以需要在linux上安装pcre库
yum install -y pcre pcre-devel
注:pcre-devel是使用pcre开发的一个二次开发库。nginx也需要此库
zlib
zlib库提供了很多种压缩和解压缩的方式,nginx使用zlib对http包的内容进行gzip,所以需要在linux上安装zlib库
yum install -y zlib zlib-devel
openssl
OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用
nginx不仅支持http协议,还支持https(即在ssl协议上传输http),所以需要在linux安装openssl库
yum install -y openssl openssl-devel
2. Nginx的安装步骤
http://nginx.org/en/download.html
- 把nginx的压缩包上传到服务器
解压
tar -zxvf nginx-1.16.1.tar.gz
编译之前,先创建nginx临时目录,如果不创建,在启动nginx的过程中会报错
#-p是递归创建文件夹 mkdir /var/temp/nginx -p
配置参数如下:(直接在nginx的解压路径执行下面的操作)
./configure \ --prefix=/usr/local/nginx \ --pid-path=/var/run/nginx/nginx.pid \ --lock-path=/var/lock/nginx.lock \ --error-log-path=/var/log/nginx/error.log \ --http-log-path=/var/log/nginx/access.log \ --with-http_gzip_static_module \ --http-client-body-temp-path=/var/temp/nginx/client \ --http-proxy-temp-path=/var/temp/nginx/proxy \ --http-fastcgi-temp-path=/var/temp/nginx/fastcgi \ --http-uwsgi-temp-path=/var/temp/nginx/uwsgi \ --http-scgi-temp-path=/var/temp/nginx/scgi
配置命令解释:
命令 | 解释 |
---|---|
–prefix | 指定nginx安装目录 |
–pid-path | 指向nginx的pid |
–lock-path | 锁定安装文件,防止被恶意篡改或误操作 |
–error-log | 错误日志 |
–http-log-path | http日志 |
–with-http_gzip_static_module | 启用gzip模块,在线实时压缩输出数据流 |
–http-client-body-temp-path | 设定客户端请求的临时目录 |
–http-proxy-temp-path | 设定http代理临时目录 |
–http-fastcgi-temp-path | 设定fastcgi临时目录 |
–http-uwsgi-temp-path | 设定uwsgi临时目录 |
–http-scgi-temp-path | 设定scgi临时目录 |
注意:上边将临时文件目录指定为/var/temp/nginx,需要在/var下创建temp及nginx目录
- 编译make
- 安装make install
- 运行(进入到安装目录运行,/usr/local/nginx)
./nginx
- 停止:
_./nginx -s stop_
- 重新加载:
_./nginx -s reload_
- 打开防火墙的80端口:
_firewall-cmd --zone=public --add-port=80/tcp_
- 查看端口开放情况:
_firewall-cmd --list-ports_
- Nginx基本目录
用 _cd /usr/local/nginx_
进入到nginx的安装目录
Conf: nginx:的配置文件路径 Html: nginx:的默认的静态文件资源路径 Sbin: nginx:的执行命令的路径
3. Nginx默认路径
- Nginx配置路径:
_/etc/nginx/_
- 命令程序:
_/usr/sbin/nginx_
- 错误日志:
_/var/log/nginx/error.log_
- 访问日志:
_/var/log/nginx/access.log_
- 默认站点目录:
_/usr/share/nginx/html_
4. Nginx常用命令
进入到nginx安装目录(/usr/local/nginx)下的sbin文件夹执行命令
- 启动:
_nginx_
- 测试nginx配置是否正确:
_nginx -t_
- 重启:nginx -s reload
- 设置conf文件:
_nginx -c /usr/conf/nginx.conf_
- 查看nginx的进程号:
_ps -ef |grep nginx_
- nginx服务停止:
_nginx -s stop / kill -9 pid_
- 等待所有连接断开后再关闭:
_nginx -s quit_
- 查看nginx相关配置:
_nginx -V_
基本启动方式
- 进入到nginx的安装目录(—prefix=/usr/local/nginx )
- 进入到sbin目录下
- 使用./nginx启动
5. Nginx大致配置
基本配置
_/etc/nginx/nginx.conf_
:文件中对nginx进行基础配置
#运行nginx的用户
user nginx;
#工作进程的数量,可以根据CPU的核心总数来设置,一般都是小于或者等于物理cpu核心数,auto表示自动去匹配cup核心数来启动worker进程数量
worker_processes auto;
#error_log表示指定nginx错误日志存放文件
error_log /var/log/nginx/error.log warn;
#pid表示指定pid文件,pid文件就是存放nginx主控进程的进程号的,如果nginx没有运行或者停止了服务,那么pid文件也会跟着消失
pid /var/run/nginx.pid;
#events此配置段表示配置有关事件驱动相关的配置
events {
#每个worker进程所能够打开的最大并发连接数
worker_connections 1024;
}
http {
#支持的媒体类型
include /etc/nginx/mime.types;
#默认的类型
default_type application/octet-stream;
#日志格式
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;
#是否调用sendfile函数来输出文件(高效文件传输模式)
sendfile on;
#tcp_nopush on;
#连接超时时间 (单位:秒)
keepalive_timeout 65;
#启用Gizp压缩
#gzip on;
#引入外部配置文件
include /etc/nginx/conf.d/*.conf;
}
实现负载均衡的相关配置
根据核心配置文件中引入外部配置文件的地址,创建对应的 .conf 配置文件
#负载均衡服务器集群的名称
upstream test.com {
#服务器集群相关配置,连接每一个被代理的服务器以及其中的Tomcat
server 192.168.31.216:8080; #weight=1;
server 192.168.31.216:8081; #weight=2; weight是权重的意思,权重越大nginx分配的概率越大
}
#虚拟主机配置(可虚拟多个主机)
server {
#nginx监听的端口
listen 80;
#虚拟主机名称,(使用域名或者IP)
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
#监听访问路径 /为所有访问路径
location / {
#监听到访问后,跳转到设置的服务器集群中,分配访问(//后对应upstream集群的名称)
proxy_pass http://test.com;
proxy_redirect default;
#监听到访问后查找该root地址,index为跳转的页面
#root /usr/share/nginx/html;
#index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#错误页面跳转
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
2. 使用Docker安装
下载nginx和tomcat的镜像:_docker pull nginx_
创建nginx本地目录,稍后挂载到容器内:_mkdir -p /usr/nginx/html /usr/nginx/conf/ /usr/nginx/logs_
新增修改 /usr/ngin/conf/nginx.conf 文件:
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" "$upstream_addr"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
# 负载均衡转发到下面地址
upstream tomcat {
server 172.17.0.2:8080;
server 172.17.0.4:8080;
}
server {
listen 80;
server_name localhost;
# 后台请求访问地址
location / {
proxy_pass http://tomcat;
proxy_redirect off;
index index.html index.htm;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-Port $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# 静态文件访问地址
location /static/ {
alias /usr/share/nginx/html/;
}
}
include /etc/nginx/conf.d/*.conf;
}
启动Nginx:
docker run -d -p 80:80 --name nginx -v /usr/nginx/html:/usr/share/nginx/html -v /usr/nginx/conf/nginx.conf:/etc/nginx/nginx.conf -v /usr/nginx/logs:/var/log/nginx nginx
三、Nginx的配置
- 使用文本编辑命令打开nginx目录下的conf/nginx.conf文件
- 配置文件主要由四部分组成:main(全区设置),server(主机配置),upstream(负载均衡服务器设置),和location(URL匹配特定位置设置)
1. 核心配置
- 设置worker进程的用户,指的linux中的用户,会涉及到nginx操作目录或文件的一些权限,默认为nobody | user root; | | —- |
- worker进程工作数设置,一般来说CPU有几个,就设置几个,或者设置为N-1也行 | worker_processes 1; | | —- |
nginx 日志级别debug | info | notice | warn | error | crit | alert | emerg,错误级别从左到右越来越大
设置nginx进程 pid | pid logs/nginx.pid; | | —- |
- 设置工作模式
| events {
# 默认使用epoll
use epoll;
# 每个worker允许连接的客户端最大连接数
worker_connections 10240;
} | | —- |
- http 是指令块,针对http网络传输的一些指令配置
| http {
} | | —- |
- include 引入外部配置,提高可读性,避免单个配置文件过大 | include mime.types; | | —- |
- 设定日志格式,main为定义的格式名称,如此 access_log 就可以直接使用这个变量了
- $remote_addr:客户端ip
- $remote_user:远程客户端用户名,一般为:’-’
- $time_local:时间和时区
- $request:请求的url以及method
- $status:响应状态码
- $body_bytes_send:响应客户端内容字节数
- $http_referer:记录用户从哪个链接跳转过来的
- $http_user_agent:用户所使用的代理,一般来时都是浏览器
- $http_x_forwarded_for:通过代理服务器来记录客户端的ip
- sendfile 使用高效文件传输,提升传输性能。启用后才能使用tcp_nopush,是指当数据表累积一定大小后才发送,提高了效率。
| sendfile on;
tcp_nopush on; | | —- |
- keepalive_timeout设置客户端与服务端请求的超时时间,保证客户端多次请求的时候不会重复建立新的连接,节约资源损耗。
| #keepalive_timeout 0;
keepalive_timeout 65; | | —- |
- gzip启用压缩,html/js/css压缩后传输会更快 | gzip on; | | —- |
- server可以在http指令块中设置多个虚拟主机
- listen 监听端口
- server_name localhost、ip、域名
- location 请求路由映射,匹配拦截
- root 请求位置
- index 首页设置
| server {
listen 88;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
} | | —- |
2. 全局配置
Nginx的worker进程运行用户以及用户组
user nobody nobody;
Nginx开启的进程数
worker_processes 1; #worker_processes auto; #error_log logs/error.log info;
指定进程ID存储文件位置
pid logs/nginx.pid;
3. 事件配置
events {
#use [ kqueue | rtsig | epoll | /dev/poll | select | poll ];
#epoll模型是Linux 2.6以上版本内核中的高性能网络I/O模型,如果跑在FreeBSD上面,就用kqueue模型。
use epoll;
#每个进程可以处理的最大连接数,理论上每台nginx服务器的最大连接数为worker_processes*worker_connections。理论值:worker_rlimit_nofile/worker_processes
#注意:最大客户数也由系统的可用socket连接数限制(~ 64K),所以设置不切实际的高没什么好处
worker_connections 65535;
#worker工作方式:串行(一定程度降低负载,但服务器吞吐量大时,关闭使用并行方式)
#multi_accept on;
}
4. http参数(可以配置多个虚拟主机)
#文件扩展名与文件类型映射表
include mime.types;
#默认文件类型
default_type application/octet-stream;
#日志相关定义
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#定义日志的格式。后面定义要输出的内容。
#1.$remote_addr 与$http_x_forwarded_for 用以记录客户端的ip地址;
#2.$remote_user :用来记录客户端用户名称;
#3.$time_local :用来记录访问时间与时区;
#4.$request :用来记录请求的url与http协议;
#5.$status :用来记录请求状态;
#6.$body_bytes_sent :记录发送给客户端文件主体内容大小;
#7.$http_referer :用来记录从那个页面链接访问过来的;
#8.$http_user_agent :记录客户端浏览器的相关信息
#连接日志的路径,指定的日志格式放在最后。
#access_log logs/access.log main;
#只记录更为严重的错误日志,减少IO压力
error_log logs/error.log crit;
#关闭日志
#access_log off;
#默认编码
#charset utf-8;
#服务器名字的hash表大小
server_names_hash_bucket_size 128;
#客户端请求单个文件的最大字节数
client_max_body_size 8m;
#指定来自客户端请求头的hearerbuffer大小
client_header_buffer_size 32k;
#指定客户端请求中较大的消息头的缓存最大数量和大小。
large_client_header_buffers 4 64k;
#开启高效传输模式。
sendfile on;
#防止网络阻塞
tcp_nopush on;
tcp_nodelay on;
#客户端连接超时时间,单位是秒
keepalive_timeout 60;
#客户端请求头读取超时时间
client_header_timeout 10;
#设置客户端请求主体读取超时时间
client_body_timeout 10;
#响应客户端超时时间
send_timeout 10;
#FastCGI相关参数是为了改善网站的性能:减少资源占用,提高访问速度。
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;
#gzip模块设置
#开启gzip压缩输出
gzip on;
#最小压缩文件大小,小于这个数就不会压缩
gzip_min_length 1k;
#压缩缓冲区
gzip_buffers 4 16k;
#压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
gzip_http_version 1.0;
#压缩等级 1-9 等级越高,压缩效果越好,节约宽带,但CPU消耗大
gzip_comp_level 2;
#压缩类型,默认就已经包含text/html,所以下面就不用再写了,写上去也不会有问题,但是会有一个warn。
gzip_types text/plain application/x-javascript text/css application/xml;
#前端缓存服务器缓存经过压缩的页面
gzip_vary on;
5. 虚拟主机监控配置
#虚拟主机定义
server {
#监听端口
listen 80;
#访问域名
server_name localhost;
#编码格式,若网页格式与此不同,将被自动转码
#charset koi8-r;
#虚拟主机访问日志定义
#access_log logs/host.access.log main;
#对URL进行匹配
location / {
#访问路径,可相对(相对于Nginx的安装路径)也可绝对路径(linux操作系统的/根据 /usr/local/nginx/html)
root html;
#首页文件。以下按顺序匹配
index index.html index.htm;
}
#错误信息返回页面
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
#访问URL以.php结尾则自动转交给127.0.0.1
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
#php脚本请求全部转发给FastCGI处理
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
#禁止访问.ht页面 (需ngx_http_access_module模块)
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
#HTTPS虚拟主机定义
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
6. nginx状态监控
#Nginx运行状态,StubStatus模块获取Nginx自启动的工作状态(编译时要开启对应功能)
#location /NginxStatus {
# #启用StubStatus的工作访问状态
# stub_status on;
# #指定StubStaus模块的访问日志文件
# access_log logs/Nginxstatus.log;
# #Nginx认证机制(需Apache的htpasswd命令生成)
# #auth_basic "NginxStatus";
# #用来认证的密码文件
# #auth_basic_user_file ../htpasswd;
#}
访问:http://IP/NginxStatus(测试就不加密码验证相关)
7. Nginx解决跨域问题
server{
listen 5000;
server_name localhost;
location = / {
proxy_pass http://localhost:3000/;
}
location /test {
proxy_pass http://localhost:3000/test;
# 指定允许跨域的方法,*代表所有
add_header Access-Control-Allow-Methods *;
# 预检命令的缓存,如果不缓存每次会发送两次请求
add_header Access-Control-Max-Age 3600;
# 带cookie请求需要加上这个字段,并设置为true
add_header Access-Control-Allow-Credentials true;
# 表示允许这个域跨域调用(客户端发送请求的域名和端口)
# $http_origin动态获取请求客户端请求的域 不用*的原因是带cookie的请求不支持*号
add_header Access-Control-Allow-Origin $http_origin;
# 表示请求头的字段 动态获取
add_header Access-Control-Allow-Headers
$http_access_control_request_headers;
# OPTIONS预检命令,预检命令通过时才发送请求
# 检查请求的类型是不是预检命令
if ($request_method = OPTIONS){
return 200;
}
}
}
8. 防盗链配置
在server中添加配置
#对源站点验证
valid_referers *.xyao.com;
#非法引入会进入下方判断
if ($invalid_referer) {
return 404;
}
9. Nginx缓存设置
Nginx控制浏览器缓存
使用expires设置过期时间
location /static{
alias /home/html
# expires 10s;
# expires @22h30m; #指定时间
# expires -1h; #缓存提前过期
# expires epoch;
# expires off;
expires max;
}
在响应头中会有Cache-Control或者Expires字段控制过期的时间
Nginx缓存其他服务器数据
浏览器缓存:加速用户访问,提升单个用户(浏览器访问者)体验,缓存在本地
location /files { alias /home/imooc; # expires 10s; # expires @22h30m; # expires -1h; # expires epoch; # expires off; expires max; }
Nginx缓存
- 缓存在nginx端,提升所有访问到nginx这一端的用户
- 提升访问上游(upstream)服务器的速度
- 用户访问仍然会产生请求流量
# proxy_cache_path 设置缓存目录
# keys_zone 设置共享内存以及占用空间大小
# max_size 设置缓存大小
# inactive 超过此时间则被清理
# use_temp_path 临时目录,使用后会影响nginx性能
proxy_cache_path /usr/local/nginx/upstream_cache keys_zone=mycache:5m max_size=1g inactive=1m use_temp_path=off;
location / {
proxy_pass http://tomcats;
# 启用缓存,和keys_zone一致
proxy_cache mycache;
# 针对200和304状态码缓存时间为8小时
proxy_cache_valid 200 304 8h;
}
10. 反向代理
以下配置追加在HTTP的全局变量中
#nginx跟后端服务器连接超时时间(代理连接超时)
proxy_connect_timeout 5;
#后端服务器数据回传时间(代理发送超时)
proxy_send_timeout 5;
#连接成功后,后端服务器响应时间(代理接收超时)
proxy_read_timeout 60;
#设置代理服务器(nginx)保存用户头信息的缓冲区大小
proxy_buffer_size 16k;
#proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
proxy_buffers 4 32k;
#高负荷下缓冲大小(proxy_buffers*2)
proxy_busy_buffers_size 64k;
#设定缓存文件夹大小,大于这个值,将从upstream服务器传
proxy_temp_file_write_size 64k;
#反向代理缓存目录
proxy_cache_path /data/proxy/cache levels=1:2 keys_zone=cache_one:500m inactive=1d max_size=1g;
#levels=1:2 设置目录深度,第一层目录是1个字符,第2层是2个字符
#keys_zone:设置web缓存名称和内存缓存空间大小
#inactive:自动清除缓存文件时间。
#max_size:硬盘空间最大可使用值。
#指定临时缓存文件的存储路径(路径需和上面路径在同一分区)
proxy_temp_path
/data/proxy/temp
#服务配置
server {
#侦听的80端口
listen 80;
server_name localhost;
location / {
#反向代理缓存设置命令(proxy_cache zone|off,默认关闭所以要设置)
proxy_cache cache_one;
#对不同的状态码缓存不同时间
proxy_cache_valid 200 304 12h;
#设置以什么样参数获取缓存文件名
proxy_cache_key $host$uri$is_args$args;
#后7端的Web服务器可以通过X-Forwarded-For获取用户真实IP
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#代理设置
proxy_pass http://IP;
#文件过期时间控制
expires 1d;
}
#配置手动清除缓存(实现此功能需第三方模块 ngx_cache_purge)
#http://www.123.com/2017/0316/17.html访问
#http://www.123.com/purge/2017/0316/17.html清楚URL缓存
location ~ /purge(/.*) {
allow 127.0.0.1;
deny all;
proxy_cache_purge cache_one $host$1$is_args$args;
}
#设置扩展名以.jsp、.php、.jspx结尾的动态应用程序不做缓存
location ~.*\.(jsp|php|jspx)?$ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://http://IP;
}
}
11. 负载均衡
#负载均衡服务器池
upstream my_server_pool {
#调度算法
#1.轮循(默认)(weight轮循权值)
#2.ip_hash:根据每个请求访问IP的hash结果分配。(会话保持)
#3.fair:根据后端服务器响应时间最短请求。(upstream_fair模块)
#4.url_hash:根据访问的url的hash结果分配。(需hash软件包)
#参数:
#down:表示不参与负载均衡
#backup:备份服务器
#max_fails:允许最大请求错误次数
#fail_timeout:请求失败后暂停服务时间。
server 192.168.1.109:80 weight=1 max_fails=2 fail_timeout=30;
server 192.168.1.108:80 weight=2 max_fails=2 fail_timeout=30;
}
#负载均衡调用
server {
...
location / {
proxy_pass http://my_server_pool;
}
}
12. URL重写
#根据不同的浏览器URL重写
if($http_user_agent ~ Firefox){
rewrite ^(.*)$ /firefox/$1 break;
}
if($http_user_agent ~ MSIE){
rewrite ^(.*)$ /msie/$1 break;
}
#实现域名跳转
location / {
rewrite ^/(.*)$ https://web8.example.com$1 permanent;
}
13. IP限制
#限制IP访问
location / {
deny 192.168.0.2;
allow 192.168.0.0/24;
allow 192.168.1.1;
deny all;
}
四、动静分离
1. 技术介绍
为了提高网站的响应速度,减轻程序服务器(Tomcat,Jboss等)的负载,对于静态资源比如图片,js,css等文件,我们可以在反向代理服务器中进行缓存,这样浏览器在请求一个静态资源时,代理服务器就可以直接处理,而不用将请求转发给后端服务器。用户请求的动态文件比如servlet,jsp则转发给Tomcat,Jboss服务器处理,这就是动静分离。这也是反向代理服务器的一个重要的作用。
本文的动静分离主要是通过nginx+tomcat来实现,其中nginx处理图片、html、JS、CSS等静态文件,tomcat处理jsp、servlet等动态请求。以下架构虽然实现了动静分离,但是服务器还要专门开放8080端口,将来要是有多个tomcat还要开发多个端口,并不是很好的选择
- 可以使用nginx做代理服务器,然后根据location对请求的路径进行分发
2. 简化配置
server {
listen 88;
server_name localhost;
#静态资源
location ~* \.(png|apk|html|js|css)$ {
root /upload;
}
#动态资源
location / {
proxy_pass http://192.168.71.101:8080;
}
}
如果出现无法访问的情况,可以将当前用户设置为root
user root;
3. location语法详解
1. 语法规则
location [=|~|~*|^~] /uri/ { … } |
---|
=
开头表示精确匹配^~
开头表示uri以某个常规字符串开头,理解为匹配 url路径即可。nginx不对url做编码,因此请求为/static/20%/aa,可以被规则^~ /static/ /aa匹配到(注意是空格)。以xx开头~
开头表示区分大小写的正则匹配 以xx结尾~*
开头表示不区分大小写的正则匹配 以xx结尾!~
和!~*
分别为区分大小写不匹配及不区分大小写不匹配的正则/
通用匹配,任何请求都会匹配到。
2. 优先级
首先精确匹配 =-》其次以xx开头匹配^~-》然后是按文件中顺序的正则匹配-》最后是交给 / 通用匹配
3. 规则案例
=:精确匹配
location = / {
#规则A
}
location = /login {
#规则B
}
以某个字符路径开头
location ^~ /static/ {
#规则C
}
location ~ \.(gif|jpg|png|js|css)$ {
#规则D,注意:是根据括号内的大小写进行匹配。括号内全是小写,只匹配小写
}
~*:匹配正则表达式,不区分大小写
location ~* \.png$ {
#规则E
}
#符合图片的显示
location ~* .(GIF|jpg|png|jpeg) {
root /home;
}
~:匹配正则表达式,区分大小写
#GIF必须大写才能匹配到
location ~ .(GIF|jpg|png|jpeg) {
root /home;
}
location !~ \.xhtml$ {
#规则F
}
location !~* \.xhtml$ {
#规则G
}
location / {
#规则H
}
那么产生的效果如下:
访问根目录/,比如http://localhost/ 将匹配规则A
访问 http://localhost/login 将匹配规则B,http://localhost/register 则匹配规则H
访问 http://localhost/static/a.html 将匹配规则C
访问 http://localhost/a.gif, http://localhost/b.jpg 将匹配规则D和规则E,但是规则D顺序优先,规则E不起作用,而 http://localhost/static/c.png 则优先匹配到规则C
访问 http://localhost/a.PNG 则匹配规则E,而不会匹配规则D,因为规则E不区分大小写。
访问 http://localhost/a.xhtml 不会匹配规则F和规则G,
http://localhost/a.XHTML不会匹配规则G,(因为!)。规则F,规则G属于排除法,符合匹配规则也不会匹配到,所以想想看实际应用中哪里会用到。
访问 http://localhost/category/id/1111 则最终匹配到规则H,因为以上规则都不匹配,这个时候nginx转发请求给后端应用服务器,比如FastCGI(php),tomcat(jsp),nginx作为方向代理服务器存在。
4. 常用规则
#直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。 #这里是直接转发给后端应用服务器了,也可以是一个静态首页 # 第一个必选规则 location = / { proxy_pass http://tomcat:8080/index } # 第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项 # 有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用 location ^~ /static/ { //以xx开头 root /webroot/static/; } location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ { //以xx结尾 root /webroot/res/; } #第三个规则就是通用规则,用来转发动态请求到后端应用服务器 #非静态文件请求就默认是动态请求,自己根据实际把握 location / { proxy_pass http://tomcat:8080/ } |
---|
4. 静态资源服务配置
1,将静态资源复制到home的www目录下
2,在配置文件中进行配置
server {
listen 88;
server_name localhost;
location / {
root /home/www;
index index.html index.htm;
}
location /static{
#root /home;
alias /home/xyao
}
}
5. root 与 alias
- 假如服务器路径为:/home/xyao/files/img/face.png
root 路径完全匹配访问
配置的时候为:
location /xyao {
root /home
}
用户访问的时候请求为:url:port/xyao/files/img/face.png
- alias 可以为你的路径做一个别名,对用户透明
配置的时候为:
location /hello {
alias /home/xyao
}
用户访问的时候请求为:url:port/hello/files/img/face.png,如此相当于为目录xyao做一个自定义的别名。
五、Nginx配置Https
1. Http与Https的区别
HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。
HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。
HTTPS和HTTP的区别主要如下:
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
2. 使用openssl生成证书
1,openssl是目前最流行的SSL密码库工具,其提供了一个通用、健壮、功能完备的工具套件,用以支持SSL/TLS协议的实现。比如生成到:/usr/local/ssl
openssl req -x509 -nodes -days 36500 -newkey rsa:2048 -keyout /usr/local/ssl/nginx.key -out /usr/local/ssl/nginx.crt
2,生成过程:
[root@iZwz9hmxhr8nh72bwa5lbxZ ~]# openssl req -x509 -nodes -days 36500 -newkey rsa:2048 -keyout /usr/local/ssl/nginx.key -out /usr/local/ssl/nginx.crt
Generating a 2048 bit RSA private key
...............................................................................+ ++
...............+++
writing new private key to '/usr/local/ssl/nginx.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:beijing
Locality Name (eg, city) [Default City]:beijing
Organization Name (eg, company) [Default Company Ltd]:xxxx
Organizational Unit Name (eg, section) []:xxxx
Common Name (eg, your name or your server's hostname) []:xxxx(一般是域名)
Email Address []:xxxx@xxxx.com
[root@iZwz9hmxhr8nh72bwa5lbxZ ~]# ll
total 8
-rw-r--r--. 1 root root 1391 Apr 21 13:29 nginx.crt
-rw-r--r--. 1 root root 1704 Apr 21 13:29 nginx.key
3. Nginx安装http_ssl_module模块
Nginx如果未开启SSL模块,配置Https时提示错误。
nginx: [emerg] the "ssl" parameter requires ngx_http_ssl_module in /usr/local/nginx/conf/nginx.conf:xxx
nginx缺少http_ssl_module模块,编译安装的时候带上—with-http_ssl_module配置就行了。
本场景是服务器已经安装过nginx,但是未安装http_ssl_module。
安装ssl插件
yum -y install openssl openssl-devel
进入到源码包,如:
cd /root/nginx-1.10.3
configure:配置ssl
./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module
make:
make
不需要执行make install,否则就覆盖安装了。
备份原有的nginx,(可选)如:
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx_bak
然后将刚刚编译好的nginx覆盖掉原有的nginx(nginx需要停止)
cp ./objs/nginx /usr/local/nginx/sbin/
查看安装情况:
/usr/local/nginx/sbin/nginx -V
4. nginx配置https
- 配置https服务器
```
server {
listen 443 ssl;
server_name www.yourdomain.com;
ssl_certificate /usr/local/ssl/nginx.crt;
ssl_certificate_key /usr/local/ssl/nginx.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
禁止在header中出现服务器版本,防止黑客利用版本漏洞攻击
server_tokens off;如果是全站 HTTPS 并且不考虑 HTTP 的话,可以加入 HSTS 告诉你的浏览器本网站全站加密,并且强制用 HTTPS 访问
fastcgi_param HTTPS on; fastcgi_param HTTP_SCHEME https; access_log /usr/local/nginx/logs/httpsaccess.log; location / {
}root html; index index.html index.htm; }
2. 先检验配置的对不对:
/usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
3,使用http跳转https
server { listen 80; server_name www.yourdomain.com; rewrite ^(.*) https://$server_name$1 permanent; #http 跳转 https }
<a name="zV69t"></a>
## 5. 使用Https访问
1. 打开地址栏使用https访问
```http
https://192.168.174.133/
- 由于是证书是自己的创建的所以不安全
- 注意打开443端口
firewall-cmd --zone=public --add-port=443/tcp
6. 专业证书的申请
Nginx配置
注意最后配置的时候,域名要和申请的域名保持一致
server {
listen 443;
server_name bjubi.com; // 你的域名
ssl on;
root /var/www/bjubi.com; // 前台文件存放文件夹,可改成别的
index index.html index.htm;// 上面配置的文件夹里面的index.html
ssl_certificate cert/214292799730473.pem;// 改成你的证书的名字
ssl_certificate_key cert/214292799730473.key;// 你的证书的名字
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
index index.html index.htm;
}
}
server {
listen 80;
server_name bjubi.com;// 你的域名
rewrite ^(.*)$ https://$host$1 permanent;// 把http的域名请求转成https
}
六、将nginx作为文件服务器
1. 安装vsftp
[root@bogon ~]# yum -y install vsftpd
1. 安装vsftpd组件
安装完后,有/etc/vsftpd/vsftpd.conf 文件,是vsftp的配置文件。
启动ftp服务器
Centos7.0启动方式: systemctl start vsftpd.service
Centos6.x 启动方式: service vsftpd start
查看ftp服务器启动的情况
service vsftpd status
2. 安装ftp的客户端(部署用)
在防火墙中放行21端口(21是ftp的端口,22是sftp的端口)
firewall-cmd —zone=public —add-port=21/tcp
firewall-cmd —list-ports (查看防火墙,放行的端口)
打开客户端的的主动模式
可以直接使用匿名访问进行测试
3. 关闭匿名访问
修改/etc/vsftpd/vsftpd.conf文件:
重启ftp服务:
service vsftpd restart
4. 添加一个Linux用户
此用户就是用来登录ftp服务器用的。
[root@bogon ~]# useradd ftpuser
这样一个用户建完,可以用这个登录,记得用普通登录不要用匿名了。登录后默认的路径为 /home/ftpuser.
5. 给ftp用户添加密码。
[root@bogon ~]# passwd ftpuser
输入两次密码后修改密码。
2. 配置nginx的图片路径地址
3. 设置访问ftp路径的用户
4. Ftp传送文件(代码)
1,导入相关的依赖
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-ftp</artifactId>
<version>2.13.2</version>
</dependency>
2,实现FtpUtil类
package com.learn.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
/**
* ftp上传下载工具类
* <p>Title: FtpUtil</p>
* <p>Description: </p>
*/
public class FtpUtil {
/**
* Description: 向FTP服务器上传文件
* @param host FTP服务器hostname
* @param port FTP服务器端口
* @param username FTP登录账号
* @param password FTP登录密码
* @param basePath FTP服务器基础目录
* @param filePath FTP服务器文件存放路径。例如分日期存放:/2015/01/01。文件的路径为basePath+filePath
* @param filename 上传到FTP服务器上的文件名
* @param input 输入流
* @return 成功返回true,否则返回false
*/
public static boolean uploadFile(String host, int port, String username, String password, String basePath,
String filePath, String filename, InputStream input) {
boolean result = false;
FTPClient ftp = new FTPClient();
try {
int reply;
ftp.connect(host, port);// 连接FTP服务器
// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
ftp.login(username, password);// 登录
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return result;
}
//切换到上传目录
if (!ftp.changeWorkingDirectory(basePath+filePath)) {
//如果目录不存在创建目录
String[] dirs = filePath.split("/");
String tempPath = basePath;
for (String dir : dirs) {
if (null == dir || "".equals(dir)) continue;
tempPath += "/" + dir;
if (!ftp.changeWorkingDirectory(tempPath)) {
if (!ftp.makeDirectory(tempPath)) {
return result;
} else {
ftp.changeWorkingDirectory(tempPath);
}
}
}
}
//设置上传文件的类型为二进制类型
ftp.setFileType(FTP.BINARY_FILE_TYPE);
//上传文件
if (!ftp.storeFile(filename, input)) {
return result;
}
input.close();
ftp.logout();
result = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
}
}
}
return result;
}
/**
* Description: 从FTP服务器下载文件
* @param host FTP服务器hostname
* @param port FTP服务器端口
* @param username FTP登录账号
* @param password FTP登录密码
* @param remotePath FTP服务器上的相对路径
* @param fileName 要下载的文件名
* @param localPath 下载后保存到本地的路径
* @return
*/
public static boolean downloadFile(String host, int port, String username, String password, String remotePath,
String fileName, String localPath) {
boolean result = false;
FTPClient ftp = new FTPClient();
try {
int reply;
ftp.connect(host, port);
// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
ftp.login(username, password);// 登录
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return result;
}
ftp.changeWorkingDirectory(remotePath);// 转移到FTP服务器目录
FTPFile[] fs = ftp.listFiles();
for (FTPFile ff : fs) {
if (ff.getName().equals(fileName)) {
File localFile = new File(localPath + "/" + ff.getName());
OutputStream is = new FileOutputStream(localFile);
ftp.retrieveFile(ff.getName(), is);
is.close();
}
}
ftp.logout();
result = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
}
}
}
return result;
}
public static void main(String[] args) {
try {
FileInputStream in=new FileInputStream(new File("F:\\upload\\a2.png"));
boolean flag = uploadFile("192.168.59.144", 21, "root", "123456", "/home/ftpuser","/www/images/", "2.png", in);
System.out.println(flag);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}