在 Elastic Beanstalk 中扩展实例会破坏 python 烧瓶应用程序的动态图像链接

Posted

技术标签:

【中文标题】在 Elastic Beanstalk 中扩展实例会破坏 python 烧瓶应用程序的动态图像链接【英文标题】:Scaling Instances in Elastic Beanstalk breaks dynamic image link of python flask app 【发布时间】:2018-08-03 11:54:50 【问题描述】:

以下代码在本地机器上以及在 AWS Elastic BeanStalk 上的部署中都能出色地工作 - 提供固定图像以及动态创建的图像。但是,一旦我将部署扩展到多个 EC2 实例,动态创建的图像就会变得不可用,即使我可以(通过 ssh)找到该动态图像存在于 EC2 实例中!

我怀疑,这与我在 html 中引用静态图像的方式或负载平衡器处理静态图像的方式有关。但是,不知道从哪里开始调查。请帮忙! :(

    <code>
    from flask import Flask, render_template, request, url_for
    import os, datetime
    import thread
    import time
    from copy import deepcopy
    import pyqrcode # generating image of QR code from given string
    application = Flask(__name__)

    class QR(object):
        def __init__(self):
            self.input_string = None
            self.output_string = None
            self.input_image_filename = None

        def encode(self, input_string, QR_image_filename, QR_image_scale):
            """Return the image of QR code"""
            if not input_string:
                raise RuntimeError('Input string is empty!') # checking that input_string is not empty
            else:
                self.input_string = input_string

            try:
                qr = pyqrcode.create(self.input_string)
                qr.png(QR_image_filename, scale=QR_image_scale)
                return True
            except Exception as e:
                print "printing exception : " + str(e)
                raise RuntimeError('QR creation failed!')


    def background_deletion_task(path):
        print "wait starts"
        # gevent.sleep(5)
        time.sleep(5)
        print "wait done"
        if os.path.exists(path):
            os.remove(path)
            print "deletion done"

    @application.route('/')
    def hello():
        gen_qr = QR()
        gen_qr.qr_time = datetime.datetime.utcnow().isoformat()
        gen_qr.image_file_name = str(gen_qr.qr_time[-6:]) + ".png"
        gen_qr.full_path = os.path.join(application.root_path, 'static', gen_qr.image_file_name)
        gen_qr.encode(str(gen_qr.image_file_name), gen_qr.full_path, 4)
        # ---------------deletion by thread------------
        #thread.start_new_thread(background_deletion_task, (gen_qr.full_path,))
        return render_template('hello.html', gen_qr = gen_qr)

    if __name__ == "__main__":
        #application.debug=True
        application.run()
</code>

<html>
<body>

Fixed Image

<img src="/static/EYN_Logo.png" style="max-width: 150px;">

Dynamically Created Image

<img src="/static/gen_qr.image_file_name">

</body>
</html>

【问题讨论】:

【参考方案1】:

您似乎是在单个服务器上创建实例,但在负载平衡的环境中,您可能拥有多个服务器,并且这些服务器可以随时进出。

所以基本上,永远不要在 EC2 实例上存储任何状态信息。

要解决这个问题,您有几个选择。最好的选择是将图像存储在 S3 中 - 如果您仍希望在 /static/ 下引用它们,那么您可以使用 Cloudfront 将该路径映射到 S3 存储桶。

另一种选择是使用 EFS 在您的所有 EC2 实例上挂载一个共享文件系统。

请记住,EFS 大约是 S3 存储成本的 10 倍。

【讨论】:

【参考方案2】:

我找到了一种可行的解决方法,但并不完全相信这是正确的方法。这就是现在对我有用的方法。

首先,我在 .exbextension 下添加了一个ANY_NAME.config,内容如下 option_settings: aws:elasticbeanstalk:container:python:staticfiles: "/static/": "static/" 这是明确告诉 EBS 在哪里可以找到静态文件。

其次,我通过&lt;img src=" url_for('static', filename=fname ) "&gt;而不是&lt;img src="/fname"&gt;调用了html

在哪里return render_template('hello.html', fname = fname)

在此之后,eb scale 2 可以很好地处理动态文件。

正如 chris 所提到的,虽然它有效,但也许更好的方法是从 S3 存储桶中提供图像(无论是动态创建的还是静态的)。

【讨论】:

以上是关于在 Elastic Beanstalk 中扩展实例会破坏 python 烧瓶应用程序的动态图像链接的主要内容,如果未能解决你的问题,请参考以下文章

在 AWS Elastic Beanstalk 上扩展 Magento

将文件添加到 AWS Elastic Beanstalk 实例

在 Elastic Beanstalk 上使用 catalina.out 缓解存储问题

重新部署后如何使用 Elastic Beanstalk 处理经典负载均衡器

如何在 Elastic Beanstalk 中为 Auto Scaling EC2 实例配置触发器?

AWS Elastic Beanstalk 运行状况检查偶尔失败