在 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 在哪里可以找到静态文件。
其次,我通过<img src=" url_for('static', filename=fname ) ">
而不是<img src="/fname">
调用了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 处理经典负载均衡器