Nginx学习笔记

课程地址

Nginx概述

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常用的功能模块:

  1. 静态资源部署
  2. Rewrite地址重写:正则表达式
  3. 反向代理
  4. 负载均衡:轮询,加权轮询,ip_hash,url_hash,fair
  5. Web缓存
  6. 环境部署:高可用的环境
  7. 用户认证模块

Nginx的核心组成

  1. nginx二进制可执行文件
  2. nginx.conf配置文件
  3. error.log错误日志文件
  4. access.log访问日志文件

安装Nginx

centos关闭防火墙:

  1. 关闭运行的防火墙,系统重新启动后,防火墙将重新打开:systemctl stop firewalld
  2. 永久关闭防火墙,系统重新启动后,防火墙依然关闭:systemctl disable firewalld
  3. 查看防火墙状态: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.conf配置文件中默认有三大块:全局块、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块

MIME的概念

我们都知道浏览器中可以显示的内容有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_loglog_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;
        }
    }

配置项可以放在httpserverlocation块多个地方,遵循最小作用域原则

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的安装

  1. 点击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
  1. 编译安装
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的关键字,大家在定义常量、变量或其他用户自定义标识符都要避免使用以下这些关键字:

andbreakdoelse
elseifendfalsefor
functionifinlocal
nilnotorrepeat
returnthentrueuntil
whilegoto

一般约定,以下划线开头连接一串大写字母的名字(比如 _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 语言提供了一组精简且常用的控制结构,包括用于条件执行的证 以及用于循环的whilerepeatfor。 所有的控制结构语法上都有一个显式的终结符: end用于终结ifforwhile结构,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)通过浏览器访问测试

在这里插入图片描述

未完待续

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值