如何在自动调整的(多实例)Elastic Beanstalk(Tomcat)应用程序(AWS)中配置数据文件?

时间:2014-06-26 12:55:17

标签: tomcat amazon-web-services elastic-beanstalk

我目前有一个Elastic Beanstalk实例运行部署到Tomcat的Java应用程序。我使用Web界面部署应用程序,但应用程序使用web.xml中引用的数据文件(Lucene索引),我通过ssh-ing到EC2并从我的S3存储桶中获取数据文件来复制到底层EC2实例。 / p>

到目前为止一切顺利。

但是,如果我将EB更改为可自动缩放的环境,以便它根据需要自动创建新实例,那么这些EC2实例将没有数据文件,我该如何处理。

  1. 在实际使用之前,我可以使用数据文件预先配置每个EC2实例吗?
  2. 我可以拥有每个服务器可以引用的共享fs(数据文件是只读的)吗?
  3. *更新*

    我认为我原则上已经找到了答案。我是从我的本地计算机上传我的应用程序,然后从亚马逊添加大数据文件。我需要做的是在我的数据处理EC2实例上构建我的战争,在某处将数据文件添加到war中,然后将此战争放到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 repo中的依赖项

      <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 *

    所以可能的选择是

    • ebextensions
    • Docker部署
    • 创建用于EB的自定义亚马逊图像

    第三种选择看起来非常h​​acky,并非全都热衷于此,或者非常热衷于其他人。

    *更新9 **

    我最终使用ebextensions,不是太糟糕,我在这里记录以防万一有用

    如果在src / main / resources中使用maven create folder ebextensions 将以下内容添加到pom.xml(在最后的战争中ebextensions出现在正确位置的sao)

                <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)并将角色策略Power User附加到Elastic Beanstalk角色用户

    部署您的应用程序

1 个答案:

答案 0 :(得分:4)

实现这一目标有多种方法。您不需要ssh到实例并复制文件。

我会在“更新3”中推荐这种方法。

您可以配置Elastic Beanstalk环境以在部署应用程序之前执行命令。您可以使用ebextensions执行此操作。阅读有关命令here的文档。

基本上,您在应用来源中创建名为.ebextensions的文件夹。此文件夹可以包含一个或多个扩展名为.config的文件。这些文件按其名称的字典顺序处理。您可以使用ebextensions执行shell命令。例如,您可以执行以下操作:

commands:
  02_download_index: 
    command: aws s3 cp s3://mybucket/test.txt test2.txt

您需要先在EC2实例上安装aws cli。这可以通过类似于上面的命令再次完成。有关如何使用捆绑安装程序安装AWS CLI的说明可用here。您可以运行多个命令。配置文件中的命令将按字典顺序执行,因此您可以命名01_install_awcli02_download_index等命令。

现在,如果您计划在EC2实例上使用AWS CLI,您还需要凭据。如果您正在使用IAM实例配置文件(很可能是您,如果没有阅读它here)。您可以使用IAM为实例配置文件授予访问S3对象的权限。这样,您的实例将具有与之关联的IAM实例配置文件,并且能够从S3下载该文件。或者,您也可以使用环境属性直接获取ACCESS_KEY_ID和SECRET_KEY,如here所示。

出现的所有新实例都应该执行ebextensions中的命令。因此,您的实例可以使用您想要的软件进行预配置。