Perl Mojolicious: 处理代理超时

huangapple go评论65阅读模式
英文:

Perl Mojolicious: handling proxy timeouts

问题

在反向代理后面有一个Mojolicious应用。Mojolicious应用使用Promises,在某些情况下,同步响应在2分钟后返回,这时反向代理会超时。

如何最好地渲染响应?(很不幸,让我的子例程更早地响应不是一个选项)

  • 我可以显示一个临时页面,然后在之后提交/渲染最终响应吗?
  • 我可以使用Ajax来显示一个"spinner",然后在完成后渲染最终响应吗?
  • 我应该切换到异步,也许集成Mojolicious和Minion,并渲染一个响应,通过Ajax检查异步调用是否已准备就绪?(欢迎提供指引和示例)。

我使用docker演示了这种行为,使用一个在5秒后超时的反向代理和一个在10秒后响应的mojo应用:

1. 创建一个Dockerfile

FROM docker.io/library/perl:5.36
# 安装Apache2
RUN apt-get update && apt-get install -y --no-install-recommends apache2
# 安装Mojolicious
RUN cpanm Mojolicious
# 安装Apache mod_proxy并将Apache2配置为反向代理到mojo应用,超时时间为5秒
RUN a2enmod proxy_http \
    && perl -i.bak -pe 's#</VirtualHost>#\tProxyPass /mojo http://localhost:3000/ keepalive=On timeout=5\n</VirtualHost>#' /etc/apache2/sites-enabled/000-default.conf
# 生成一个mojo应用并模拟一个计时器
RUN mojo generate app \
    && perl -i.bak -pe 's/^.*$/  sleep(10);/ if $. == 6' /my_app/lib/MyApp/Controller/Example.pm
# 暴露Apache2和Mojo端口
EXPOSE 80 3000
# 在后台运行Apache 2和在前台运行Morbo
CMD ["/bin/bash", "-c", "apache2ctl start; /my_app/script/my_app prefork"]

2. 构建和运行:

docker build -t myapp .
docker run --rm --name myapp -p 8080:80 -p 3000:3000 myapp

3. 浏览到:

http://localhost:8080/mojo
英文:

I have a Mojolicious App behind a reverse proxy. The Mojo App uses Promises, and in some cases, the synchronous response is returned after 2 minutes, by which time, the reverse proxy times out.

How can I best render the response? (making my subroutine respond sooner, unfortunately, is not an option)

  • Can I show a temporary page, but commit / render the final response afterwards?
  • Can I use Ajax to show a spinner, then render the final response once done?
  • Should I switch to Async, perhaps integrate Mojolicious with Minion, and render a response that checks if the async call is ready via Ajax? (pointers and samples would be appreciated).

I demonstrate this behavior using docker below with a reverse proxy that times out after 5 seconds, and a mojo app that responds after 10 seconds:

1. Create a Dockerfile

FROM docker.io/library/perl:5.36
# Install Apache2
RUN apt-get update && apt-get install -y --no-install-recommends apache2
# Install Mojolicious
RUN cpanm Mojolicious
# Install Apache mod_proxy and configure Apache2 as a reverse proxy to mojo app with 5s timeout
RUN a2enmod proxy_http \
    && perl -i.bak -pe 's#</VirtualHost>#\tProxyPass /mojo http://localhost:3000/ keepalive=On timeout=5\n</VirtualHost>#' /etc/apache2/sites-enabled/000-default.conf
# Generate a mojo app and simulate a timer
RUN mojo generate app \
    && perl -i.bak -pe 's/^.*$/  sleep(10);/ if $. == 6' /my_app/lib/MyApp/Controller/Example.pm
# Expose Apache2 and Mojo ports
EXPOSE 80 3000
# Run Apache 2 in the background and Morbo in the foreground
CMD ["/bin/bash", "-c", "apache2ctl start; /my_app/script/my_app prefork"]

2. Build & run:

docker build -t myapp .
docker run --rm --name myapp -p 8080:80 -p 3000:3000 myapp

3. Browse to:

http://localhost:8080/mojo

答案1

得分: 1

我最终采用了异步方法,使用 Minion 作为队列。LinkCheck 应用的完整工作示例提供在以下链接:

https://github.com/mojolicious/minion/tree/main/examples/linkcheck

该示例要求你执行以下操作之一:

  1. 启动一个 Postgres 数据库,例如使用 docker
docker run --rm --name postgres -e POSTGRES_HOST_AUTH_METHOD=trust -p 5432:5432 postgres:15

或者
2. 替换启动过程中的一行 ,使用 SQLite 而不是 Postgres。(需要 Minion::Backend::SQLite 插件)

$self->plugin(Minion => {SQLite=>'sqlite:minion.db'});

在任何情况下,你必须运行一个单独的后台工作进程来处理作业队列,例如:

perl script/linkcheck minion worker
英文:

I ended up going with an asynchronous approach using Minion as a queue. A full working example of a LinkCheck application is provided at:

https://github.com/mojolicious/minion/tree/main/examples/linkcheck

The example requires you either:

  1. Start a Postgres Database, for example using docker:
docker run --rm --name postgres -e POSTGRES_HOST_AUTH_METHOD=trust -p 5432:5432 postgres:15

OR
2. Replace one line during startup to use SQLite instead of Postgres. (requires Minion::Backend::SQLite plugin )

$self->plugin(Minion => {SQLite=>'sqlite:minion.db'});

In either cases, you must run a separate a background worker process to handle the job queue, for example:

perl script/linkcheck minion worker

答案2

得分: 0

你应该查看流式响应,并在构建它们时将响应的块部分写入,而不是在整个响应构建完成后发送它们,详见 https://docs.mojolicious.org/Mojolicious/Guides/Rendering#Streaming

英文:

You should look at a streaming response, and writing chunks of your response as you they are built, rather than sending them after the whole response is built, see https://docs.mojolicious.org/Mojolicious/Guides/Rendering#Streaming

huangapple
  • 本文由 发表于 2023年4月7日 03:50:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/75953264.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定