了解 OpenResty XRay 是如何做到帮助企业定位应用程序存在的问题以及优化其效率的。

了解更多

在这个视频中,我将演示如何在 OpenResty 中进行流式 HTTP 响应体输出。

cd ~/
mkdir stream-resp/
cd stream-resp/

我们一如既往地创建子目录结构。

mkdir logs conf html

我们快速写出模板配置。

vim conf/nginx.conf

并在此文件中进行以下编辑。

  1. 我们创建一个 HTTP 服务器,监听 8080 端口。
  2. 增加一个 /test 位置。
  3. 指定这个 application/octet-stream MIME 类型是很重要的,这样才能让 Chrome 网络浏览器满意。
  4. 通过 content_by_lua_block 指令添加一些 Lua 代码。
  5. 我们每隔一秒输出一行输出。
  6. 我们需要显式调用 ngx.flush 方法来刷新 Nginx 的写缓冲区。这是一个 100% 非阻塞的调用。
  7. 而我们使用 ngx.sleep 在每次循环迭代中睡一秒钟。这也是非阻塞的。
  8. 然后我们为 html 目录创建一个根位置。
worker_processes 1;

events {
    worker_connections 1024;
}

http {
    server {
        listen 8080 reuseport;

        location = /test {
            default_type application/octet-stream;

            content_by_lua_block {
                for i = 1, 4 do
                    ngx.say("hello ", i)
                    ngx.flush(true)
                    ngx.sleep(1) -- sec
                end
            }
        }

        location / {
            default_type text/html;
            root html;
        }
    }
}

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

tree .

截图 16

看起来不错。

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

openresty -p $PWD/

截图 18

是时候用 curl 来查询我们的 HTTP 位置了。

curl 'http://127.0.0.1:8080/test'

截图 19

酷,确实是每秒生成一行字!

为了验证一切是否真的是非阻塞的,我们可以用 weighttp 工具加载这个 HTTP API。请注意,这将需要一段时间,因为我们在这里故意放慢响应速度。

weighttp -c 500 -k -n 500 127.0.0.1:8080/test

截图 21

因此,在 500 个并发请求的情况下,我们仍然可以实现每秒 120 个以上的请求!需要注意的是,每个请求需要 4 秒才能完成。而这里我们只使用了一个工作进程和一个操作系统线程。

我们仍然可以将并发量提高很多,但是我们需要对 Nginx 配置进行相应的调整。

vim conf/nginx.conf

比如把 worker_connections 调到一个较大的数值。

截图 24

通过启用访问日志缓冲也可以获得更好的性能。我们还可以减少请求内存池的大小。

现在让我们创建一个 HTML 页面,在 Web 浏览器中进行测试。

vim html/a.html

我们在这个文件中进行以下编辑。

  1. 增加一个 DIV 标签,以保持输出。
  2. 添加一些 JavaScript 来发送 AJAX 请求到我们之前的 HTTP 位置。
  3. 我们取出 DIV 元素。
  4. 让我们添加一个 JavaScript 函数来进行流式响应接收。
  5. 确保有新的数据。
  6. 将我们的新数据追加到 DIV 元素中。在这里,我们是懒惰的。我们不需要对特殊的 HTML 字符进行转义。
  7. 而且我们每秒都会检查新的传入响应数据。
  8. 火狐支持更巧妙的方式,但我们也要支持 Chrome。
  9. 最后,我们处理响应体流的结束。
  10. 最后一次检查响应数据。
  11. 删除我们的定期计时器。
  12. 并将最终的输出结果追加到网页上。
  13. 为了简洁起见,我们在此省略错误处理。
<!doctype html>
<html>
<body>
<div style="margin: 2em;" id="out"></div>

<script>
(function () {
    let xhttp = new XMLHttpRequest();
    xhttp.open("GET", "/test", true);
    xhttp.send();

    let div = document.getElementById("out")

    let total_len = 0
    let check_resp = function () {
        let resp = xhttp.responseText
        let len = resp.length

        if (len > total_len) {
            let new_data = resp.substring(total_len, len)
            total_len = len;

            div.innerHTML += new_data + "<br/>"
        }
    };

    let timer = setInterval(check_resp, 1000);
    check_resp();

    xhttp.onreadystatechange = function () {
        if (this.readyState == 4) {
            check_resp();
            clearInterval(timer);
            div.innerHTML += "done<br/>";
        }
    };
})();
</script>
</body>
</html>

我们再来检查一下整个目录树。

tree .

截图 44

我们不需要重新加载或重新启动 OpenResty 服务器,因为它只是一个静态的 HTML 页面。

ps aux|grep nginx|grep -v /tmp/

截图 45

是时候用 Chrome 打开这个 HTML 页面了。

截图 46

生效了!这就是我今天要讲的全部内容。 如果你喜欢这个教程,请订阅这个博客网站和我们的 YouTube 频道B 站频道。谢谢!

关于本文和关联视频

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

关于作者

章亦春是开源 OpenResty® 项目创始人兼 OpenResty Inc. 公司 CEO 和创始人。

章亦春(Github ID:agentzh),出生于中国江苏,现定居美国硅谷。他是中国早期开源技术和文化的倡导者和领军人物,曾供职于多家国际知名的高科技企业,如 Cloudflare、Yahoo!、Alibaba, 是 “边缘计算“、”动态追踪 “和 “机器编程 “的先驱,拥有超过 22 年的编程及 16 年的开源经验。作为拥有超过 4000 万全球域名用户的开源项目的领导者,章亦春被许多业内开发者描述为开源领域的“传奇“。他基于其 OpenResty® 开源项目打造的高科技企业 OpenResty Inc. 位于美国硅谷中心。其主打的三个产品 OpenResty XRay(利用动态追踪技术的非侵入式的故障剖析和排除工具)、OpenResty Edge(最适合微服务和分布式流量的全能型网关软件)以及 OpenResty Plus(加强版 Web 应用服务器) ,广受全球数十家上市及大型企业青睐。在 OpenResty 以外,章亦春为多个开源项目贡献了累计超过百万行代码,其中包括,Linux 内核、Nginx、LuaJIT、GDB、SystemTap、LLVM、Perl 等,并编写过 60 多个开源软件库。

关注我们

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

我们的微信公众号

翻译

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