Nginx概述
一个具有高性能的HTTP
和反向代理
的WEB服务器
,同时也是一个POP3,SMTP,IMAP代理服务器
反向代理
正向代理为客户端提供服务;反向代理为服务端提供服务
反向代理服务器位于用户与目标服务器之间,但是对于用户而言,反向代理服务器就相当于目标服务器,即用户直接访问反向代理服务器就可以获得目标服务器的资源。同时,用户不需要知道目标服务器的地址,也无须在用户端作任何设定。反向代理服务器通常可用来作为Web加速,即使用反向代理作为Web服务器的前置机来降低网络和服务器的负载,提高访问效率。
Nginx的优点
- 速度更快,并发更高:多进程+epoll
- 配置简单,扩展性强:模块化设计
- 高可靠性:master和worker多进程
- 热部署
- 成本低:基于BSD许可证
BSD是一个开源的许可证,世界上的开源许可证有很多,现在比较流行的有六种分别是GPL、BSD、MIT、Mozilla、Apache、LGPL。这六种的区别是什么,我们可以通过下面一张图来解释下:
所以我们可以免费的将Nginx应用在商业领域
两个基于nginx的应用:OpenRestry [Nginx+Lua]和Tengine[淘宝]
Nginx的常用功能
主要包括以下三种:
- 基本http服务
- 高级http服务
- 邮件服务
Nginx常用的功能模块:
- 静态资源部署
- Rewrite地址重写:正则表达式
- 反向代理
- 负载均衡:轮询,加权轮询,ip_hash,url_hash,fair
- Web缓存
- 环境部署:高可用的环境
- 用户认证模块
Nginx的核心组成
- nginx二进制可执行文件
- nginx.conf配置文件
- error.log错误日志文件
- access.log访问日志文件
安装Nginx
centos关闭防火墙:
- 关闭运行的防火墙,系统重新启动后,防火墙将重新打开:
systemctl stop firewalld
- 永久关闭防火墙,系统重新启动后,防火墙依然关闭:
systemctl disable firewalld
- 查看防火墙状态:
systemctl status firewalld
centos设置selinux:
查看状态:sestatus
设定关闭,修改配置文件:vim /etc/selinux/config
Nginx的安装方式:
通过Nginx源码
通过Nginx源码简单安装 (1)
通过Nginx源码复杂安装 (3)
通过yum安装 (2)
源码安装需要提前准备好的工具和库:gcc, pcre, zlib, openssl
sudo yum install -y gcc pcre pcre-devel zlib zlib-devel openssl openssl-devel
#检查
rpm -qa pcre pcre-devel zlib zlib-devel openssl openssl-devel
通过Nginx源码简单安装
创建目录:
mkdir -p nginx/core
cd nginx/core/
使用wget下载源码并解压:
wget http://nginx.org/download/nginx-1.20.1.tar.gz
tar -zxvf nginx-1.20.1.tar.gz
检查编译安装:
./configure
make && make install
存放路径:/usr/local/nginx
。目录结构:
$ pwd
/usr/local/nginx
$ ls
conf html logs sbin
启动nginx:
cd sbin && ./nginx
通过yum安装nginx
sudo yum install -y yum-utils
# 添加yum源文件
vim /etc/yum.repos.d/nginx.repo
cat /etc/yum.repos.d/nginx.repo
#output
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
查看是否安装成功:
yum list | grep nginx
使用yum进行安装:
yun install -y nginx
查看nginx的安装位置:
whereis nginx
简单源码安装与yum安装的区别:
源码简单安装,通过./nginx -V
查看版本及相关配置信息:
$ ./nginx -V
nginx version: nginx/1.20.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
configure arguments:
对于使用yum安装的情况,其configure
参数情况要复杂得多
通过Nginx源码复杂安装
PATH:是和路径相关的配置信息
with:是启动模块,默认是关闭的;without:是关闭模块,默认是开启的。这两者一般用于添加插件
一些简单的路径配置:
--prefix=PATH
指向Nginx的安装目录,默认值为/usr/local/nginx
--sbin-path=PATH
指向(执行)程序文件(nginx)的路径,默认值为<prefix>/sbin/nginx
--modules-path=PATH
指向Nginx动态模块安装目录,默认值为<prefix>/modules
--conf-path=PATH
指向配置文件(nginx.conf)的路径,默认值为<prefix>/conf/nginx.conf
--error-log-path=PATH
指向错误日志文件的路径,默认值为<prefix>/logs/error.log
--http-log-path=PATH
指向访问日志文件的路径,默认值为<prefix>/logs/access.log
--pid-path=PATH
指向Nginx启动后进行ID的文件路径,默认值为<prefix>/logs/nginx.pid
--lock-path=PATH
指向Nginx锁文件的存放路径,默认值为<prefix>/logs/nginx.lock
如何卸载nginx:
./nginx -s stop #停止进程
rm -rf /usr/local/nginx #删除文件
make clean #清除编译环境
通过源码指定参数复杂安装:
$ ./configure --prefix=/usr/local/nginx \
> --sbin-path=/usr/local/nginx/sbin/nginx \
> --modules-path=/usr/local/nginx/modules \
> --conf-path=/usr/local/nginx/conf/nginx.conf \
> --error-log-path=/usr/local/nginx/logs/error.log \
> --http-log-path=/usr/local/nginx/logs/access.log \
> --pid-path=/usr/local/nginx/logs/nginx.pid \
> --lock-path=/usr/local/nginx/logs/nginx.lock
Nginx目录结构分析
重要的目录:
$ pwd
/usr/local/nginx
$ ls
conf html logs sbin
conf
目录下是相关配置文件:
$ pwd
/usr/local/nginx/conf
$ ls
fastcgi.conf fastcgi_params koi-utf mime.types nginx.conf scgi_params uwsgi_params win-utf
fastcgi.conf.default fastcgi_params.default koi-win mime.types.default nginx.conf.default scgi_params.default uwsgi_params.default
logs
目录下是日志文件:
$ pwd
/usr/local/nginx/logs
$ ls
access.log error.log nginx.pid
log/access.log
:访问日志文件
112.17.245.19 - - [27/Aug/2021:19:04:34 +0800] "GET /ab HTTP/1.1" 404 555 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36"
log/error.log
:错误日志文件
2021/08/27 19:04:34 [error] 25733#0: *29 open() "/usr/local/nginx/html/ab" failed (2: No such file or directory), client: 112.17.245.19, server: localhost, request: "GET /ab HTTP/1.1", host: "116.62.20.151"
log/nginx.pid
:进程id
sbin
目录下是nginx的可执行文件:
$ pwd
/usr/local/nginx/sbin
$ ls
nginx
html
目录下是网页资源文件:
$ pwd
/usr/local/nginx/html
$ ls
50x.html index.html
启动Nginx
Nginx有两种启停方式:
- Nginx的信号控制
- Nginx的命令行控制
Nginx服务的信号控制
Nginx中的master和worker进程?
Nginx的工作方式?
如何获取进程的PID?
信号有哪些?
如何通过信号控制Nginx的启停等相关操作?
查看当前Nginx的进程:
$ ps -ef | grep nginx
root 25732 1 0 18:39 ? 00:00:00 nginx: master process ./nginx
nobody 25733 25732 0 18:39 ? 00:00:00 nginx: worker process
root 26035 25041 0 19:21 pts/0 00:00:00 grep --color=auto nginx
Nginx后台进程中包含一个master进程和多个worker进程,master进程主要用来管理worker进程,包含接收外界的信息,并将接收到的信号发送给各个worker进程,监控worker进程的状态,当worker进程出现异常退出后,会自动重新启动新的worker进程。而worker进程则是专门用来处理用户请求的,各个worker进程之间是平等的并且相互独立,处理请求的机会也是一样的。nginx的进程模型,我们可以通过下图来说明下:
我们现在作为管理员,只需要通过给master进程发送信号就可以来控制Nginx
获取pid的两种方式:
$ ps -ef | grep nginx
root 14175 1 0 09:34 ? 00:00:00 nginx: master process ./nginx
nobody 14177 14175 0 09:34 ? 00:00:00 nginx: worker process
root 14217 4154 0 09:34 pts/1 00:00:00 grep --color=auto nginx
$ cat ../logs/nginx.pid
14175
控制信号:
信号 | 作用 |
---|---|
TERM/INT | 立即关闭整个服务 |
QUIT | "优雅"地关闭整个服务 |
HUP | 重读配置文件并使用服务对新配置项生效 |
USR1 | 重新打开日志文件,可以用来进行日志切割 |
USR2 | 平滑升级到最新版的nginx |
WINCH | 所有子进程不在接收处理新连接,相当于给work进程发送QUIT指令 |
发送TERM/INT信号给master进程,会将Nginx服务立即关闭:
$ kill -TERM 14175
$ kill -TERM `cat /usr/local/nginx/logs/nginx.pid`
$ kill -INT 14175
$ kill -INT `cat /usr/local/nginx/logs/nginx.pid`
发送QUIT信号给master进程,master进程会控制所有的work进程不再接收新的请求,等所有请求处理完后,在把进程都关闭掉:
$ kill -QUIT 14175
$ kill -TERM `cat /usr/local/nginx/logs/nginx.pid`
发送HUP信号给master进程,master进程会把控制旧的work进程不再接收新的请求,等处理完请求后将旧的work进程关闭掉,然后根据nginx的配置文件重新启动新的work进程:
$ kill -HUP 14175
$ kill -TERM `cat /usr/local/nginx/logs/nginx.pid`
发送USR1信号给master进程,告诉Nginx重新开启日志文件:
$ kill -USR1 14175
$ kill -TERM `cat /usr/local/nginx/logs/nginx.pid`
#查看当前Nginx的进程状态
$ ps -ef | grep nginx
root 26088 1 0 19:30 ? 00:00:00 nginx: master process ./nginx
nobody 26089 26088 0 19:30 ? 00:00:00 nginx: worker process
root 26443 26397 0 20:26 pts/1 00:00:00 grep --color=auto nginx
#发送USR2信号
$ kill -USR2 26088
$ cd /usr/local/nginx/
#nginx.pid.olbbin文件记录了旧进程的pid
$ tree logs/
logs/
├── access.log
├── error.log
├── nginx.pid
└── nginx.pid.oldbin
0 directories, 4 files
$ cat logs/nginx.pid.oldbin
26088
#现在旧进程和新进程共存
$ ps -ef | grep nginx
root 26088 1 0 19:30 ? 00:00:00 nginx: master process ./nginx
nobody 26089 26088 0 19:30 ? 00:00:00 nginx: worker process
root 26446 26088 0 20:26 ? 00:00:00 nginx: master process ./nginx
nobody 26447 26446 0 20:26 ? 00:00:00 nginx: worker process
root 26461 26397 0 20:27 pts/1 00:00:00 grep --color=auto nginx
#杀死旧进程
$ kill -QUIT 26088
#查看当前Nginx的进程状态
$ ps -ef | grep nginx
root 26446 1 0 20:26 ? 00:00:00 nginx: master process ./nginx
nobody 26447 26446 0 20:26 ? 00:00:00 nginx: worker process
root 26465 26397 0 20:28 pts/1 00:00:00 grep --color=auto nginx
发送USR2信号给master进程,告诉master进程要平滑升级,这个时候,会重新开启对应的master进程和work进程,整个系统中将会有两个master进程,并且新的master进程的PID会被记录在/usr/local/nginx/logs/nginx.pid
而之前的旧的master进程PID会被记录在/usr/local/nginx/logs/nginx.pid.oldbin
文件中,接着再次发送QUIT信号给旧的master进程,让其处理完请求后再进行关闭
kill -USR2 PID
kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`
kill -QUIT PID
kill -QUIT `cat /usr/local/nginx/logs/nginx.pid.oldbin`
Nginx服务的命令行控制
列出帮助选项:
$ ./nginx -h
nginx version: nginx/1.20.1
Usage: nginx [-?hvVtTq] [-s signal] [-p prefix]
[-e filename] [-c filename] [-g directives]
Options:
-?,-h : this help
-v : show version and exit
-V : show version and configure options then exit
-t : test configuration and exit
-T : test configuration, dump it and exit
-q : suppress non-error messages during configuration testing
-s signal : send signal to a master process: stop, quit, reopen, reload
-p prefix : set prefix path (default: /usr/local/nginx/)
-e filename : set error log file (default: /usr/local/nginx/logs/error.log)
-c filename : set configuration file (default: /usr/local/nginx/conf/nginx.conf)
-g directives : set global directives out of configuration file
-?和-h:显示帮助信息
-v:打印版本号信息并退出
-V:打印版本号信息和配置信息并退出
-t:测试nginx的配置文件语法是否正确并退出
-T:测试nginx的配置文件语法是否正确并列出用到的配置文件信息然后退出
-q:在配置测试期间禁止显示非错误消息
-s:signal信号,后面可以跟 :
stop[快速关闭,类似于TERM/INT信号的作用]
quit[优雅的关闭,类似于QUIT信号的作用]
reopen[重新打开日志文件类似于USR1信号的作用]
reload[类似于HUP信号的作用]
-p:prefix,指定Nginx的prefix路径,(默认为: /usr/local/nginx/)
-c:filename,指定Nginx的配置文件路径,(默认为: conf/nginx.conf)
-g:用来补充Nginx配置文件,向Nginx服务指定启动时应用全局的配置
-v
与-V
的区别:
$ ./nginx -v
nginx version: nginx/1.20.1
$ ./nginx -V
nginx version: nginx/1.20.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
configure arguments: --prefix=/usr/local/nginx --sbin-path=/usr/local/nginx/sbin/nginx --modules-path=/usr/local/nginx/modules --conf-path=/usr/local/nginx/conf/nginx.conf --error-log-path=/usr/local/nginx/logs/error.log --http-log-path=/usr/local/nginx/logs/access.log --pid-path=/usr/local/nginx/logs/nginx.pid --lock-path=/usr/local/nginx/logs/nginx.lock
-t
测试nginx.conf
语法是否正确:
$ ./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
Nginx配置文件
文件结构
#全局块,主要设置Nginx服务器整体运行的配置指令
#指令名 指令值;
worker_processes 1;
#events块,主要设置,Nginx服务器与用户的网络连接,这一部分对Nginx服务器的性能影响较大
events {
worker_connections 1024;
}
#http块,是Nginx服务器配置中的重要部分,代理、缓存、日志记录、第三方模块配置...
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
#server块,是Nginx配置和虚拟主机相关的内容
server {
listen 80;
server_name localhost;
#location块,基于Nginx服务器接收请求字符串与location后面的值进行匹配,对特定请求进行处理
location / {
root html;
index index.html index.htm;
}
#状态码是50x时返回的错误页面
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
nginx.con
f配置文件中默认有三大块:全局块、events块、http块
http
块中可以配置多个server
块,每个server
块又可以配置多个location
块
http {
server1 {
location1
location2
...
}
server2 {
location1
location2
...
}
...
}
重新加载配置文件:
$ nginx -s reload
user
用于配置运行Nginx服务器的worker进程的用户和用户组,属于全局块
语法 | user user [group] |
---|---|
默认值 | nobody |
位置 | 全局块 |
该属性也可以在编译的时候指定,语法如下./configure --user=user --group=group
如果两个地方都进行了设置,最终生效的是配置文件中的配置
该指令的使用步骤:
设置一个用户信息"daniel":
user daniel;
创建/root/html/index.html
页面
修改nginx.conf
:
location / {
root /root/html;
index index.html index.htm;
}
测试配置文件语法并reload服务器:
./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
./nginx -s reload
测试启动访问:页面会报403拒绝访问的错误
分析原因:因为当前用户没有访问/root/html目录的权限
将文件创建到 /home/www/html/index.html
,修改配置:
location / {
root /home/www/html;
index index.html index.htm;
}
再次测试启动,能正常访问
综上所述,使用user指令可以指定启动运行工作进程的用户及用户组,这样对于系统的权限访问控制的更加精细,也更加安全
$ ps -ef | grep nginx
root 31982 1 0 17:52 ? 00:00:00 nginx: master process ./nginx
nobody 31983 31982 0 17:52 ? 00:00:00 nginx: worker process
root 31987 31849 0 17:52 pts/0 00:00:00 grep --color=auto nginx
$ vim ../conf/nginx.conf
$ ./nginx -t
nginx: [emerg] getpwnam("www") failed in /usr/local/nginx/conf/nginx.conf:2
nginx: configuration file /usr/local/nginx/conf/nginx.conf test failed
$ useradd www
$ ./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
$ ./nginx -s reload
$ ps -ef | grep nginx
root 31982 1 0 17:52 ? 00:00:00 nginx: master process ./nginx
www 32011 31982 0 17:53 ? 00:00:00 nginx: worker process
root 32020 31849 0 17:53 pts/0 00:00:00 grep --color=auto nginx
master_process与worker_processes
master_process:用来指定是否开启工作进程
语法 | master_process on|off; |
---|---|
默认值 | master_process on; |
位置 | 全局块 |
worker_processes:用于配置Nginx生成工作进程的数量
这个是Nginx服务器实现并发处理服务的关键所在。理论上来说workder process的值越大,可以支持的并发处理量也越多,但事实上这个值的设定是需要受到来自服务器自身的限制,建议将该值和服务器CPU的内核数保存一致。
语法 | worker_processes num/auto; |
---|---|
默认值 | 1 |
位置 | 全局块 |
#查看当前进程状态
$ ps -ef | grep nginx
root 31982 1 0 17:52 ? 00:00:00 nginx: master process ./nginx
nobody 32219 31982 0 18:19 ? 00:00:00 nginx: worker process
root 32269 31849 0 18:26 pts/0 00:00:00 grep --color=auto nginx
#修改配置文件,添加项`master_precess off;`
$ vim ../conf/nginx.conf
#检查配置文件语法
$ ./nginx -tq
#重新加载配置文件
$ ./nginx -s reload
#重新加载配置文件,没有生效
$ ps -ef | grep nginx
root 31982 1 0 17:52 ? 00:00:00 nginx: master process ./nginx
nobody 32276 31982 0 18:27 ? 00:00:00 nginx: worker process
root 32278 31849 0 18:27 pts/0 00:00:00 grep --color=auto nginx
#重启nginx
$ ./nginx -s stop
$ ./nginx
#配置文件生效了
$ ps -ef | grep nginx
root 32282 1 0 18:27 ? 00:00:00 ./nginx
root 32289 31849 0 18:27 pts/0 00:00:00 grep --color=auto nginx
#注释掉上面的,添加项`worker_precess 2`
$ vim ../conf/nginx.conf
$ ./nginx -tq
$ ./nginx -s reload
$ ps -ef | grep nginx
root 32282 1 0 18:27 ? 00:00:00 ./nginx
root 32296 31849 0 18:28 pts/0 00:00:00 grep --color=auto nginx
#重启nginx
$ ./nginx -s stop
$ ./nginx
#可以看到有2个工作进程
$ ps -ef | grep nginx
root 32300 1 0 18:28 ? 00:00:00 nginx: master process ./nginx
nobody 32301 32300 0 18:28 ? 00:00:00 nginx: worker process
nobody 32302 32300 0 18:28 ? 00:00:00 nginx: worker process
root 32313 31849 0 18:28 pts/0 00:00:00 grep --color=auto nginx
daemon
daemon:设定Nginx是否以守护进程的方式启动
语法 | daemon on|off; |
---|---|
默认值 | daemon on; |
位置 | 全局块 |
pid
用来配置Nginx当前master进程的进程号ID存储的文件路径
语法 | pid file; |
---|---|
默认值 | 默认为:/usr/local/nginx/logs/nginx.pid |
位置 | 全局块 |
该属性可以通过./configure --pid-path=PATH
来指定
error_log
用来配置Nginx的错误日志存放路径
语法 | error_log file [日志级别]; |
---|---|
默认值 | error_log logs/error.log error; |
位置 | 全局块、http、server、location |
该属性可以通过./configure --error-log-path=PATH
来指定
其中日志级别的值有:debug|info|notice|warn|error|crit|alert|emerg
,翻译过来为调试|信息|通知|警告|错误|临界|警报|紧急
,这块建议大家设置的时候不要设置成info以下的等级,因为会带来大量的磁盘I/O消耗,影响Nginx的性能
include
用来引入其他配置文件,使Nginx的配置更加灵活:
include main.conf
语法 | include file; |
---|---|
默认值 | 无 |
位置 | any |
events块
accept_mutex:用来设置Nginx网络连接序列化
语法 | accept_mutex on|off; |
---|---|
默认值 | accept_mutex on; |
位置 | events |
这个配置主要可以用来解决常说的"惊群"问题。大致意思是在某一个时刻,客户端发来一个请求连接,Nginx后台是以多进程的工作模式,也就是说有多个worker进程会被同时唤醒,但是最终只会有一个进程可以获取到连接,如果每次唤醒的进程数目太多,就会影响Nginx的整体性能。如果将上述值设置为on(开启状态),将会对多个Nginx进程接收连接进行序列号,一个个来唤醒接收,就防止了多个进程对连接的争抢
multi_accept:用来设置是否允许同时接收多个网络连接
语法 | multi_accept on|off; |
---|---|
默认值 | multi_accept off; |
位置 | events |
如果multi_accept被禁止了,nginx一个工作进程只能同时接受一个新的连接。否则,一个工作进程可以同时接受所有的新连接
worker_connections:用来配置单个worker进程最大的连接数
语法 | worker_connections number; |
---|---|
默认值 | worker_commections 512; |
位置 | events |
这里的连接数不仅仅包括和前端用户建立的连接数,而是包括所有可能的连接数。另外,number值不能大于操作系统支持打开的最大文件句柄数量
use:用来设置Nginx服务器选择哪种事件驱动来处理网络消息
语法 | use method; |
---|---|
默认值 | 根据操作系统定 |
位置 | events |
注意:此处所选择事件处理模型是Nginx优化部分的一个重要内容,method的可选值有select/poll/epoll/kqueue等,之前在准备centos环境的时候,我们强调过要使用linux内核在2.6以上,就是为了能使用epoll函数来优化Nginx
另外这些值的选择,我们也可以在编译的时候使用
--with-select_module
、--without-select_module
、
--with-poll_module
、 --without-poll_module
来设置是否需要将对应的事件驱动模块编译到Nginx的内核
打开Nginx的配置文件 nginx.conf,添加如下配置
events{
accept_mutex on; #开启网络连接序列化(互斥)
multi_accept on; #工作进程同时接受多个网络连接
worker_commections 1024; #最大连接数量
use epoll; #选择事件驱动模型
}
启动测试
./nginx -t
./nginx -s reload
http块
我们都知道浏览器中可以显示的内容有HTML、XML、GIF等种类繁多的文件、媒体等资源,浏览器为了区分这些资源,就需要使用MIME Type。所以说MIME Type是网络资源的媒体类型。Nginx作为web服务器,也需要能够识别前端请求的资源类型
在Nginx的配置文件中,默认有两行配置
include mime.types;
default_type application/octet-stream;
default_type:用来配置Nginx响应前端请求默认的MIME类型
语法 | default_type mime-type; |
---|---|
默认值 | default_type text/plain; |
位置 | http、server、location |
在default_type之前还有一句include mime.types
,include之前我们已经介绍过,相当于把mime.types文件中MIMT类型与相关类型文件的文件后缀名的对应关系加入到当前的配置文件中
举例来说明:
有些时候请求某些接口的时候需要返回指定的文本字符串或者json字符串,如果逻辑非常简单或者干脆是固定的字符串,那么可以使用nginx快速实现,这样就不用编写程序响应请求了,可以减少服务器资源占用并且响应性能非常快
定义一个location
块:
location /get_text {
default_type text/html; #这里也可以设置成text/plain
return 200 "This is nginx's text";
}
如果不设置default_type
,默认application/octet-stream
的方式下载;
设置default_type text/plain;
,返回直接原样字符串,浏览器不解析;
设置default_type text/html
后,浏览器解析该字符串并呈现;
再定义一个location
返回一个json对象:
location /get_json{
default_type application/json;
return 200 '{"username":"TOM","age":18}';
}
http块自定义服务日志
Nginx中日志的类型分access.log、error.log
access.log:用来记录用户所有的访问请求
112.10.180.105 - - [01/Sep/2021:22:50:48 +0800] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36"
112.10.180.105 - - [01/Sep/2021:22:50:48 +0800] "GET /assets/images/favicon.ico HTTP/1.1" 200 1150 "http://116.62.20.151/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36"
error.log:记录nginx本身运行时的错误信息,不会记录用户的访问请求。
Nginx服务器支持对服务日志的格式、大小、输出等进行设置,需要使用到两个指令,分别是access_log
和log_format
指令
access_log:用来设置用户访问日志的相关属性
语法 | access_log path[format[buffer=size]] |
---|---|
默认值 | access_log logs/access.log combined; |
位置 | http , server , location |
log_format:用来指定日志的输出格式
语法 | log_format name [escape=default|json|none] string…; |
---|---|
默认值 | log_format combined “…”; |
位置 | http |
自定义日志格式:
log_format myformat 'from $http_user_agent';
设定日志记录到my.log
文件中,并应用上面的自定义格式:
access_log logs/my.log myformat;
sendfile:用来设置Nginx服务器是否使用sendfile()
传输文件,该属性可以大大提高Nginx处理静态资源的性能
语法 | sendfile on|off |
---|---|
默认值 | sendfile off; |
位置 | http、server、location |
keepalive_timeout:用来设置长连接的超时时间
为什么要使用keepalive?
我们都知道HTTP是一种无状态协议,客户端向服务端发送一个TCP请求,服务端响应完毕后断开连接。
如果客户端向服务端发送多个请求,每个请求都需要重新创建一次连接,效率相对来说比较多,使用keepalive模式,可以告诉服务器端在处理完一个请求后保持这个TCP连接的打开状态,若接收到来自这个客户端的其他请求,服务端就会利用这个未被关闭的连接,而不需要重新创建一个新连接,提升效率,但是这个连接也不能一直保持,这样的话,连接如果过多,也会是服务端的性能下降,这个时候就需要我们进行设置其的超时时间。
语法 | keepalive_timeout time; |
---|---|
默认值 | keepalive_timeout 75s; |
位置 | http、server、location |
keepalive_requests:用来设置一个keep-alive连接使用的次数
语法 | keepalive_requests number; |
---|---|
默认值 | keepalive_requests 100; |
位置 | http、server、location |
sendfile on;
keepalive_timeout 65;
keepalive_requests 100;
server块和location块
一个http
块中可以放多个server
块,一个server
块中可以放多个location
块
server {
#监听端口
listen 80;
#ip或域名
server_name localhost;
location / {
root /usr/local/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
配置项可以放在http
,server
,location
块多个地方,遵循最小作用域原则
Nginx基础配置实例
前面我们已经对Nginx服务器默认配置文件的结构和涉及的基本指令做了详细的阐述。通过这些指令的合理配置,我们就可以让一台Nginx服务器正常工作,并且提供基本的web服务器功能
接下来我们将通过一个比较完整和最简单的基础配置实例,来巩固下前面所学习的指令及其配置,需求如下:
(1)有如下访问:
http://192.168.200.133:8081/server1/location1
访问的是:index_sr1_location1.html
http://192.168.200.133:8081/server1/location2
访问的是:index_sr1_location2.html
http://192.168.200.133:8082/server2/location1
访问的是:index_sr2_location1.html
http://192.168.200.133:8082/server2/location2
访问的是:index_sr2_location2.html
(2)如果访问的资源不存在,返回自定义的404页面
(3)将/server1和/server2的配置使用不同的配置文件分割
将文件放到/home/www/conf.d目录下,然后使用include进行合并
(4)为/server1和/server2各自创建一个访问日志文件
准备相关的文件:
$ pwd
/home/www
$ tree
.
├── conf.d
│ ├── server1.conf
│ └── server2.conf
└── myweb
├── 404.html
├── server1
│ ├── location1
│ │ └── index_sr1_location1.html
│ ├── location2
│ │ └── index_sr1_location2.html
│ └── logs
│ └── access.log
└── server2
├── location1
│ └── index_sr2_location1.html
├── location2
│ └── index_sr2_location2.html
└── logs
└── access.log
10 directories, 9 files
然后将/usr/local/nginx/conf/nginx.conf
文件初始化:
cat /usr/local/nginx/conf/nginx.conf.default > /usr/locat/nginx/conf/nginx.conf
准备两个配置文件:
# server1.conf
server {
listen 8081;
server_name localhost;
access_log /home/www/myweb/server1/logs/access.log server1;
location /server1/location1 {
root /home/www/myweb; #root path
index index_sr1_location1.html;
}
location /server1/location2 {
root /home/www/myweb;
index index_sr1_location2.html;
}
error_page 404 /404.html;
location = /404.html {
root /home/www/myweb;
index 404.html;
}
}
# server2.conf
server {
listen 8082;
server_name localhost;
access_log /home/www/myweb/server2/logs/access.log server2;
location /server2/location1 {
root /home/www/myweb; #root path
index index_sr2_location1.html;
}
location /server2/location2 {
root /home/www/myweb;
index index_sr2_location2.html;
}
error_page 404 /404.html;
location = /404.html {
root /home/www/myweb;
index 404.html;
}
}
将nginx配置成系统服务:
在/usr/lib/systemd/system
目录下添加nginx.service:
vim /usr/lib/systemd/system/nginx.service
内容如下:
[Unit]
Description=nginx web service
Documentation=http://nginx.org/en/docs/
After=network.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
PrivateTmp=true
[Install]
WantedBy=default.target
添加完成后如果权限有问题需要进行权限设置:
chmod 755 /usr/lib/systemd/system/nginx.service
使用系统命令来操作Nginx服务:
启动: systemctl start nginx
停止: systemctl stop nginx
重启: systemctl restart nginx
重新加载配置文件: systemctl reload nginx
查看nginx状态: systemctl status nginx
开机启动: systemctl enable nginx
将nginx命令配置到系统环境:修改/etc/profile
文件,修改PATH
:
export PATH=$PATH:/usr/local/nginx/sbin
然后加载配置文件:
source /etc/profile
或者直接把alias nginx='/usr/local/nginx/sbin/nginx'
写入.bashrc
文件中
Nginx静态资源部署
静态资源即指在服务器端真实存在并且能直接拿来展示的一些文件,比如常见的html页面、css文件、js文件、图片、视频等资源
动态资源即指在服务器端真实存在但是要想获取需要经过一定的业务逻辑处理,根据不同的条件展示在页面不同这一部分内容,比如说报表数据展示、根据当前登录用户展示相关具体数据等资源
Nginx处理静态资源的内容,我们需要考虑下面这几个问题:
(1)静态资源的配置指令
(2)静态资源的配置优化
(3)静态资源的压缩配置指令
(4)静态资源的缓存处理
(5)静态资源的访问控制,包括跨域问题和防盗链问题
listen
用来配置监听端口
语法 | listen address[:port] [default_server]…; listen port [default_server]…; |
---|---|
默认值 | listen *:80 | *:8000 |
位置 | server |
listen的设置比较灵活,我们通过几个例子来把常用的设置方式熟悉下:
listen 127.0.0.1:8000; // listen localhost:8000 监听指定的IP和端口
listen 127.0.0.1; 监听指定IP的所有端口
listen 8000; 监听指定端口上的连接
listen *:8000; 监听指定端口上的连接
default_server属性是标识符,用来将此虚拟主机设置成默认主机。所谓的默认主机指的是如果没有匹配到对应的address:port,则会默认执行的。如果不指定默认使用的是第一个server
server{
listen 8080;
server_name 127.0.0.1;
location /{
root html;
index index.html;
}
}
server{
listen 8080 default_server;
server_name localhost;
default_type text/plain;
return 444 'This is a error request';
}
server_name
设置虚拟主机服务名称:127.0.0.1 、 localhost 、域名[www.baidu.com | www.jd.com]
语法 | server_name name …; name可以提供多个中间用空格分隔 |
---|---|
默认值 | server_name “”; |
位置 | server |
server {
listen 80;
server_name www.nginx521.cn;
...
}
windows的hosts文件路径:C:\Windows\System32\drivers\etc
。刷新hosts命令:ipconfig /flushdns
linux的hosts文件路径:/etc/hosts
server_name中支持通配符*
,但需要注意的是通配符不能出现在域名的中间,只能出现在首段或尾段,如:
server {
listen 80;
server_name *.nginx521.cn www.nginx521.*;
...
}
修改配置文件,增加如下内容:
127.0.0.1 abc.nginx521.cn
127.0.0.1 www.nginx521.com
接下来就可以访问上面两个网址了
server_name中也可以使用正则表达式,并且使用~
作为正则表达式字符串的开始标记
server_name ~^www\.(\w+)\.com$;
server_name的匹配顺序:
由于server_name指令支持通配符和正则表达式,因此在包含多个虚拟主机的配置文件中,可能会出现一个名称被多个虚拟主机的server_name匹配成功,当遇到这种情况,当前的请求交给谁来处理呢?
server{
listen 80;
server_name ~^www\.\w+\.com$;
default_type text/plain;
return 200 'regex_success';
}
server{
listen 80;
server_name www.itheima.*;
default_type text/plain;
return 200 'wildcard_after_success';
}
server{
listen 80;
server_name *.itheima.com;
default_type text/plain;
return 200 'wildcard_before_success';
}
server{
listen 80;
server_name www.itheima.com;
default_type text/plain;
return 200 'exact_success';
}
server{
listen 80 default_server;
server_name _;
default_type text/plain;
return 444 'default_server not found server';
}
Lua
14-Lua的概念介绍
概念
Lua是一种轻量、小巧的脚本语言,用标准C语言编写并以源代码形式开发。设计的目的是为了嵌入到其他应用程序中,从而为应用程序提供灵活的扩展和定制功能。
特性
跟其他语言进行比较,Lua有其自身的特点:
(1)轻量级
Lua用标准C语言编写并以源代码形式开发,编译后仅仅一百余千字节,可以很方便的嵌入到其他程序中。
(2)可扩展
Lua提供非常丰富易于使用的扩展接口和机制,由宿主语言(通常是C或C++)提供功能,Lua可以使用它们,就像内置的功能一样。
(3)支持面向过程编程和函数式编程
应用场景
Lua在不同的系统中得到大量应用,场景的应用场景如下:
游戏开发、独立应用脚本、web应用脚本、扩展和数据库插件、系统安全上。
15-Lua的安装
- 点击download可以找到对应版本的下载地址,我们本次课程采用的是lua-5.3.5,其对应的资源链接地址为https://www.lua.org/ftp/lua-5.4.1.tar.gz,也可以使用wget命令直接下载:
wget https://www.lua.org/ftp/lua-5.4.1.tar.gz
- 编译安装
cd lua-5.4.1
make linux test
make install
16-Lua的第一个案例交互式和脚本式使用
交互式:
[root@izbp1i6xv0q1dyvetecayhz lua_demo]# lua
Lua 5.4.3 Copyright (C) 1994-2021 Lua.org, PUC-Rio
> print(1+2)
3
脚本式:
[root@izbp1i6xv0q1dyvetecayhz lua_demo]# cat hello.lua
#! /usr/local/bin/lua
print(1+2)
添加执行权限就可以执行了。
补充一点,如果想在交互式中运行脚本式的hello.lua中的内容,我们可以使用一个dofile函数,如:
dofile("lua_demo/hello.lua")
注意:在Lua语言中,连续语句之间的分隔符并不是必须的,也就是说后面不需要加分号,当然加上也不会报错,
在Lua语言中,表达式之间的换行也起不到任何作用。如以下四个写法,其实都是等效的
写法一
a=1
b=a+2
写法二
a=1;
b=a+2;
写法三
a=1; b=a+2;
写法四
a=1 b=a+2
不建议使用第四种方式,可读性太差。
17-Lua的单行和多行注释
关于Lua的注释要分两种,第一种是单行注释,第二种是多行注释。
单行注释的语法为:
--注释内容
多行注释的语法为:
--[[
注释内容
注释内容
--]]
如果想取消多行注释,只需要在第一个–之前在加一个-即可,如:
---[[
注释内容
注释内容
--]]
[root@izbp1i6xv0q1dyvetecayhz lua_demo]# cat hello.lua
#! /usr/local/bin/lua
print(111)
--print(222)
--[[
print(333)
print(444)
print(555)
--]]
---[[
print(666)
print(777)
print(888)
--]]
[root@izbp1i6xv0q1dyvetecayhz lua_demo]# ./hello.lua
111
666
777
888
18-Lua的其他语法
标识符
换句话说标识符就是我们的变量名,Lua定义变量名以一个字母 A 到 Z 或 a 到 z 或下划线 _ 开头后加上0个或多个字母,下划线,数字(0到9)。这块建议大家最好不要使用下划线加大写字母的标识符,因为Lua的保留字也是这样定义的,容易发生冲突。注意Lua是区分大小写字母的。
A0
关键字
下列是Lua的关键字,大家在定义常量、变量或其他用户自定义标识符都要避免使用以下这些关键字:
and | break | do | else |
---|---|---|---|
elseif | end | false | for |
function | if | in | local |
nil | not | or | repeat |
return | then | true | until |
while | goto |
一般约定,以下划线开头连接一串大写字母的名字(比如 _VERSION)被保留用于 Lua 内部全局变量。这个也是上面我们不建议这么定义标识符的原因。
运算符
Lua中支持的运算符有算术运算符、关系运算符、逻辑运算符、其他运算符。
算术运算符:
+ 加法
- 减法
* 乘法
/ 除法
% 取余
^ 乘幂
- 负号
例如:
10+20 -->30
20-10 -->10
10*20 -->200
20/10 -->2
3%2 -->1
10^2 -->100
-10 -->-10
关系运算符
== 等于
~= 不等于
> 大于
< 小于
>= 大于等于
<= 小于等于
例如:
10==10 -->true
10~=10 -->false
20>10 -->true
20<10 -->false
20>=10 -->true
20<=10 -->false
逻辑运算符
and 逻辑与 A and B &&
or 逻辑或 A or B ||
not 逻辑非 取反,如果为true,则返回false !
逻辑运算符可以作为if的判断条件,返回的结果如下:
A = true
B = true
A and B -->true
A or B -->true
not A -->false
A = true
B = false
A and B -->false
A or B -->true
not A -->false
A = false
B = true
A and B -->false
A or B -->true
not A -->true
其他运算符
.. 连接两个字符串
# 一元预算法,返回字符串或表的长度
例如:
> "HELLO ".."WORLD" -->HELLO WORLD
> #"HELLO" -->5
全局变量&局部变量
在Lua语言中,全局变量无须声明即可使用。在默认情况下,变量总是认为是全局的,如果未提前赋值,默认为nil:
要想声明一个局部变量,需要使用local来声明
[root@izbp1i6xv0q1dyvetecayhz lua_demo]# lua
Lua 5.4.3 Copyright (C) 1994-2021 Lua.org, PUC-Rio
> b=true
> print(b)
true
> b=10
> print(b)
10
> local a=100
> print(a)
nil
> local a=1000; print(a)
1000
> print("hello".."world")
helloworld
> print(#"hello,world")
11
> local a=1; print(a~=b)
true
19-Lua的数据类型上
Lua有8个数据类型
nil(空,无效值)
boolean(布尔,true/false)
number(数值)
string(字符串)
function(函数)
table(表)
thread(线程)
userdata(用户数据)
可以使用type函数测试给定变量或者的类型:
print(type(nil)) -->nil
print(type(true)) --> boolean
print(type(1.1*1.1)) --> number
print(type("Hello world")) --> string
print(type(io.stdin)) -->userdata
print(type(print)) --> function
print(type(type)) -->function
print(type{}) -->table
print(type(type(X))) --> string
nil
nil是一种只有一个nil值的类型,它的作用可以用来与其他所有值进行区分,也可以当想要移除一个变量时,只需要将该变量名赋值为nil,垃圾回收就会会释放该变量所占用的内存。
boolean
boolean类型具有两个值,true和false。boolean类型一般被用来做条件判断的真与假。在Lua语言中,只会将false和nil视为假,其他的都视为真,特别是在条件检测中0和空字符串都会认为是真,这个和我们熟悉的大多数语言不太一样。
number
在Lua5.3版本开始,Lua语言为数值格式提供了两种选择:integer(整型)和float(双精度浮点型)[和其他语言不太一样,float不代表单精度类型]。
数值常量的表示方式:
>4 -->4
>0.4 -->0.4
>4.75e-3 -->0.00475
>4.75e3 -->4750
不管是整型还是双精度浮点型,使用type()函数来取其类型,都会返回的是number
>type(3) -->number
>type(3.3) -->number
所以它们之间是可以相互转换的,同时,具有相同算术值的整型值和浮点型值在Lua语言中是相等的
string
Lua语言中的字符串即可以表示单个字符,也可以表示一整本书籍。在Lua语言中,操作100K或者1M个字母组成的字符串的程序很常见。
可以使用单引号或双引号来声明字符串
>a = "hello"
>b = 'world'
>print(a) -->hello
>print(b) -->world
如果声明的字符串比较长或者有多行,则可以使用如下方式进行声明
html = [[
<html>
<head>
<title>Lua-string</title>
</head>
<body>
<a href="http://www.lua.org">Lua</a>
</body>
</html>
]]
[root@izbp1i6xv0q1dyvetecayhz lua_demo]# lua
Lua 5.4.3 Copyright (C) 1994-2021 Lua.org, PUC-Rio
> print(type('hello'))
string
> print(type(1))
number
> print(type(true))
boolean
> print(type(nil))
nil
> print(type({}))
table
> print(type(type))
function
> print(type(print))
function
> html=[[
>> <html>
>> <head>
>> <title>long lua string</title>
>> </head>
>> <body>
>> <h1>lua</h1>
>> </body>
>> </html>
>> ]]
> print(html)
<html>
<head>
<title>long lua string</title>
</head>
<body>
<h1>lua</h1>
</body>
</html>
20-Lua的数据类型中
table是Lua语言中最主要和强大的数据结构。使用表, Lua 语言可以以一种简单、统一且高效的方式表示数组、集合、记录和其他很多数据结构。 Lua语言中的表本质上是一种辅助数组。这种数组比Java中的数组更加灵活,可以使用数值做索引,也可以使用字符串或其他任意类型的值作索引(除nil外)。
创建表的最简单方式:
> a = {}
创建数组:
我们都知道数组就是相同数据类型的元素按照一定顺序排列的集合,那么使用table如何创建一个数组呢?
>arr = {"TOM","JERRY","ROSE"}
要想获取数组中的值,我们可以通过如下内容来获取:
print(arr[0]) nil
print(arr[1]) TOM
print(arr[2]) JERRY
print(arr[3]) ROSE
从上面的结果可以看出来,数组的下标默认是从1开始的。所以上述创建数组,也可以通过如下方式来创建
>arr = {}
>arr[1] = "TOM"
>arr[2] = "JERRY"
>arr[3] = "ROSE"
上面我们说过了,表的索引即可以是数字,也可以是字符串等其他的内容,所以我们也可以将索引更改为字符串来创建
>arr = {}
>arr["X"] = 10
>arr["Y"] = 20
>arr["Z"] = 30
当然,如果想要获取这些数组中的值,可以使用下面的方式
方式一
>print(arr["X"])
>print(arr["Y"])
>print(arr["Z"])
方式二
>print(arr.X)
>print(arr.Y)
>print(arr.Z)
当前table的灵活不进于此,还有更灵活的声明方式
>arr = {"TOM",X=10,"JERRY",Y=20,"ROSE",Z=30}
如何获取上面的值?
TOM : arr[1]
10 : arr["X"] | arr.X
JERRY: arr[2]
20 : arr["Y"] | arr.Y
ROESE?
[root@izbp1i6xv0q1dyvetecayhz ~]# lua
Lua 5.4.3 Copyright (C) 1994-2021 Lua.org, PUC-Rio
> a={}
> print(type(a))
table
> arr={'tom','jerry','rose'}
> print(arr[0])
nil
> print(arr[1])
tom
> print(arr[2])
jerry
> print(arr[3])
rose
> arr={}
> arr['x']=10
> arr['y']=20
> arr['z']=30
> arr['x']
10
> arr.y
20
> arr.z
30
> arr = {"TOM",X=10,"JERRY",Y=20,"ROSE",Z=30}
> arr[1]
TOM
> arr[2]
JERRY
> arr.X
10
> arr['Y']
20
> arr["Z"]
30
21-Lua的数据类型下
在 Lua语言中,函数( Function )是对语句和表达式进行抽象的主要方式。
定义函数的语法为:
function functionName(params)
end
函数被调用的时候,传入的参数个数与定义函数时使用的参数个数不一致的时候,Lua 语言会通过抛弃多余参数和将不足的参数设为nil的方式来调整参数的个数。
function f(a,b)
print(a,b)
end
f() --> nil nil
f(2) --> 2 nil
f(2,6) --> 2 6
f(2,6,8) --> 2 6 (8被丢弃)
可变长参数函数
function add(...)
a,b,c=...
print(a)
print(b)
print(c)
end
add(1,2,3) --> 1 2 3
函数返回值可以有多个,这点和Java不太一样
function f(a,b)
return a,b
end
x,y=f(11,22) --> x=11,y=22
thread
thread翻译过来是线程的意思,在Lua中,thread用来表示执行的独立线路,用来执行协同程序。
userdata
userdata是一种用户自定义数据,用于表示一种由应用程序或C/C++语言库所创建的类型。
[root@izbp1i6xv0q1dyvetecayhz ~]# lua
Lua 5.4.3 Copyright (C) 1994-2021 Lua.org, PUC-Rio
> function add()
>> print('add function')
>> end
>
> print(type(add))
function
>
> add
function: 0xbae210
>
> add()
add function
>
> function add(a,b)
>> print(a,b)
>> end
>
> add()
nil nil
>
> add(1,2)
1 2
>
> add(1)
1 nil
>
> add(1,2,3)
1 2
>
> function add(...)
>> local a,b,c=...
>> print(a,b,c)
>> end
>
> add(1,2,3)
1 2 3
> add('x','y','z')
x y z
>
> add(1,2,3,4)
1 2 3
>
> function add(a,b)
>> return b,a
>> end
>
> x,y=add(100,200)
>
> print(x,y)
200 100
22-Lua的条件判断
Lua 语言提供了一组精简且常用的控制结构,包括用于条件执行的证 以及用于循环的while
、 repeat
和for
。 所有的控制结构语法上都有一个显式的终结符: end
用于终结if
、for
及while
结构,until
用于终结repeat
结构。
if then elseif else
if语句先测试其条件,并根据条件是否满足执行相应的 then 部分或 else 部分。 else 部分 是可选的。
function testif(a)
if a>0 then
print("a是正数")
end
end
function testif(a)
if a>0 then
print("a是正数")
else
print("a是负数")
end
end
如果要编写嵌套的 if 语句,可以使用 elseif。 它类似于在 else 后面紧跟一个if。根据传入的年龄返回不同的结果,如
age<=18 青少年,
age>18 , age <=45 青年
age>45 , age<=60 中年人
age>60 老年人
function show(age)
if age<=18 then
return "青少年"
elseif age>18 and age<=45 then
return "青年"
elseif age>45 and age<=60 then
return "中年人"
elseif age>60 then
return "老年人"
end
end
Lua 5.4.3 Copyright (C) 1994-2021 Lua.org, PUC-Rio
> function testif(a)
>> if a>0 then
>> print('a is positive')
>> end
>> end
>
> testif(1)
a is positive
> testif(0)
>
> function testif(a)
>> if a>0 then
>> print('a is positive')
>> else
>> print('a is negtive')
>> end
>> end
>
> testif(10)
a is positive
> testif(-1)
a is negtive
> testif(0)
a is negtive
>
> function show(age)
>> if age<=18 then
>> return "teenagers"
>> elseif age>18 and age<=45 then
>> return "youth"
>> elseif age>45 and age<=60 then
>> return "middle-age"
>> elseif age>60 then
>> return "old"
>> end
>> end
>
> print(show(12))
teenagers
> print(show(30))
youth
> print(show(45))
youth
> print(show(80))
old
23-Lua的循环之while循环
顾名思义,当条件为真时 while 循环会重复执行其循环体。 Lua 语言先测试 while 语句 的条件,若条件为假则循环结束;否则, Lua 会执行循环体并不断地重复这个过程。
语法:
while 条件 do
循环体
end
例子:实现数组的循环
function testWhile()
local i = 1
while i<=10 do
print(i)
i=i+1
end
end
Lua 5.4.3 Copyright (C) 1994-2021 Lua.org, PUC-Rio
> function testwhile()
>> local i=1
>> while i<=10 do
>> print(i)
>> i=i+1
>> -- not i++
>> end
>> end
> testwhile()
1
2
3
4
5
6
7
8
9
10
24-Lua的循环之repeat循环
顾名思义,repeat-until
语句会重复执行其循环体直到条件为真时结束。 由于条件测试在循环体之后执行,所以循环体至少会执行一次。
语法
repeat
循环体
until 条件
function testRepeat()
local i = 10
repeat
print(i)
i=i-1
until i < 1
end
Lua 5.4.3 Copyright (C) 1994-2021 Lua.org, PUC-Rio
> function testrepeat()
>> local i=10
>> repeat
>> print(i)
>> i=i-1
>> until i<1
>> end
>
> testrepeat()
10
9
8
7
6
5
4
3
2
1
25-Lua的循环之for循环
daniel@vostro:~$ lua
Lua 5.4.3 Copyright (C) 1994-2021 Lua.org, PUC-Rio
> function testfor1()
>> for i=0,100,10 do
>> print(i)
>> end
>> end
>
> testfor1()
0
10
20
30
40
50
60
70
80
90
100
>
>
> function testfor2(arr)
>> for index,value in ipairs(arr) do
>> print(index,value)
>> end
>> end
>
> arr={'apple','orange','banana','peach'}
> testfor2(arr)
1 apple
2 orange
3 banana
4 peach
>
> arr={'apple','orange','banana',x='pee','peach'}
> testfor2(arr)
1 apple
2 orange
3 banana
4 peach
># x='pee':ipairs don't work
> function testfor2(arr)
>> for index,value in pairs(arr) do
>> print(index,value)
>> end
>> end
>
> testfor2(arr)
1 apple
2 orange
3 banana
4 peach
x pee
数值型for循环
语法
for param=begin,end,step do
循环体
end
param
的值从begin
变化到end
之前的每次循环会执行循环体
,并在每次循环结束后将步长stepe
增加到param
上。step
可选,如果不设置默认为1
for i = 1,100,10 do
print(i)
end
泛型for循环
泛型for循环通过一个迭代器函数来遍历所有值,类似于java中的foreach语句。
语法
for i,v in ipairs(x) do
循环体
end
i是数组索引值,v是对应索引的数组元素值,ipairs
是Lua提供的一个迭代器函数,用来迭代数组,x是要遍历的数组。
例如:
arr = {"TOME","JERRY","ROWS","LUCY"}
for i,v in ipairs(arr) do
print(i,v)
end
上述实例输出的结果为
1 TOM
2 JERRY
3 ROWS
4 LUCY
但是如果将arr的值进行修改为
arr = {"TOME","JERRY","ROWS",x="JACK","LUCY"}
同样的代码在执行的时候,就只能看到和之前一样的结果,而其中的x为JACK就无法遍历出来,缺失了数据,如果解决呢?
我们可以将迭代器函数变成pairs
,如
for i,v in pairs(arr) do
print(i,v)
end
上述实例就输出的结果为
1 TOM
2 JERRY
3 ROWS
4 LUCY
x JACK
26-ngx_lua的环境准备之OpenResty搭建
OpenRestry
概述
前面我们提到过,OpenResty是由淘宝工程师开发的,所以其官方网站(http://openresty.org/)我们读起来是非常的方便。OpenResty是一个基于Nginx与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。所以本身OpenResty内部就已经集成了Nginx和Lua,所以我们使用起来会更加方便。
安装
(1)下载OpenResty:https://openresty.org/download/openresty-1.15.8.2.tar.gz
(2)使用wget下载: wget https://openresty.org/download/openresty-1.15.8.2.tar.gz
(3)解压缩: tar -zxf openresty-1.15.8.2.tar.gz
(4)进入OpenResty目录: cd openresty-1.15.8.2
(5) 执行命令:./configure
(6) 执行命令:make && make install
(7)进入OpenResty的目录,找到nginx:cd /usr/local/openresty/nginx/
(8)在conf目录下的nginx.conf添加如下内容
location /lua{
default_type 'text/html';
content_by_lua 'ngx.say("<h1>HELLO,OpenRestry</h1>")';
}
(9)在sbin目录下启动nginx
(10)通过浏览器访问测试