2017年9月23日土曜日

python3インストール(pyenvは使わない)

以前書いた記事ではpyenvを使用してPython3をインストールしました。
Pythonインストール

後日、下記の記事を拝見し、
確かにpyenvいらないかもと思ったので、別のインストール方法をメモしておこうと思います。
pyenvが必要かどうかフローチャート

# python3のインストール
$ mkdir ~/DL
$ cd ~/DL
$ wget https://www.python.org/ftp/python/3.6.2/Python-3.6.2.tgz
$ sudo tar -zxvf Python-3.6.2.tgz -C /usr/local/src/
$ cd /usr/local/src/Python-3.6.2/
$ ./configure
$ make
$ sudo make install

# python3がインストールされていることを確認
$ python3 -V
Python 3.6.2

#現在のpythonコマンドを確認
$ python -V
Python 2.7.5
$ which python
/usr/bin/python
$ ls -l /usr/bin/python
lrwxrwxrwx. 1 root root 7 Aug  1 22:19 /usr/bin/python -> python2

# pythonコマンドをpython2からpython3にする
$ which python3
/usr/local/bin/python3
$ ln -si /usr/local/bin/python3 /usr/bin/python

# 変更後のpythonコマンドの確認
$ python -V
Python 3.6.2
※既存の機能で使用している可能性があるため、pythonコマンドのリンク先は変更しないほうが良いようです。

以上です。

2017年9月12日火曜日

JavaによるAWS S3へのファイルアップロード注意点

S3へファイルをアップロード(TransferManagerを使用)するコードを書く機会がありました。その際に困った点について共有したいと思います。
実際はコードを書いている際に困ったわけではなく、運用している際に困った話です。
(つまりテストなどで逃しやすい)
さっそく結論から
1.TransferManagerは必ずtransferManager.shutdownNow()でシャットダウンする。
2.amazonS3Client.getCachedResponseMetadata()でS3ResponseMetadataを取得しログに出力しておく。
3.マルチパートアップロードされないように閾値を変更しておく。(アップロードサイズとの兼ね合い)
コード例
private void fileUploadToS3(String s3UploadFilePath, MultipartFile multipartFile) throws Exception {
    String s3BucketName = "test_bucket";

    AmazonS3Client amazonS3Client = new AmazonS3Client();
    PutObjectRequest putObjectRequest = null;
    try (
        InputStream multipartFileInStream = multipartFile.getInputStream()) {

        TransferManager transferManager = new TransferManager(amazonS3Client);
        TransferManagerConfiguration config = new TransferManagerConfiguration();

        // ResponseMetadataを取得するために閾値変更
        Long multipartUploadThreshold = 50L * 1000L * 1000L
        transferManagerConfiguration.setMultipartUploadThreshold(multipartUploadThreshold);
        transferManager.setConfiguration(transferManagerConfiguration);

        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentLength(multipartFile.getSize());

        putObjectRequest = new PutObjectRequest(s3BucketName, s3UploadFilePath, multipartFileInStream, objectMetadata);
        Upload upload = transferManager.upload(putObjectRequest);
        upload.waitForUploadResult();

    } finally {
        S3ResponseMetadata s3ResponseMetadata = amazonS3Client.getCachedResponseMetadata(putObjectRequest);
        if (s3ResponseMetadata != null) {
            // AWSサポートへの問い合わせに使用する。(SLF4Jとか使ってオブジェクトごと出したほうがいいかも)
            System.out.println("RequestId : "+ s3ResponseMetadata.getRequestId() + ", HostId : " + s3ResponseMetadata.getHostId());
        } else {
            System.out.println("ResponseMetadata :null");
        }
        // シャットダウンしないとExceptionの素
        transferManager.shutdownNow(false);
    }
}
簡単にですが説明
1.について
シャットダウンしない場合、アップロードが頻繁に起きた際にException発生の原因になる。ドキュメントの例をよく見るとこっそり必ず入ってました。
2.について
S3アップロードの失敗など、調査でAWSサポートへ問い合わせる場合に必要になる。
3.について
閾値を超えてマルチパートアップロードになった場合2.で取得予定のS3ResponseMetadataが取得できません。
TransferManagerでのアップロードではアップロードファイルサイズによって単体アップロードかマルチパートアップロードかを切り替えているため、必ず取得したい場合、閾値を上げる必要があります。(デフォルト16MB)
ただし、サイズが大きい場合マルチパートアップロードの恩恵を受けるために致し方なし?
今気づきましたが、S3ResponseMetadata、ResponseMetadataのドキュメントにAWSサポートで使用するっぽいことって書いてますね。
Returns the Amazon S3 host ID, providing additional debugging information about how a request was handled.
Returns the AWS request ID contained in this response metadata object. AWS request IDs can be used in the event a service call isn't working as expected and you need to work with AWS support to debug an issue.

余談:Qiita投稿用に書いてたものをコピペしたら、Qiitaでの書式がそのままコピーされた。