当前位置: 首页 > news >正文

openresty学习笔记

openresty 简介

openresty 是一个基于 nginx 与 lua 的高性能 web 平台,其内部 集成了大量精良的 lua 库、第三方模块以及大数的依赖项。用于 方便搭建能够处理超高并发、扩展性极高的动态 web 应用、 web 服务和动态网关。

openresty 通过汇聚各种设计精良的 nginx 模块,从而将 nginx 有效地变成一个强大的通用 Web 应用平台。这样,Web 开发人 员和系统工程师可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,快速构造出足以胜任 10K 乃至 1000K 以上单 机并发连接的高性能 Web 应用系统。

openresty 的目标是让你的 Web 服务直接跑在 Nginx 服务内部, 充分利用 Nginx 的非阻塞 I/O 模型(多reactor 模型),不仅仅 对 HTTP 客户端请求(stream),甚至于对远程后端诸如 MySQL、PostgreSQL、Memcached 以及 Redis etcd kafka grpc 等都进行一致的高性能响应(upstream)。

openresty 安装

官网: http://openresty.org/cn/

下载页面:http://openresty.org/cn/download.html 

# 安装依赖
apt-get install libpcre3-dev \libssl-dev perl make build-essential curl
# 解压源码
tar -xzvf openresty-VERSION.tar.gz
# 配置:默认, --prefix=/usr/local/openresty 程序会被
安装到/usr/local/openresty目录。
./configure
make -j2
sudo make install
cd ~
export PATH=/usr/local/openresty/bin:$PATH

启动、关闭、重启 openresty

# 指定配置启动 openresty
openresty -p . -c conf/nginx.conf
# 优雅退出
openresty -p . -s quit
# 重启 openresty
openresty -p . -s reload

openresty 应用场景

奇虎360的所有服务端团队都在使用,京东、百度、魅族、知 乎、优酷、新浪这些互联网公司都在使用。有用来写 WAF (web application firewall)、有做 CDN 调度、有做广告系统、消息推送系统,API server 的。还有用在非常关键的业务上,比如高可用架构分享的京东商品详情页。

1 在请求真正到达上游服务之前,Lua 可以随心所欲的做复杂的访问控制和安全检测

2 随心所欲的操控响应头里面的信息

3 从外部存储服务(比如 Redis,Memcached,MySQL, Postgres)中获取后端信息,并用这些信息来实时选择哪一个后端来完成业务访问

4 在内容 handler 中随意编写复杂的 Web 应用,使用同步但依然非阻塞的方式,访问后端数据库和其他存储

5 在 rewrite 阶段,通过 Lua 完成非常复杂的 URL dispatch

6 用 Lua 可以为 nginx 子请求和任意 location,实现高级缓存机制

lua-nginx-module

nginx 采用模块化设计,使得每一个 http 模块可以仅专注于完 成一个独立的、简单的功能,而一个请求的完整处理过程可以 由无数个 http 模块共同合作完成。为了灵活有效地指定下一个 http 处理模块是哪一个;http 框架依据常见的的处理流程将处 理阶段划分为 11 个阶段,其中每一个阶段都可以由任意多个 http 模块流水式地处理请求。

openresty 将 lua 脚本嵌入到 nginx 阶段处理的末尾模块下;这样以来并不会影响 nginx 原有的功能,而是在 nginx 基础上丰富它的功能;

嵌入 lua 的优点是:使用 openresty 开发,不需要重新编译, 直接修改 lua 脚本,重新启动即可;

lua 模块指令顺序

问题:访问某个页面,先验证是否用户权限是否合法,否则跳到用户验证界面;

问题:黑白名单在哪个阶段实现?

init_by_lua

在 nginx 重新加载配置文件时,运行里面 lua 脚本,常用于 全局变量的申请。例如 lua_shared_dict 共享内存的申请,只 有当 nginx 重启后,共享内存数据才清空,这常用于统计。

set_by_lua

设置一个变量,常用与计算一个逻辑,然后返回结果,该阶 段不能运行Output API、Control API、Subrequest API、 Cosocket API

rewrite_by_lua

在 access 阶段前运行,主要用于 rewrite url;

access_by_lua

主要用于访问控制,这条指令运行于 nginx access 阶段的末 尾,因此总是在 allow 和 deny 这样的指令之后运行,它们 同属 access 阶段。可用来判断请求是否具备访问权限;

content_by_lua

阶段是所有请求处理阶段中最为重要的一个,运行在这个阶 段的配置指令一般都肩负着生成内容(content)并输出 HTTP 响应。

header_filter_by_lua

一般只用于设置 Cookie 和 Headers 等。

body_filter_by_lua

一般会在一次请求中被调用多次,因为这是实现基于 HTTP 1.1 chunked 编码的所谓“流式输出”的。

log_by_lua

该阶段总是运行在请求结束的时候,用于请求的后续操作, 如在共享内存中进行统计数据,如果要高精确的数据统计, 应该使用 body_filter_by_lua

嵌入原理

openresty 是在nginx处理的阶段末尾加上我们的方法,补充功能,原来实现的功能不受影响。

责任链模式

ngx.exit(status) 

如果status == 0 只打断当前责任链,如果status>=200 则打断整个责任链,直接退出。

ngx.redirect()

cosocket

openresty 为 nginx 添加的最核心的功能就是 cosocket;自 cosocket 加入,可以在 http 请求处理中访问第三方服务; cosocket 主要依据 nginx 中的事件机制和 lua 的协程结合后实现了非阻塞网络 io;在业务逻辑使用层面上可以通过同步非阻塞的方式来写代码;

引入 cosocket 后,nginx 中相当于有了多条并行同步逻辑线 (lua 协程),nginx 中单线程负责唤醒或让出其中 lua 协程; 唤醒或让出依据来源于协程运行的条件是否得到满足;

问题:比较 openresty 、skynet、zvnet 的 lua 虚拟机抽象和 lua 协程抽象?

黑名单用户 nginx.conf

worker_processes 8;events {worker_connections 10240;
}http {lua_shared_dict bklist 1m;init_worker_by_lua_file ./app/init_worker.lua;server {listen 9000;location / {access_by_lua_block {local black_list = {["192.168.44.1"] = true}if black_list[ngx.var.remote_addr] then return ngx.exit(403)end}content_by_lua_block {ngx.say("hello" , "\t" , ngx.var.remote_addr)}}location /black_v1 {access_by_lua_file ./app/black_v1.lua;content_by_lua_block {ngx.say("hello" , "\t" , ngx.var.remote_addr)}}location /black_v2 {access_by_lua_file ./app/black_v2.lua;content_by_lua_block {ngx.say("hello" , "\t" , ngx.var.remote_addr)}}}
}

black_v1.lua  (将黑名单ip放入redis)

local redis = require "resty.redis"local red = redis:new()local ok , err = red:connect("127.0.0.1" , 6379)if not ok then return ngx.exit(301)
endlocal ip = ngx.var.remote_addrlocal exists , err = red:sismember("black_list" , ip)if exists == 1 thenreturn ngx.exit(403)
end

black_v2.lua   

local bklist = ngx.shared.bklistlocal ip = ngx.var.remote_addrif bklist:get(ip) then return ngx.exit(403)
end

init_worker.lua   一个worker定时往共享内存中刷数据,(黑名单ip)

if ngx.worker.id() ~= 0 thenreturn
endlocal redis = require "resty.redis"
local bklist = ngx.shared.bklistlocal function update_blacklist()local red = redis:new()local ok , err = red:connect("127.0.0.1" , 6379)if not ok then returnendlocal black_list,err = red:smembers("black_list")bklist:flush_all() for _,v in pairs(black_list) dobklist:set(v , true)endngx.timer.at(5 , update_blacklist)
endngx.timer.at(5 , update_blacklist)

反向代理

worker_processes 8;events {worker_connections 10240;
}# http
http {server {listen 8989;location / {rewrite_by_lua_block {local args = ngx.req.get_uri_args()if args["jump"] == "1" thenreturn ngx.redirect("http://baidu.com")elseif args["jump"] == "2" thenreturn ngx.redirect("/jump_here")end}content_by_lua_block {ngx.say("hello", "\t", ngx.var.remote_addr)}}location /jump_here {content_by_lua_block {ngx.say("jump_here hello", "\t", ngx.var.remote_addr)}body_filter_by_lua_block {local chunk = ngx.arg[1]ngx.arg[1] = chunk:gsub("hello", "mark")}}}
}stream {upstream ups {server 127.0.0.1:8888;}server {listen 9999;proxy_pass ups;proxy_protocol on;}server {listen 9000;content_by_lua_file ./app/proxy.lua;}
}

cosocket   proxy.lua

local sock, err = ngx.req.socket()if err thenngx.log(ngx.INFO, err)
endlocal upsock, okupsock = ngx.socket.tcp()ok, err = upsock:connect("127.0.0.1", 8989)
if not ok thenngx.log(ngx.INFO, "connect error:"..err)
endupsock:send(ngx.var.remote_addr .. '\n')local function handle_upstream()local datafor i=1, 1000 dolocal reader = upsock:receiveuntil("\n", {inclusive = true})data, err, _ = reader()if err thensock:close()upsock:close()returnendsock:send(data)end
endngx.thread.spawn(handle_upstream)local datawhile true dolocal reader = sock:receiveuntil("\n", {inclusive = true})data, err, _ = reader()if err thensock:close()upsock:close()returnendupsock:send(data)
end

相关文章:

openresty学习笔记

openresty 简介 openresty 是一个基于 nginx 与 lua 的高性能 web 平台,其内部 集成了大量精良的 lua 库、第三方模块以及大数的依赖项。用于 方便搭建能够处理超高并发、扩展性极高的动态 web 应用、 web 服务和动态网关。 openresty 通过汇聚各种设计精良的 ngi…...

微信小程序DAY3

文章目录一、页面导航1-1、声明式导航1-2、编程式导航1-3、声明式导航传参1-4、编程式导航传参1-5、获取导航传递的参数二、页面事件2-1、下拉刷新事件2-1-1、启用下拉刷新2-1-2、配置下拉刷新2-1-3、监听页面下拉刷新事件2-2、上拉触底事件2-2-1、事件触发2-2-1、事件配置三、…...

【CAN】手把手教你学习CAN总线(一)

CAN总线一、CAN总线概念二、CAN的差分信号三、CAN总线的通信协议1、 帧起始2、仲裁段3、控制段4、数据段5、CRC段6、ACK段7、帧结束四、CAN的位时序1、同步段(SS)2、传播时间段(PTS)3、相位缓冲段(PBS)4、再…...

JUC 体系的基石——AQS

—— AQS(AbstractQueuedSynchronizer) 概念 抽象队列同步器;volatile cas 机制实现的锁模板,保证了代码的同步性和可见性,而 AQS 封装了线程阻塞等待挂起,解锁唤醒其他线程的逻辑。AQS 子类只需要根据状…...

Qt中信号与槽的使用

Qt中信号与槽的使用 Qt当中一个重要的东西是信号和槽,它被用于对象之间的通信。 在Qt中,例如“点击按钮”这个事件就是发送信号的对象,接收信号的是某一个窗口,响应信号的是一个处理,可以是隐藏窗口或者是关闭窗口。…...

力扣-销售员

大家好,我是空空star,本篇带大家了解一道简单的力扣sql练习题。 文章目录前言一、题目:607. 销售员二、解题1.正确示范①提交SQL运行结果2.正确示范②提交SQL运行结果3.正确示范③提交SQL运行结果4.正确示范④提交SQL运行结果5.其他总结前言 …...

HTML综合案例练习

一、展示简历内容 可以首先看一下我们的效果,之后再思考怎么实现 总的来说,这个练习不算难。 这里关于这个简历的代码编写我们不说太多,只注意以下几个内容即可: 注意及时查看我们的代码是否符合预期,即一段一段测 …...

MySQL运维

目录 1、日志 1、错误日志 2、二进制日志 3、查询日志 4、慢查询日志 2、主从复制 搭建 1、主库配置 2、从库配置 3、分库分表 1、简介 ​编辑 1、垂直拆分 2、水平拆分 3、实现技术 2、MyCat 3、MyCat使用和配置 配置 4、MyCat分片 1、垂直拆分 2、水平拆分…...

【网络原理10】构造HTTP请求、HTTPS加密

目录 一、构造HTTP请求 ①使用form表单构造HTTP请求: form表单是如何提交的 form提交的缺点 ②基于ajax构造http请求 如何使用Jquery框架 二、HTTPS 运营商劫持 HTTP的加密版本:HTTPS ①对称加密:客户端和服务端使用同一把密钥&…...

Allegro如何锁定报表界面操作指导

Allegro如何锁定报表界面操作指导 用Allegro做PCB设计的时候,进行测量的时候,比如测量器件两个PIN中间的间距,如下图,会有一个报表显示 但是当运行下一个命令的时候,报表会被自动关闭掉。 但是有时我们需要报表界面仍被保留 下面介绍如何将报表界面进行锁定,不受下一个…...

基于STM32的微型电子琴设计

基于STM32的微型电子琴设计报告中的图片和文字太多了,全部一个一个把搬过来太麻烦了,需要完整文本和代码自行q我963160156 第一章 总体设计1.1 系统功能1.2 主要技术性能指标第二章硬件设计2.1 整体硬件图2.2 按键模块2.3 扬声器模块2.4 显示模块2.5 主控模块第三章…...

Shell输入输出重定向

一、文件描述符 文件描述符是一个非负整数。它是一个索引值,指向进程打开的文件。 Linux 程序在执行任何形式的 I/O 操作时,都是在读取或者写入一个文件描述符。 每个文件描述符会与一个打开的文件相对应 不同的文件描述符也可能指向同一个文件 在L…...

华为OD机试-运维日志排序

文章目录题目描述输入描述输出描述:示例Java 代码实现题目描述 运维工程师采集到某产品线网运行一天产生的日志n条,现需根据日志时间先后顺序对日志进行排序,日志时间格式为H:M:S.N。 H表示小时(0~23) M表示分钟(0~59) S表示秒(0~59) N表…...

1Kotlin基础知识

1 变量 1.1 用法 Kotlin中的变量定义有2个关键字,val和var val用来定义不可变变量,第一次赋值后就不能再被修改了, var定义可变变量, 随便修改。一个好的编程习惯是, 能用val的就不要用var, 原因是安全&a…...

Redis Lua脚本

文章目录一.引言二.eval简介三.lua数据类型和redis数据类型之间转换四.脚本的原子性五.错误处理六.纯函数脚本七.选择内部脚本一.引言 eval和evalsha命令使用内置的lua解释器,可以对lua脚本进行求值。 二.eval简介 第一个参数是一段脚本程序第二个参数是参数的个…...

web自动化测试-执行 JavaScript 脚本

JavaScript 是一种脚本语言,有的场景需要使用 js 脚本注入辅助我们完成 Selenium 无法做到的事情。 当 webdriver 遇到无法完成的操作时,可以使用 JavaScript 来完成,webdriver 提供了 execute_script() 方法来调用 js 代码。 执行 js 有两种…...

libevent笔记——简单介绍

背景 libevent libevent – an event notification library 官方定义:libevent是一个事件通知的库。更详细的介绍参考官方的就够了,这里我摘抄一下,并做一些注释 The libevent API provides a mechanism to execute a callback function whe…...

C++学习笔记-多态

多态的概念 多态的概念:通俗来说,就是多种形态, 具体点就是去完成某个行为,当不同的对象去完成时会 产生出不同的状态 。 举个例子:比如 买票这个行为 ,当 普通人 买票时,是全价买票&#xff1b…...

5632: 三角形

描述平面坐标系下,给定不共线的三个点组成一个三角形,问三角形最短的边长和最长的边长各为多少?输入输入包含3行,每行两个整数,表示一个点的坐标x和y。输出输出包括2个小数,分别为最短的边长和最长的边长。…...

Java基础--IO操作

一、IO原理及分类 一、IO原理 1、I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于处理设备之间的数据传输,如读写文件,网络通信等。 2、java程序中对于数据的输入/输出操作一般都是以流的方式进行 3、java.io包下提供各…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理&#xff1a…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

Ubuntu Cursor升级成v1.0

0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开&#xff0c;快捷键也不好用&#xff0c;当看到 Cursor 升级后&#xff0c;还是蛮高兴的 1. 下载 Cursor 下载地址&#xff1a;https://www.cursor.com/cn/downloads 点击下载 Linux (x64) &#xff0c;…...

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址&#xff1a;Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址&#xff08;如 10.244.1.2&#xff09;无特殊名称&#xff1a;在 Kubernetes 中&#xff0c;它通常被称为 “Pod IP” 或 “容器 IP”生命周期&#xff1a;与 Pod …...

如何配置一个sql server使得其它用户可以通过excel odbc获取数据

要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据&#xff0c;你需要完成以下配置步骤&#xff1a; ✅ 一、在 SQL Server 端配置&#xff08;服务器设置&#xff09; 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到&#xff1a;SQL Server 网络配…...