英文:
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
该示例要求你执行以下操作之一:
- 启动一个 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:
- 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论