我当前有一个运行部署到 Tomcat 的 Java 应用程序的 Elastic Beanstalk 实例。我使用 Web 界面部署应用程序,但应用程序使用 web.xml 中引用的数据文件(Lucene 索引),我通过 ssh-ing 到 EC2 并从 S3 存储桶获取数据文件将其复制到底层 EC2 实例。
到目前为止,一切都很好。
但是,如果我将 EB 更改为可自动扩展的环境,以便它根据需要自动创建新实例,那么这些 EC2 实例将没有数据文件,我该如何处理这个问题。
- 我可以在实际使用每个 EC2 实例之前使用数据文件对其进行预配置吗?
- 我可以有一个每个服务器都可以引用的共享文件系统(数据文件是只读的)吗?
* 更新 *
我想我已经从原则上找到了答案。我从本地计算机上传应用程序,然后从亚马逊添加大型数据文件。我需要做的是在我的数据处理 EC2 实例上构建我的战争,将数据文件添加到战争中的某个位置,然后将此战争放到 S3 上,然后当我创建 EB 时,我需要从 S3 存储桶加载 WAR。
所以只需要弄清楚数据文件在 War 中应该放在哪里以及如何通过 Maven 构建过程来创建。
*更新2*
实际上,不清楚数据文件到底应该放在 WAR 文件中,我看不到将它们放在哪里,并且应用程序希望它们是真实的文件,因此如果包含在 WAR 中并且 WAR 没有扩展/解压缩(我不知道EB)做什么应用程序无论如何都不会工作。
*更新3*
我当然可以将数据放入 S3 中(事实上它可能会在那里开始)所以我想知道在服务器初始化时我是否可以获取 s3 数据并将其放在某个地方然后使用它?
请指导。
*更新4*
因此,使用 s3 的想法,我几乎可以让它工作,在 servlet init() 方法中,我获取压缩文件,将其保存到当前工作目录(/usr/share/tomcat7/),然后解压缩它。问题是压缩文件为2.7GB,解压缩后的文件夹为5GB,EB使用的小实例提供8GB,其中使用了2GB。所以我有 6GB 足够的空间用于未压缩的文件,但不能保存压缩文件然后解压缩它,因为在解压缩过程中我需要 2.7 GB + 5 GB。
我将压缩版本加载到S3,因为原始数据不是单个文件,而是一个充满文件的文件夹,很难作为文件列表进行管理。我无法更改 EB 中根目录的大小,我可以尝试更改为功能强大的实例,但这会不必要地更加昂贵,并且不清楚 ECB 使用的实例提供了哪些磁盘空间。有任何想法吗 ?
这些是我添加到我的 Maven 存储库中的依赖项
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.8.2</version>
</dependency>
<dependency>
<groupId>org.rauschig</groupId>
<artifactId>jarchivelib</artifactId>
<version>0.6.0</version>
</dependency>
这是代码
@Override
public void init()
{
try
{
log.severe("Retrieving Indexes from S3");
AWSCredentials credentials = new BasicAWSCredentials("***********", "***********");
AmazonS3Client ac = new AmazonS3Client(credentials);
log.severe("datalength-testfile:"+ac.getObjectMetadata("widget","test.txt").getContentLength());
File testFile = new File("test.txt");
ac.getObject(new GetObjectRequest("widget", "test.txt"), testFile);
log.severe("datalength-testfile:retrieved");
log.severe("datalength-largefile:"+ac.getObjectMetadata("widget","indexes.tar.gz").getContentLength());
File largeFile = new File("indexes.tar.gz");
ac.getObject(new GetObjectRequest("widget", "indexes.tar.gz"), largeFile);
log.severe("datalength-largefile:retrieved");
log.severe("Retrieved Indexes from S3");
log.severe("Unzipping Indexes");
File indexDirFile = new File(indexDir).getAbsoluteFile();
indexDirFile.mkdirs();
Archiver archiver = ArchiverFactory.createArchiver(largeFile);
archiver.extract(largeFile, indexDirFile);
log.severe("Unzipped Indexes");
}
catch(Exception e)
{
log.log(Level.SEVERE, e.getMessage(), e );
}
}
*更新5*
意识到微型 EC2 实例仅提供 0.6GB 而不是 6GB 后,我无论如何都需要更新到一台更大的机器,并且它提供了两个磁盘,这样我就可以将压缩文件复制到一个磁盘,然后成功解压缩到根磁盘,所以准备好了。
*更新6*
EB 不尊重 init() 方法,因此在自动缩放的 EB 配置中,它会启动其他 EC2 实例,并相信第一个实例已过载,而实际上它刚刚准备好。我怀疑,如果在真正繁忙时启动新的实例,负载均衡器将在这些实例准备好之前开始向这些实例提供请求,从而导致请求失败。
*更新7*
尝试将索引直接放入 WEB-INF/classes 并引用 web.xml 中的该位置。这适用于本地测试 Tomcat 部署,但不幸的是在 EB 中失败,因为抱怨
所以看来 EB 不尊重 init()。因此,我没有尝试在 init() 方法中从 S3 获取索引,而是将索引直接放入 WEB-INF/classes 下的 War 文件中,并将 web.xml 中的参数指向那里。尽管它们实际上不是类,但这不会对 Tomcat 造成问题,并且我已经针对本地 Tomcat 安装进行了部署测试,没有出现任何问题。
不幸的是,将包含索引的较大 war 文件上传到 S3 后,尝试将其从 S3 位置部署到 EB 失败,并显示:
无法启动环境:源包为空或超过允许的最大大小:524288000。
亚马逊为什么要施加这种任意限制?
*更新8*
所以可能的选择是
- 电子扩展
- Docker部署
- 创建自定义 Amazon 映像以与 EB 一起使用
第三个选项似乎很老套,并不是所有人都热衷于此,或者真的非常热衷于其他选项。
* 更新 9 **
我最终让它与 ebextensions 一起工作,还不错,我在这里记录以防万一有用
如果使用 maven 在 src/main/resources 中创建文件夹 ebextensions
将以下内容添加到 pom.xml (sao ebextensions 在最终战争中出现在正确的位置)
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
<directory>src/main/ebextensions</directory>
<targetPath>.ebextensions</targetPath>
<filtering>true</filtering>
</resource>
</webResources>
</configuration>
</plugin>
在 ebextensions 文件夹中创建 .config 文件(我称之为 copyindex.cfg),我的有此信息
commands:
01_install_cli:
command: wget https://s3.amazonaws.com/aws-cli/awscli-bundle.zip; unzip awscli-bundle.zip; ./awscli-bundle/install -b ~/bin/aws
02_get_index:
command:
aws s3 cp --region eu-west-1 s3://jthink/release_index.tar.gz /dev/shm/release_index.tar.gz;
cd /usr/share/tomcat7; tar -xvf /dev/shm/release_index.tar.gz
转到 IAM 控制台(https://console.aws.amazon.com/iam/home?#home https://console.aws.amazon.com/iam/home?#home) 并将角色策略高级用户附加到 Elastic Beanstalk 角色用户
部署您的应用程序