Meathill

Meathill 查看完整档案

广州编辑中国地质大学(武汉)  |  应用化学 编辑OpenResty Inc.  |  高级前端工程师 编辑 blog.meathill.com/ 编辑
编辑

爱编程,爱旅游,爱吐槽。

今年的目标是多做直播和视频,现阶段目标:坚持工作日直播。近期直播内容:

  • JavaScript 设计模式
  • 浏览器扩展开发共享收藏夹
  • 小程序开发卡通照片

欢迎大家到B站找我:https://space.bilibili.com/74...

个人动态

Meathill 回答了问题 · 4月4日

解决不懂就问,用 setTimeout 简单实现 setInterval 的问题

JS 里的定时器也依赖 event loop,并不是严格按照时间。所以虽然支持你用 ms 设置定时器,但什么时候触发其实不一定。所以建议至少以 10ms 为标准,也不要让不同定时器互相影响。

关注 3 回答 2

Meathill 回答了问题 · 4月2日

解决vue 计算属性

  1. 这里应该用 method,如果出于缓存数据的考虑,应该对整个数据进行格式化
  2. if (xxx) return true 太……直接 return xxx 就好了

关注 3 回答 2

Meathill 回答了问题 · 4月1日

vue3没有官方对应的dev-tools吗?

  1. 去 v3 的官网 https://v3.vuejs.org/
  2. 在导航里找 'Ecosystem'(生态)
  3. 在里面找到 Devtools https://github.com/vuejs/vue-...
  4. 在 README 里找到教程:https://github.com/vuejs/vue-...

关注 3 回答 2

Meathill 赞了文章 · 3月30日

CPU 提供了什么

为了方便理解,CPU 可以简单认为是:

  1. 一堆的寄存器,用于暂时存放数据
  2. 可以执行机器指令,完成运算 / 数据读写 等操作

寄存器

CPU 有很多的寄存器,这里我们只介绍 指令寄存器 和 通用寄存器。

指令寄存器

64 位下,指令寄存器叫 rip (32 位下叫 eip)。
指令寄存器用于存放下一条指令的地址,CPU 的工作模式,就是从 rip 指向的内存地址取一条指令,然后执行这条指令,同时 rip 指向下一条指令,如此循环,就是 CPU 的基本工作。

也就意味着,通常模式下 CPU 是按照顺序执行指令的。但是,CPU 也有一些特殊的指令,用于直接修改 rip 的地址。比如,jmp 0xff00 指令,就是把 rip 改为 0xff00,让 CPU 接下来执行内存中 0xff00 这个位置的指令。

通用寄存器

以 x86_64 来说,有 16 个“通用”寄存器。“通用”意味着可以放任意的数据,这 16 个寄存器并没有什么区别,但是实际上还是存在一些约定俗称的用法:

先看看这 8 个:
(这是原来 32 位架构下就有的,只是 32 位下是 e 开头的)

rax: "累加器"(accumulator), 很多加法乘法指令的缺省寄存器,函数返回值一般也放在这里
rbx: "基地址"(base)寄存器, 在内存寻址时存放基地址
rcx: 计数器(counter), 是重复(REP)前缀指令和 LOOP 指令的内定计数器
rdx: 用来放整数除法产生的余数,或者读写I/O端口时,用来存放端口号
rsp: 栈顶指针,指向栈的顶部
rbp: 栈底指针,指向栈的底部,通常用`rbp+偏移量`的形式来定位函数存放在栈中的局部变量
rsi: 字符串操作时,用于存放数据源的地址
rdi: 字符串操作时,用于存放目的地址的,和 rsi 经常搭配一起使用,执行字符串的复制等操作

另外还有 8 个,是 64 位架构下新增的:

r8, r9, r10, r11, r12, r13, r14, r15

机器指令

在 CPU 的世界里,只有 0 1 这种二进制的表示,所以指令也是用 0 1 二进制表示的。
然而,二进制对人类并不友好,所以有了汇编这种助记符。

算术运算

比如这段加法:

add    rax,rdx

比如这个汇编指令,表示:rax = rax + rdx,这就完成了一个加法的运算。
通常我们用 rax 寄存器来做加法运算,但是其他寄存器一样也可以完成加法运算的,比如:

add    rbx,0x1

这个表示 rbx = rbx + 0x1

这里的加法运算,都是在寄存器上完成的,也就是直接修改的寄存器的值。

跳转指令

比如这段无条件跳转指令

jmp 0x269e001c

CPU 默认是按照顺序执行指令的,跳转指令则是,让 CPU 不再顺序执行后续的指令,转而执行 0x269e001c 这个内存地址中的指令。
具体来说,将指令寄存器中的值改为 0x269e001c 即可,即:rip = 0x269e001c

内存读写指令

比如这一对 mov 指令:

mov rbp, [rcx]
mov [rcx], rbp

这里假设 rcx 的值,是一个内存地址,比如:0xff00
第一行 mov 指令,是将内存地址 0xff00 中的值,读取到 rbp 寄存器。
第二行 mov 指令,则是反过来,将 rbp 寄存器的值,写入到内存 0xff00 中。

栈操作

pushpop 这一对用于操作“栈”。
“栈”是内存空间中的一段地址,我们约定是以栈的形式来使用它,并且用 rsp 寄存器指向栈顶。

栈操作本质也是内存读写操作,只是以栈的方式来使用。

比如这一对:

push   rbp
pop    rbp

第一行是将 rbp 寄存器中的值压入栈,等效于:

sub rsp, 8       // rsp = rsp - 8; 栈顶向下生长 8 byte
mov [rsp], rbp   // rbp 的值写入新的栈顶

第二行则是反过来,栈顶弹出一个值,写入到 rbp 寄存器中,等效于:

mov rbp, [rsp]   // 栈顶的值写入 rbp
add rsp, 8       // rsp = rsp + 8; 栈顶向上缩小 8 byte

注意:因为栈在内存空间中是倒过来的,所以是向下生长的。

查看原文

赞 11 收藏 2 评论 0

Meathill 关注了用户 · 3月30日

doujiang24 @doujiang24

中年程序员

关注 412

Meathill 回答了问题 · 3月28日

git分支修改合并问题

  1. main 是主干,是发布的基础
  2. dev1 合并到 main,就应该删掉 dev1
  3. dev2 合并到 main,也应该删掉 dev2
  4. 将来有需要,再开分支
  5. dev2 不应该修改 dev1,每个分支只应该干自己的事情

关注 6 回答 5

Meathill 回答了问题 · 3月27日

Git子仓库如何操作?

git submodule 可以维护子仓库。不过根据我多年实践,子仓库并不好用,维护性和易用性都不如依赖管理,比如 node.js 下的 NPM。

关注 4 回答 3

Meathill 收藏了文章 · 3月27日

resty 命令行工具演示

https://www.bilibili.com/vide...

在本教程中,我们将演示如何使用 OpenResty 附带的 resty 命令行工具。

cd ~
export PATH=/usr/local/openresty/bin:$PATH
which resty

截图 1

一般都是这个路径。

我们可以通过 -V 选项检查其版本号。

resty -V

截图 3

如果你使用我们预构建的 Linux 二进制包安装 OpenResty,那么你应该安装 openresty-resty 包。

dnf list installed openresty-resty

截图 4

因为它不在 openresty 主包中。

比如用 resty 命令来做“hello world”,就容易多了。

resty -e 'print("Hello World")'

截图 6

注意 -e 选项。

或者在终端上运行一个 Lua 脚本。

echo 'print("Hello World")' > hello.lua
cat hello.lua
resty hello.lua

截图 8

所以这也是使用 OpenResty 编写新的命令行应用程序的好方法。

这里也可以实现非阻塞 I/O。

time resty -e 'ngx.sleep(1) ngx.say("done")'

截图 10

让我们使用 cosocket API 连接到 openresty.com 的 443 端口。

resty -e 'local sock = ngx.socket.tcp() print(sock:connect("openresty.com", 443))'

截图 11

或者使用轻线程。

resty -e 'ngx.thread.wait(ngx.thread.spawn(function () print("in thread!") end))'

截图 12

你也可以很容易地使用 Lua 模块。让我们创建一个 test 模块。

mkdir lua/
vim lua/test.lua

lua/test.lua文件是这样的。

local _M = {}

function _M.hello() print("Hello") end

return _M

截图 13

然后我们使用 -I 选项将 lua/ 目录添加到 Lua 模块搜索路径中。

resty -I lua/ -e 'require "test".hello()'

截图 14

如果没有 -I 选项,它就找不到。

resty -e 'require "test".hello()'

截图 15

这是因为 lua/ 目录默认不在 Lua 模块的搜索路径中。

可以直接加载标准的 Lua 模块,比如 resty.shell

resty -e 'local ok, stdout = require "resty.shell".run([[echo ok]]) print(stdout)'

截图 17

该模块用于非阻塞地运行少量 shell 命令。

我们也可以通过 --shdict 选项来定义 lua 共享内存字典。

resty --shdict 'dogs 10m' -e 'print(ngx.shared.dogs:set("age", 11))'

截图 19

可以这样定义多个共享词典。

resty --shdict 'dogs 7m' --shdict 'cats 5m' -e 'print(ngx.shared.dogs, " ", ngx.shared.cats)'

截图 20

它还可以方便地注入自定义的 nginx 配置代码。

resty --http-conf 'lua_regex_match_limit 102400;' -e 'print "ok"'

截图 21

我们还可以玩玩 LuaJIT 的 JIT 编译器。

让我们创建一个跑得比较热的 Lua 脚本。

echo 'local a = 0 for i = 1, 1e8 do a = a + 1 end print(a)' > bench.lua
cat bench.lua

截图 23

然后完全禁用 JIT 编译器。

time resty -joff bench.lua

截图 24

为了比较,我们可以检查一下启用 JIT 编译器后速度有多快。

time resty bench.lua

截图 25

或者我们可以用 -jv 选项检查编译后的 Lua 代码路径,或者说“traces”。

resty -jv bench.lua

截图 26

或者有更多的细节,比如编译后的字节码转储,IR 代码转储,以及机器代码转储。

resty -jdump bench.lua

你可以随时通过 -h 选项找到所有支持的功能。

resty -h

或者通过“restydoc”工具参考其文档。

restydoc resty-cli

如果你通过我们预建的二进制包安装 openresty,那么你应该安装 openresty-docopenresty-restydoc 包。

dnf list installed openresty-doc

截图 30

我们将在另一个专门的视频教程中更深入地了解“restydoc”工具。
如果你喜欢这个教程,请订阅这个博客网站和我们的 YouTube 频道B 站频道。谢谢!

<!-- xray "通过 OpenResty XRay 产品提升您应用的性能" -->

关于本文和关联视频

本文和相关联的视频都是完全由我们的 OpenResty Demo 系统从一个极简单的剧本文件自动生成的。

关于作者

章亦春是开源项目 OpenResty® 的创始人,同时也是 OpenResty Inc. 公司的创始人和 CEO。他贡献了许多 Nginx 的第三方模块,相当多 Nginx 和 LuaJIT 核心补丁,并且设计了 OpenResty XRay 等产品。

关注我们

如果您喜欢本文,欢迎关注我们 OpenResty Inc. 公司的博客网站 。也欢迎扫码关注我们的微信公众号:

我们的微信公众号

翻译

我们提供了英文版原文和中译版(本文) 。我们也欢迎读者提供其他语言的翻译版本,只要是全文翻译不带省略,我们都将会考虑采用,非常感谢!

查看原文

Meathill 赞了文章 · 3月27日

resty 命令行工具演示

https://www.bilibili.com/vide...

在本教程中,我们将演示如何使用 OpenResty 附带的 resty 命令行工具。

cd ~
export PATH=/usr/local/openresty/bin:$PATH
which resty

截图 1

一般都是这个路径。

我们可以通过 -V 选项检查其版本号。

resty -V

截图 3

如果你使用我们预构建的 Linux 二进制包安装 OpenResty,那么你应该安装 openresty-resty 包。

dnf list installed openresty-resty

截图 4

因为它不在 openresty 主包中。

比如用 resty 命令来做“hello world”,就容易多了。

resty -e 'print("Hello World")'

截图 6

注意 -e 选项。

或者在终端上运行一个 Lua 脚本。

echo 'print("Hello World")' > hello.lua
cat hello.lua
resty hello.lua

截图 8

所以这也是使用 OpenResty 编写新的命令行应用程序的好方法。

这里也可以实现非阻塞 I/O。

time resty -e 'ngx.sleep(1) ngx.say("done")'

截图 10

让我们使用 cosocket API 连接到 openresty.com 的 443 端口。

resty -e 'local sock = ngx.socket.tcp() print(sock:connect("openresty.com", 443))'

截图 11

或者使用轻线程。

resty -e 'ngx.thread.wait(ngx.thread.spawn(function () print("in thread!") end))'

截图 12

你也可以很容易地使用 Lua 模块。让我们创建一个 test 模块。

mkdir lua/
vim lua/test.lua

lua/test.lua文件是这样的。

local _M = {}

function _M.hello() print("Hello") end

return _M

截图 13

然后我们使用 -I 选项将 lua/ 目录添加到 Lua 模块搜索路径中。

resty -I lua/ -e 'require "test".hello()'

截图 14

如果没有 -I 选项,它就找不到。

resty -e 'require "test".hello()'

截图 15

这是因为 lua/ 目录默认不在 Lua 模块的搜索路径中。

可以直接加载标准的 Lua 模块,比如 resty.shell

resty -e 'local ok, stdout = require "resty.shell".run([[echo ok]]) print(stdout)'

截图 17

该模块用于非阻塞地运行少量 shell 命令。

我们也可以通过 --shdict 选项来定义 lua 共享内存字典。

resty --shdict 'dogs 10m' -e 'print(ngx.shared.dogs:set("age", 11))'

截图 19

可以这样定义多个共享词典。

resty --shdict 'dogs 7m' --shdict 'cats 5m' -e 'print(ngx.shared.dogs, " ", ngx.shared.cats)'

截图 20

它还可以方便地注入自定义的 nginx 配置代码。

resty --http-conf 'lua_regex_match_limit 102400;' -e 'print "ok"'

截图 21

我们还可以玩玩 LuaJIT 的 JIT 编译器。

让我们创建一个跑得比较热的 Lua 脚本。

echo 'local a = 0 for i = 1, 1e8 do a = a + 1 end print(a)' > bench.lua
cat bench.lua

截图 23

然后完全禁用 JIT 编译器。

time resty -joff bench.lua

截图 24

为了比较,我们可以检查一下启用 JIT 编译器后速度有多快。

time resty bench.lua

截图 25

或者我们可以用 -jv 选项检查编译后的 Lua 代码路径,或者说“traces”。

resty -jv bench.lua

截图 26

或者有更多的细节,比如编译后的字节码转储,IR 代码转储,以及机器代码转储。

resty -jdump bench.lua

你可以随时通过 -h 选项找到所有支持的功能。

resty -h

或者通过“restydoc”工具参考其文档。

restydoc resty-cli

如果你通过我们预建的二进制包安装 openresty,那么你应该安装 openresty-docopenresty-restydoc 包。

dnf list installed openresty-doc

截图 30

我们将在另一个专门的视频教程中更深入地了解“restydoc”工具。
如果你喜欢这个教程,请订阅这个博客网站和我们的 YouTube 频道B 站频道。谢谢!

<!-- xray "通过 OpenResty XRay 产品提升您应用的性能" -->

关于本文和关联视频

本文和相关联的视频都是完全由我们的 OpenResty Demo 系统从一个极简单的剧本文件自动生成的。

关于作者

章亦春是开源项目 OpenResty® 的创始人,同时也是 OpenResty Inc. 公司的创始人和 CEO。他贡献了许多 Nginx 的第三方模块,相当多 Nginx 和 LuaJIT 核心补丁,并且设计了 OpenResty XRay 等产品。

关注我们

如果您喜欢本文,欢迎关注我们 OpenResty Inc. 公司的博客网站 。也欢迎扫码关注我们的微信公众号:

我们的微信公众号

翻译

我们提供了英文版原文和中译版(本文) 。我们也欢迎读者提供其他语言的翻译版本,只要是全文翻译不带省略,我们都将会考虑采用,非常感谢!

查看原文

赞 1 收藏 1 评论 0

Meathill 回答了问题 · 3月26日

解决关于js自执行函数的问题?

不能。(紫薯布丁)

关注 4 回答 3

Meathill 回答了问题 · 3月25日

项目与项目自身依赖的npm包均引入了不同版本的公共模块导致打包后体积变大该如何解决?

  1. 项目中的依赖选择与依赖一致的依赖,即你也用 Bv0.0.2
  2. 选择依赖 Bv0.0.1 的 A
  3. 建议模块作者使用更宽泛的依赖标记,比如 ~(小版本一致)甚至 ^(大版本一致)

关注 5 回答 3

Meathill 回答了问题 · 3月25日

解决vue-cli4.0 项目发布浏览器缓存问题解决?

  1. 时间戳和 hash 的作用一样,工作原理也一样,任选一个就行
  2. index.html 里 <meta> 控制的缓存规则只有浏览器能理解,但实际上从源服务器到用户浏览器,中间可能经历很多环节,也存在多个缓存的可能,在源服务器上设置 nginx 进行缓存控制是合理的

关注 2 回答 1

Meathill 回答了问题 · 3月24日

Vue3.0 如何监听子组件的数据加载完成。

自组件加载完成广播一个事件,父组件侦听事件然后计数,计数够了就关闭 loading。

关注 2 回答 1

Meathill 回答了问题 · 3月24日

如何释放浏览器 js内存的问题?

确保被替换掉的 DOM 没有引用,没有未移除的事件侦听器,即可以被 GC 回收,然后等着 GC 自动回收即可。

关注 7 回答 6

Meathill 收藏了文章 · 3月24日

为 OpenResty 应用编写你自己的 Lua 模块

https://www.bilibili.com/vide...

今天我就来演示一下如何在 OpenResty 应用中编写自己的 Lua 模块,一步一步来。

screenshot 1

让我们把我们简单的 OpenResty 应用放到一个新的目录中,命名为 test-module

cd ~/
mkdir test-module/
cd test-module/

screenshot 2

然后我们像往常一样创建子目录结构。

mkdir logs conf lua

screenshot 3

请注意,与上一篇教程中的“Hello World”示例不同,我们在这里创建了一个 lua/ 目录来存放我们的 lua 模块文件。

现在让我们在 lua 子目录下创建我们自己的 Lua 模块文件,命名为 hello.lua

vim lua/hello.lua

我们进行如下编辑操作:

  1. 声明 Lua 模块表 _M
  2. 然后给这个 Lua 模块添加一个名为 greet 的函数。
  3. 最后,别忘了在最后返回模块表。
local _M = {}

function _M.greet(name)
    ngx.say("Greetings from ", name)
end

return _M

搞定!一个很简单的 Lua 模块就完成了。

现在是创建 nginx.conf 配置文件的时候了。

vim conf/nginx.conf

我们快速完成下列编辑操作:

  1. 我们快速写出相对固定的配置。
  2. http {} 配置块中,我们应该告诉 OpenResty 我们的 Lua 模块在哪里。
  3. 请注意,特殊变量 $prefix 在运行时被 nginx 的 -p 选项值所替代。
  4. 然后我们创建一个 HTTP 服务器,监听 8080 端口。
  5. 并在根位置配置 content_by_lua"_block
  6. 这里我们用 require 内置函数加载 Lua 模块 hello
  7. 我们用一个参数调用它的 greet 函数。
worker_processes 1;

events {
    worker_connections 1024;
}

http {
    lua_package_path "$prefix/lua/?.lua;;";

    server {
        listen 8080 reuseport;

        location / {
            default_type text/plain;
            content_by_lua_block {
                local hello = require "hello"
                hello.greet("a Lua module")
            }
        }
    }
}

我们现在就来检查整个目录树。

tree .

screenshot 22

看起来不错。

现在启动这个 OpenResty 应用程序。

nginx -p $PWD/

screenshot 24
是时候用 curl 命令行工具查询我们的 HTTP 接口了。

curl 'http://127.0.0.1:8080/'

screenshot 25

酷,我们的 Lua 模块开始工作了。

我们也可以在网页浏览器中进行测试。

screenshot 28

如果你看到了 500 错误页面,那么你的 Lua 代码一定有错误。

在这种情况下,你应该检查 logs 子目录下的 error.log 文件。

tail logs/error.log

screenshot 30

这里我们没有任何错误消息,正如预期的那样。

值得注意的是,我们的 Lua 模块是在这第一个请求中加载的,后续的请求只是使用内存中缓存的 Lua 模块。
为了避免第一次请求的额外开销,我们可以在服务器启动时预加载 Lua 模块。

要做到这一点,我们需要编辑一下 nginx.conf 文件。

vim conf/nginx.conf

http {} 块里,我们添加一个 init_by_lua_block 指令。在那个上下文中,我们加载我们的 Lua 模块。

    http {
        init_by_lua_block {
            require "hello"
        }
        ...

screenshot 34

init_by_lua_block 运行在 OpenResty 服务器启动的时候。

测试一下配置是否正确。

nginx -p $PWD/ -t

screenshot 37

没有问题。

现在我们通过向 nginx 主进程发送 HUP 信号来重新加载服务器。
Now we reload the server by sending the HUP signal to the nginx master process.

kill -HUP `cat logs/nginx.pid`

screenshot 39

主进程的进程 ID 存储在这个 nginx.pid 文件中。

再次发送 HTTP 请求。

curl 'http://127.0.0.1:8080/'

screenshot 41

同样的行为,只是这次快了一点点。
如果你喜欢这个教程,请订阅这个博客网站和我们的 YouTube 频道B 站频道。谢谢!

关于本文和关联视频

本文和相关联的视频都是完全由我们的 OpenResty Demo 系统从一个极简单的剧本文件自动生成的。

关于作者

章亦春是开源项目 OpenResty® 的创始人,同时也是 OpenResty Inc. 公司的创始人和 CEO。他贡献了许多 Nginx 的第三方模块,相当多 Nginx 和 LuaJIT 核心补丁,并且设计了 OpenResty XRay 等产品。

关注我们

如果您喜欢本文,欢迎关注我们 OpenResty Inc. 公司的博客网站 。也欢迎扫码关注我们的微信公众号:

我们的微信公众号

翻译

我们提供了英文版原文和中译版(本文) 。我们也欢迎读者提供其他语言的翻译版本,只要是全文翻译不带省略,我们都将会考虑采用,非常感谢!

查看原文

Meathill 赞了文章 · 3月24日

为 OpenResty 应用编写你自己的 Lua 模块

https://www.bilibili.com/vide...

今天我就来演示一下如何在 OpenResty 应用中编写自己的 Lua 模块,一步一步来。

screenshot 1

让我们把我们简单的 OpenResty 应用放到一个新的目录中,命名为 test-module

cd ~/
mkdir test-module/
cd test-module/

screenshot 2

然后我们像往常一样创建子目录结构。

mkdir logs conf lua

screenshot 3

请注意,与上一篇教程中的“Hello World”示例不同,我们在这里创建了一个 lua/ 目录来存放我们的 lua 模块文件。

现在让我们在 lua 子目录下创建我们自己的 Lua 模块文件,命名为 hello.lua

vim lua/hello.lua

我们进行如下编辑操作:

  1. 声明 Lua 模块表 _M
  2. 然后给这个 Lua 模块添加一个名为 greet 的函数。
  3. 最后,别忘了在最后返回模块表。
local _M = {}

function _M.greet(name)
    ngx.say("Greetings from ", name)
end

return _M

搞定!一个很简单的 Lua 模块就完成了。

现在是创建 nginx.conf 配置文件的时候了。

vim conf/nginx.conf

我们快速完成下列编辑操作:

  1. 我们快速写出相对固定的配置。
  2. http {} 配置块中,我们应该告诉 OpenResty 我们的 Lua 模块在哪里。
  3. 请注意,特殊变量 $prefix 在运行时被 nginx 的 -p 选项值所替代。
  4. 然后我们创建一个 HTTP 服务器,监听 8080 端口。
  5. 并在根位置配置 content_by_lua"_block
  6. 这里我们用 require 内置函数加载 Lua 模块 hello
  7. 我们用一个参数调用它的 greet 函数。
worker_processes 1;

events {
    worker_connections 1024;
}

http {
    lua_package_path "$prefix/lua/?.lua;;";

    server {
        listen 8080 reuseport;

        location / {
            default_type text/plain;
            content_by_lua_block {
                local hello = require "hello"
                hello.greet("a Lua module")
            }
        }
    }
}

我们现在就来检查整个目录树。

tree .

screenshot 22

看起来不错。

现在启动这个 OpenResty 应用程序。

nginx -p $PWD/

screenshot 24
是时候用 curl 命令行工具查询我们的 HTTP 接口了。

curl 'http://127.0.0.1:8080/'

screenshot 25

酷,我们的 Lua 模块开始工作了。

我们也可以在网页浏览器中进行测试。

screenshot 28

如果你看到了 500 错误页面,那么你的 Lua 代码一定有错误。

在这种情况下,你应该检查 logs 子目录下的 error.log 文件。

tail logs/error.log

screenshot 30

这里我们没有任何错误消息,正如预期的那样。

值得注意的是,我们的 Lua 模块是在这第一个请求中加载的,后续的请求只是使用内存中缓存的 Lua 模块。
为了避免第一次请求的额外开销,我们可以在服务器启动时预加载 Lua 模块。

要做到这一点,我们需要编辑一下 nginx.conf 文件。

vim conf/nginx.conf

http {} 块里,我们添加一个 init_by_lua_block 指令。在那个上下文中,我们加载我们的 Lua 模块。

    http {
        init_by_lua_block {
            require "hello"
        }
        ...

screenshot 34

init_by_lua_block 运行在 OpenResty 服务器启动的时候。

测试一下配置是否正确。

nginx -p $PWD/ -t

screenshot 37

没有问题。

现在我们通过向 nginx 主进程发送 HUP 信号来重新加载服务器。
Now we reload the server by sending the HUP signal to the nginx master process.

kill -HUP `cat logs/nginx.pid`

screenshot 39

主进程的进程 ID 存储在这个 nginx.pid 文件中。

再次发送 HTTP 请求。

curl 'http://127.0.0.1:8080/'

screenshot 41

同样的行为,只是这次快了一点点。
如果你喜欢这个教程,请订阅这个博客网站和我们的 YouTube 频道B 站频道。谢谢!

关于本文和关联视频

本文和相关联的视频都是完全由我们的 OpenResty Demo 系统从一个极简单的剧本文件自动生成的。

关于作者

章亦春是开源项目 OpenResty® 的创始人,同时也是 OpenResty Inc. 公司的创始人和 CEO。他贡献了许多 Nginx 的第三方模块,相当多 Nginx 和 LuaJIT 核心补丁,并且设计了 OpenResty XRay 等产品。

关注我们

如果您喜欢本文,欢迎关注我们 OpenResty Inc. 公司的博客网站 。也欢迎扫码关注我们的微信公众号:

我们的微信公众号

翻译

我们提供了英文版原文和中译版(本文) 。我们也欢迎读者提供其他语言的翻译版本,只要是全文翻译不带省略,我们都将会考虑采用,非常感谢!

查看原文

赞 2 收藏 1 评论 0

Meathill 回答了问题 · 3月23日

window.location.href给界面添加遮罩问题

window.location.href 相当于新打开一个页面,而新页面只有下载功能,所以你的当前页面无法获取下载的任何信息。

所以你只能在开始下载的时候,给当前页面加上遮罩,然后在遮罩里用文本提示用户,等下载完成再关闭遮罩。

或者,考虑改成 ajax 下载,下载完成后用 <a download="filename.ext"> 触发下载,理论上也可以满足需要。

关注 2 回答 1

Meathill 回答了问题 · 3月23日

解决复制一段js代码到phpstorm中,空格怎么变成NBSP了?

多半是那个网页有意做的防复制粘贴吧。NBSP 没记错的话就是零宽空格,不影响阅读,但影响执行,phpstorm 作为 IDE,主动显示出来,避免出错;记事本里面只是看不到而已,并不是不存在。

自己手动删除吧。

关注 2 回答 2

Meathill 回答了问题 · 3月20日

解决Nginx 部署Vue项目后,走链接跳转页面可以,手动刷新404请求url也改变了

  1. 内部链接走 pushState,大部分不发起新请求,所以也不会遭遇 404
  2. nginx 需要把所有未命中请求定位到 /index.html,由 /index.html 处理,即 try_files 的部分
  3. 空白的原因可能有很多,你可以先看下 index.html 和 js 有没有正常加载。按我以前的经验,此时比较大的可能是组件里有错误,但是编译后,Vue 把隐蔽了。可以试试全局 errorHandler 或者 Vue Devtools

关注 2 回答 1

Meathill 回答了问题 · 3月19日

解决github彻底上不去了怎么办??

买个香港服务器做反向代理。

关注 4 回答 3