Amazon S3に置いた画像ファイルがTwitter, Facebook, Chatwork, Slack, Discordでどう展開されるか …

AWS利用料業界最安値に挑戦します! …. 【求人】AWSソリューションアーキテクト(AWSシステム環境 コンサル・構築・運用支援). 2015年07月01日; 求人情報. 続きを読む

Amazon CloudSearch の domain を AWS SDK for PHP で作成する

ゴール

Cloud formation は CloudSearchをサポートしていなさそうなので、AWSのコンソールから行える CloudSearch のドメイン作成と同等のことを AWS SDK for PHP で実現します。

環境

実行環境

  • AWS SDK for php version 2.8.31
  • php 7.0.21
  • PHPはEC2で実行しました。EC2には CloudSearchFullAccess を付与したIAMロールが設定してあります。

composer.json

composer.json
    "require": {
        "aws/aws-sdk-php": "2.*"
    }

CloudSeachのドメインを作成する PHPスクリプト

繰り返して実行すると、設定が更新されます。「既に存在するのでダメ」なエラーは発生しませんでした。

<?php

require_once 'vendor/autoload.php';

use AwsCloudSearchCloudSearchClient;
use AwsCommonEnumRegion;


const DOMAIN_NAME = '[作成するドメイン名]';

$client = CloudSearchClient::factory([
    'profile' => 'cloudsearch',
    'region'  => Region::US_WEST_2  // Oregon
]);

// ドメイン作成
$doamin = $client->createDomain(['DomainName'=>DOMAIN_NAME]);
// var_dump($doamin);

// Scaling Options でインスタンスサイズを設定
$client->UpdateScalingParameters([
    'DomainName'=>DOMAIN_NAME,
    'ScalingParameters' => [
        'DesiredInstanceType' => 'search.m1.small',
        'DesiredReplicationCount' => 1,
        // 'DesiredPartitionCount' => 1, // only search.m3.2xlarge
    ]
]);

// Availability Options でマルチAZ を無効 に設定
$client->UpdateAvailabilityOptions([
    'DomainName'=>DOMAIN_NAME,
    'MultiAZ' => false
]);

// Access Policies で指定したIPアドレスからのアクセスを許可
$client->UpdateServiceAccessPolicies([
    'DomainName'=>DOMAIN_NAME,
    'AccessPolicies' => accessPolicy(),
]);

// フィールドの設定
foreach( defineFields() as $name => $f )
{
    $f['IndexFieldName'] = $name;
    $client->defineIndexField([
        'DomainName' => DOMAIN_NAME,
        'IndexField' => $f,
    ]);
}

$indexFiled = $client->indexDocuments(['DomainName' => DOMAIN_NAME]);
// var_dump(indexFiled);

/**
 * アクセス ポリシー
 */ 
function accessPolicy()
{
    $policy = <<<EOM
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "cloudsearch:*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": "[接続を許可するIPアドレス]"
        }
      }
    }
  ]
}
EOM;
    return $policy;
}

/**
 * フィールドの定義
 */
function defineFields()
{
    // AnalysisScheme
    // http://docs.aws.amazon.com/ja_jp/cloudsearch/latest/developerguide/text-processing.html
    return [
        'tweet_id' => [
            'IndexFieldType'=> 'literal',
            'LiteralOptions' => [
                'SearchEnabled' => true,
                'FacetEnabled' => false,
                'ReturnEnabled' => true,
                'SortEnabled' => true,
            ],
         ],
         'tweet_url' => [
            'IndexFieldType'=> 'text',
            'TextOptions' => [
                'AnalysisScheme' => '_en_default_',
                'ReturnEnabled' => true,
                'SortEnabled' => false,
                'HighlightEnabled' => false,
            ],
         ],
         'user_id' => [
            'IndexFieldType'=> 'text',
            'TextOptions' => [
                'SearchEnabled' => true,
                'FacetEnabled' => false,
                'ReturnEnabled' => true,
                'SortEnabled' => true,
            ],
         ],
         'user_screen_name' => [
            'IndexFieldType'=> 'text',
            'TextOptions' => [
                'AnalysisScheme' => '_en_default_',
                'ReturnEnabled' => true,
                'SortEnabled' => true,
                'HighlightEnabled' => false,
            ],
         ],
         'created_at' => [
            'IndexFieldType'=> 'date',
            'DateOptions' => [
                'FacetEnabled' => true,
                'ReturnEnabled' => true,
                'SearchEnabled' => true,
                'SortEnabled' => true,
            ],
         ],
         'text' =>[
            'IndexFieldType'=> 'text',
            'TextOptions' => [
                'AnalysisScheme' => '_ja_default_',
                'ReturnEnabled' => true,
                'SortEnabled' => true,
                'HighlightEnabled' => true,
            ],
         ],
         'retweet_count' => [
            'IndexFieldType'=> 'int',
            'IntOptions' => [
                'SearchEnabled' => true,
                'FacetEnabled' => true ,
                'ReturnEnabled' => true,
                'SortEnabled' => true,
            ],
         ],
         'retweeted' => [
            'IndexFieldType'=> 'literal',
            'LiteralOptions' => [
                'SearchEnabled' => true,
                'FacetEnabled' => false,
                'ReturnEnabled' => true,
                'SortEnabled' => true,
            ],
         ],
         'hash_tags' => [
            'IndexFieldType'=> 'text-array',
            'TextArrayOptions' => [
                'SearchEnabled' => true,
                'AnalysisScheme' => '_ja_default_',
                'HighlightEnabled' => true,
                'ReturnEnabled' => true,
            ],
         ],
         "hash_tags_facet" => [
            'IndexFieldType'=> 'literal-array',
            'LiteralArrayOptions' => [
                'FacetEnabled' => true,
                'ReturnEnabled' => false,
                'SourceFields' => 'hash_tags',
            ],
         ],
         'urls' => [
            'IndexFieldType'=> 'text-array',
            'TextArrayOptions' => [
                'SearchEnabled' => true,
                'AnalysisScheme' => '_ja_default_',
                'HighlightEnabled' => true,
                'ReturnEnabled' => true,
            ],
         ],
    ];
}

実行後の Indexing Options の画面キャプチャ
スクリーンショット 2017-11-12 11.53.27.png

TwitterのAPIでツイートを取得して、主に ツイートのメッセージとハッシュタグで検索します。

メモ

インスタンス・タイプ

今回はデータ量が少ないので、明示的に search.m1.small にしています。

インスタンス・タイプを決めるにあたり、参考になる情報がドキュメントにあります。

一括アップロードを実行するには、以下に従います。

・バッチのサイズを制限の 5 MB にできるだけ近付けてください。小さなバッチを大量にアップロードすると、アップロードとインデックス作成の処理速度が低下します。
・必要なインスタンスタイプを、デフォルトの search.m1.small より大きなインスタンスタイプに設定します。使用できるアップロードスレッドの数は、ドメインで使っている検索インスタンスのタイプ、データの性質、インデックス作成オプションによって異なります。インスタンスタイプが大きいほど、アップロード容量が大きくなります。search.m1.small インスタンスにバッチを並列アップロードしようとすると、通常は、高い確率で 504 または 507 エラーが発生します。必要なインスタンスタイプの設定の詳細については、「スケーリングオプションの設定」を参照してください。

〜 省略 〜

データが 1 GB 未満のデータセットまたは 1,000,001 KB 未満のドキュメントの場合は、スモール検索インスタンスで十分です。1~8 GB のデータセットをアップロードするには、アップロードする前に、必要なインスタンスタイプを search.m3.large に設定することをお勧めします。8~16 GB のデータセットは、search.m3.xlarge で始まります。16~32 GB のデータセットは、search.m3.2xlarge で始まります。アップロードのサイズが 32 GB を超える場合は、インスタンスタイプに search.m3.2xlarge を選択し、データセットに対応できるように、望ましいパーティション数を増やします。各パーティションに最大 32 GB のデータを格納できます。さらに多くのアップロード容量が必要な場合、または 500 GB を超えるインデックスを作成する場合は、Service Increase Limit Request を送信します。

http://docs.aws.amazon.com/ja_jp/cloudsearch/latest/developerguide/uploading-data.html#bulk-uploads

TextField の AnalysisScheme

管理コンソールから操作する時にプルダウンで表示される言語別のテキスト処理の一覧です。
http://docs.aws.amazon.com/ja_jp/cloudsearch/latest/developerguide/text-processing.html

目的の言語の デフォルトの分析スキーム を AnalysisScheme に指定します。日本語は _ja_default_ 、英語は_en_default_ です。

日本語(ja)
アルゴリズム語幹解釈オプション: full
アルゴリズム複混合が有効
オプションのトークン分割ディクショナリ
デフォルトの分析スキーム: __ja_default__
・アルゴリズム語幹解釈: full
・デフォルトのストップワードディクショナリ

続きを読む

Serverless Tech Challengeに参加した

完全に個人の参加報告&感想となります。

Serverless Tech Challengeとは

サーバレス界隈としては国内最大級のイベントとなる Serverlessconf Tokyo 2017 の1日目に行われたワークショップの内のひとつです。
このワークショップでは参加者同士で1~3名のチームを割り振られ、そのメンバーで協力して出された課題に取り組むワークショップとなっています。

http://tokyo.serverlessconf.io/workshops.html

課題内容

ルール

  • 制限時間は17:00まで(開始は10:30ぐらい)
  • 原則としてAWSサービスのみで構築すること
  • 出された4テーマから1つ選んで構築すること
  • 下記の要素を必ず含むと
    • 認証機能(サインアップ/サインイン)
    • GUI(デザインは問いません)
    • 画像ファイルの取扱が可能(添付、共有など)

成果物として求められるもの

  • アーキテクチャ図
  • デモ
  • プレゼンテーション資料(工夫した点など)

表彰

  • AWS のソリューションアーキテクト(7名が当日来ていました)が独断でイケていると思ったチームを1チーム選出
  • 選出の観点は以下
    • アーキテクチャ
    • ライフサイクル管理(ロギング、モニタリング、CI/CD)
    • コスト
    • 耐障害性
  • 賞品は10万円分のAmazonギフトカード(チームに進呈)

選択するテーマ

下記から1つ選択して実装する
– 電子掲示板 (いわゆる電子掲示板、StackOverflowなどのスレッドがあるものをイメージ)
– SNS(Twitter、Facebook等のSNS)
– マッチングアプリ
– Chat(Slack等のチャットアプリ)

私のチーム

チームメンバー&選択テーマ

私は全13チームの中で#12のチームとして、2名1チームの1人として取り組みました。
#12のもうひと方は、インフラエンジニアの方で、普段はオンプレミスからAWSへの
移行作業を順次行っているメンバーとのことでした。
役割分担として相方にフロントエンドの構築(HTML/JavaScript/CSSは書けるとのこと)、私がバックエンドの
構築(API設計/DB設計/サーバサイドコード(Lambda)/CI&CDパイプライン/サーバサイドリソースのデプロイ)といった
役割分担をして進めました。

選択したテーマは「Chat」です。
短時間で構築するためには一番想像がしやすく、比較的現実的な感じがしたという理由です。
とはいえ、賞味7時間(昼休憩もその中で)でこれを作り上げるのはかなり過酷です。

構築の進め方

下記のような流れで進めていきました。
ポイントとしては、時間がかなり限られた中で取り組むため、
出来る限りインクリメンタルにアジャイル開発的に進めていこうというものです。

  1. 私のアカウントにIAMユーザを追加
  2. Cognito User Pool&Cognito Identity Pool(仮)をAWSコンソールから作成
  3. Webページ配置用S3バケット(仮)をAWSコンソールから作成
  4. フロントエンドからユーザ登録・認証フローを構築する
  5. CI/CDパイプラインを構築
  6. Cognito User Pool & Cognito Identity PoolをCloudFormationテンプレートで記述しCI/CDパイプラインに乗せてデプロイ
  7. 6で作成したCognitoに向け直す
  8. SwaggerにてAPI設計を行い、APIのデプロイを行う(もちろんCI/CDにて)
  9. モックを応答するLambdaをデプロイ
  10. メッセージ表示、投稿用のDynamoDBのデプロイとDynamoDBとのインテグレーションをするLambdaに修正
  11. APIを使ってチャット画面を表示、投稿する機能を構築
  12. 画像保存用S3バケットのデプロイ
  13. APIを画像投稿に対応するよう修正しLambdaも修正
  14. 画像投稿をできるようにUIを修正

ここまででタイムアップ
ちなみに、まだ時間があれば進めようとしていた流れは下記の通り、

  1. メッセージ画面に画像表示
  2. ルーム一覧を取得するためのAPIを追加
  3. ルーム作成APIを追加
  4. ルーム一覧を表示する
  5. ルーム作成画面を追加
  6. ルームに参加可能なユーザの制限等を行う

などです。

プレゼンテーション

プレゼンテーションは各チーム3分間で行います。
プレゼンテーション中は公正を期すために全員クローズドデスクトップとして発表を聞くこと
私のチームは所々の関係上最後の発表となりました。

発表時に使用した資料は下記
http://k1nakayama-docs.s3.amazonaws.com/ChatApp12.pdf

画像の投稿機能を実装中にタイムアップとなってしまったため、投稿機能自体がうまく動かないままとなってしまいました。

結果発表

各チームのプレゼンテーションが終了し、20分間の休憩の間にAWSのSAによる審査が行われました。
その後、結果発表です。

なんと画面には #12 と表示され私達のチームの優勝が決まりました!
これはめちゃくちゃ嬉しかったです。

優勝賞品としてチームに10万円分のAmazonギフト券が渡され、2人のチームだったので、
仲良く5万円分ずつ分けました。
IMG_0618.jpg

評価としては、

  • アーキテクチャとしては至ってオーソドックスではある
  • 課題として出された条件を全て網羅している
  • 完成度が平均的によい
  • 全チームの中で唯一DynamoDBオートスケーリングなどを取り入れており、キャパシティマネジメントなどの点も考慮されている
  • SAによる評価の全会一致で選出された

ということでした。

感想&印象に残ったもの

今回のワークショップは、AWSではたまに見かけるGame Dayと似たような取り組みでしたが、
Game Dayも参加したことなかったため、とっても新鮮でした。
そして、普段からサーバレスに触れているものの、色々な発見がありとても参加した甲斐があったと思います。
(賞味7時間で死に物狂いで取り組めば、一応これぐらいはできるのかという気づきにもなりました(^_^;))

まず、すごく気付かされたものは、チームワークというか、構成メンバーって本当に大事で、
今回の場合、私のチームは2人だったものの、ほぼほぼ経験の多い分野が分かれていたのもあり、
それぞれが取り組むべきところを自分で考えて取り組むことも出来たので、時間短縮に繋がったと思います。
また、この手の開発はやはりとにかく小さな目標を積み重ね、インクリメンタルに成果を積み上げていくことが良いということも再確認出来ました。

他のチームのアーキテクチャとして印象に残ったものは、
同じチャットアプリに取り組んでいたチームが、
メッセージ投稿のアーキテクチャについてAPI Gatewayを使わず、
JavaScript(フロントエンド)→ SNS → Lambda → S3
というものをベースに作っていました。
ある意味一昔前のアーキテクチャだと思いますが、ユニークな発想でこういう発想も普段から持っておくと
柔軟に取り組めるかもなぁと思いました。

その他、マッチングアプリのチームは、ほぼ必須でAmazon Rekognitionを使用して画像の中の写真に対する
プロパティによるマッチングを考えていました。
世の中本当にAIの時代だなぁと考えさせられました。
このあたりのAI系サービスはあまり知見が少ないので、今後はこのようなサービスも積極的に使っていきたいなぁと思います。

続きを読む

AWS GreengrassでLチカ:クラウドとエッジについて考える(1)

できたもの

LED blink by AWS Greengrass controll pic.twitter.com/sdBzLaifdf

— nobu_e753 (@nobu_e753) 2017年10月7日

  • AWS Greengrassのコンソール上からLambda関数をRasPi3へデプロイすると,RasPi3につないであるLEDが点滅する(5秒毎に赤→緑→赤…)
  • その後,RasPi3のネットワークを切断してもLEDは既定のパターンで点滅し続ける

はじめに

先日,JAWS-UG主催のAWS Greengrassハンズオンに参加したのですが,機材トラブルや難度の問題もあり,半端な状態で終わってしまいました.あまり理解できず終わってしまったことが悔しかったので,自宅にて自分なりの課題を立て進めてみることにしました.本記事はそのまとめです.

※「自分なりに理解すること」を優先したので,公式のやり方に沿わないもしくは語弊がある部分もあるかもしれません

下準備

機材は以下で進めました.こちらにGreengrassに対応している機材一覧があります.

  • RaspberryPi 3
  • PC

またとりくみ前に以下のチュートリアルを実施しました.内容そのものの理解というより”なんとなくオペレーションを理解しておく”ためです.

言語はPythonですすめました.あと,あえて述べておくと私のAWSに関する知識は「EC2やDynamoDBを仕事でつかうものの利用は基本的な範囲にとどまる」レベルです.

とりくみ内容

AWSを利用して以下のような「ネットワーク型信号機」を設計する,ことをお題にしました(実際は信号機にみたてたRasPi3+LEDを制御・点灯させます).

problem.png

この課題に取り組むにあたり

  1. AWS IoT にて実現(クラウドの考え方)
  2. AWS Greengrass にて実現(エッジの考え方)

の双方を試すことにより,それらの違い,そしてクラウドとエッジの考え方を感覚的に理解することを目標にしました.本記事では1つめ,続編で2つめに取り組みます.

1. AWS IoTにてネットワーク型信号機を実現する

まずは構成検討です.できるだけ単純なモデルにするため以下にしました.

p1.png

  • 制御はAWS側から相当するMQTTメッセージを送信
  • RasPi3側でメッセージを受信,信号機に見立てたLEDを制御(赤/緑の2色)

赤/緑だけの2色信号機をネットワーク経由で制御します(最初に「赤を点灯」に相当するメッセージを発信,60秒後に「緑を点灯」に相当するメッセージを発信…).信号の切り替え間隔を変える場合も,サーバー(AWS)側の制御プログラムを変更するだけで済みます.なんかクラウドっぽいです…
早速作成してみます.

信号機側S/W

  • MQTTメッセージを受信
  • メッセージに合わせGPIO経由でLED制御

機能としてはこれだけです.コードは以下としました.AWS IoTのサンプルに毛の生えた程度です.各種アドレスやファイルパスはすべて埋め込みとしました.AWS IoTに接続するための証明書はあらかじめ作成し,./certs/ フォルダ以下に格納しておくものとします.
GPIO経由でLEDを点灯させることについてはこちらの記事などが参考になります.

led_brink_iot.py
# -*- coding: utf-8 -*-
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
import RPi.GPIO as GPIO
import time
import json

# gpio pins
LED_R = 14
LED_G = 15
LEVEL = [GPIO.LOW, GPIO.HIGH]

# host
host = "xxxxxxxxxxxxxx.iot.ap-northeast-1.amazonaws.com"
port = 8883

# certs
rootca_path = "./certs/root-ca.pem"
certificate_path = "./certs/thing-certificate.pem.crt"
privatekey_path = "./certs/thing-private.pem.key"
thing_name = "RasPi3"

def onMessage(message):    # メッセージを受け取った際に呼ばれる
    payload = json.loads(message.payload.decode('utf-8'))
    print(" > Message : {}".format(payload))
    print("--------------n")   

    try:    # GPIOの制御
        red_lv = int(payload['red'])    
        green_lv = int(payload['green'])
        GPIO.output(LED_R, LEVEL[red_lv])
        GPIO.output(LED_G, LEVEL[green_lv])
    except:
        print(" ! Invalid message")     

if __name__ == "__main__":

    # gpio setup
    GPIO.setwarnings(False) 
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(LED_R, GPIO.OUT)
    GPIO.setup(LED_G, GPIO.OUT)

    # mqtt setup
    mqtt_client = AWSIoTMQTTClient(thing_name)
    mqtt_client.configureEndpoint(host,port)    # MQTTクライアントの接続先を上で指定したhost/portにする
    mqtt_client.configureCredentials(rootca_path, privatekey_path, certificate_path)

    mqtt_client.configureOfflinePublishQueueing(0)
    mqtt_client.configureDrainingFrequency(2)
    mqtt_client.configureConnectDisconnectTimeout(120)
    mqtt_client.configureMQTTOperationTimeout(5)

    # Register an onMessage callback
    mqtt_client.onMessage = onMessage    # メッセージを受信したときのコールバック関数設定

    # start subscribe
    mqtt_client.connect()    # 接続
    time.sleep(2)
    print(" * Connection successful")   

    mqtt_client.subscribe("io/led", 1, None)
    print(" * Start subscribe..")

    while True:
        time.sleep(3)    # 無限ループでメッセージ受信を待つ

サーバー側からのメッセージは以下のMQTTトピック&JSON形式としました.0なら消灯,1なら点灯です.

# MQTT topic
io/led
# Message format
{
    "red":0,
    "green":1
}

信号機側H/W

GPIO-LED間の接続は以下としました(抵抗には手元にあった330Ωを使用).

20170929_krs_qiita.png

動かしてみる

まずはRasPi3側のプログラムを動かします.

pi@raspi3-nobu_e753:~/Workspace/aws $ ls
certs/  led_blink_awsgg.py  led_blink_awsiot.py
pi@raspi3-nobu_e753:~/Workspace/aws $ python3 led_blink_awsiot.py 
 * connection success
 * start subscribing...    # AWS側からメッセージを発行すると以下が出力される
 > Message : {'green': 0, 'red': 1}
--------------

 > Message : {'green': 1, 'red': 0}
--------------

 > Message : {'green': 0, 'red': 1}
--------------

待ち受け状態になったらAWS IoTのコンソールからMQTTメッセージを発行してみます.

aws01s.png

aws02.png

メッセージを発行すると,コンソールにその内容が表示されると当時にRasPi3に接続されているLEDの点灯状況が変わるはずです.このメッセージを発行手順を,手動ではなく,AWS Lambdaで記述し,これを定期実行するようにすれば,「サーバーからのメッセージによって切り替えを行うクラウドタイプ信号機」が実現できます(AWS Lambdaによる定期発行のコードは省略します).

クラウドタイプ信号機の問題点

さて,もし世の中の信号機が上記の構成で実現されていたらかなり危ないことに気づくと思います.

1. ネットワークが切れたら終わり
まずこれです.信号機の制御はサーバーから送信されにはてくるメッセージによっているので,ネットワークが切れた瞬間に制御できなくなります.事故が多発するに違いありません.

2. 通信費がバカにならない
日本にある信号機は全部で約20万基だそうです(ちなみに,コンビニ5万件,歯医者7万件,美容院23万件!だそうです).これらをすべて制御する場合,一体どれだけの費用がかかるか想像もしたくありません.

どうやらこの構成だと問題が大きそうです

ではどうしたら?

上記問題を解決するには

  • 信号機側である程度自立して動くようにする
  • ただしネットワークを通じて制御内容をアップデートできるようにする

としたいです.すると信号機側にアップデーを受け入れる機構や,新設定にしたがって動き出す機構,アップデートが失敗した場合の手当てを行う機構などなど,本題ではないところでいろいろと面倒なことが発生します.

ううむ面倒だ,誰かやってもらえないだろうか…

→ AWS Greengrassに面倒をみてもらおう!(という意図のサービスだと私は理解しました

記事2に続きます.

続きを読む

[AWS] Basic認証を設定する

概要

AWSにBasic認証を設定する方法です。

ターミナルでアクセスする

キーペアとipアドレスを適時変更し、ターミナルからアクセスします。

ssh -i ~/.ssh/{キーペア.pem} ec2-user@{IP アドレス}

httpd.confを編集する

ターミナルから下記コマンドを入力しhttpd.confを表示します。

sudo vi /etc/httpd/conf/httpd.conf

aを押して編集モードにしたら

下記をコメントアウトして

# AllowOverride None

下記を追記します(.htaccessを有効にするため)

AllowOverride All

追記が終わったら「control+[」で編集モードを終了し「:w」で保存、「:q!」で終了します。

htmlに.htaccessと.htpasswdを設定する

.htaccess

<Files ~ "^.(htaccess|htpasswd)$">
deny from all
</Files>
AuthUserFile /var/www/html/.htpasswd
AuthGroupFile /dev/null
AuthName "Please enter your ID and password"
AuthType Basic
require valid-user 
order deny,allow

.htpasswd

id:pass

下記のサイトで暗号化ができます。
http://www.htaccesseditor.com/#a_basic

以上です。

おそらく役立つ情報

痒いところに手が届くかもしれない記事を書いています。
フォローしてくれるとやる気になります!

続きを読む

[AWS] ドキュメントルートを変更する

概要

AWSのEC2でドキュメントルートを変更する方法です。

変更ファイル

EC2では下記のファイルに指定が入っています。

/etc/httpd/conf/httpd.conf

変更方法

EC2にログインした状態で下記のコマンドを実行します。

$ sudo vi /etc/httpd/conf/httpd.conf

vimモードに変更し、ファイルを290行目付近の記述を下記のように変更します。

変更前

DocumentRoot "/var/www/html"

変更後

DocumentRoot "/var/www/html/app/webroot"

変なファイルが生成された時は

下記のコマンドで削除します。

$ sudo rm /etc/httpd/confd/httpd.conf.swp

最後

Apacheを再起動すれば反映されます。

おそらく役立つ情報

痒いところに手が届くかもしれない記事を書いています。
フォローしてくれるとやる気になります!

続きを読む

aws RDSのm3 m4 r2全インスタンスでスペック比較した

さくらVPSでDBを立てていたんだけど、どうも重い。AWSへの乗り換えの検討の為色々比較してみた。

select文をEXPLAIN ANALYZEしただけという前提はあるが、$5/hのdb.m4.10xlargeと$0.1/hのdb.t2.mediumが5%しか違わないのがへっ?となった。
ソートはBのAVG。t2.midiumが4069でm4.10xlargeが3955。オリジナルのExcelファイルはこちら https://github.com/fushihara/aws-rds-cost

image.png

ただt2もmidiumとlargeは早いけどsmallとmicroになると4倍の時間がかかってるから、クエリがメモリに入り切らなくなった?ら急に重くなる可能性がかなりあるのかもしれない。そうなるとm4の一番少ないlargeがベストかもしれない。しかし月2万円。DBはお高い。

以下、比較条件

image.png

以下のクエリを10回投げて、かかった時間をソート。一番多い値と少ない値を一つづつ取り除いて8個の最大値・最小値・平均を取った。クエリAとBがあるけど、上記の図のBというのはクエリBの事。こっちの方が重いのでそっちの値を図に出した。

クエリA
select * 
from home_timeline_tweet_ids left join tweet on home_timeline_tweet_ids.tweet_id = tweet.tweet_id 
where home_timeline_tweet_ids.user_id = 123456 order by home_timeline_tweet_ids.tweet_id desc limit 100

クエリB
select to_char(tweet.created_at, 'yyyy/mm/dd') as time , count(*) as cnt from home_timeline_tweet_ids
left join tweet on home_timeline_tweet_ids.tweet_id = tweet.tweet_id 
where home_timeline_tweet_ids.user_id = 123456 and 
tweet.text ~ 'テスト' 
group by to_char(tweet.created_at, 'yyyy/mm/dd')
 order by to_char(tweet.created_at, 'yyyy/mm/dd') desc limit 100

こうやって10回測定 from linux
export Q="select ほにゃらら"
i=1; while [ $i -le 10 ]; do psql -d twitter -h xxxxx.ap-northeast-1.rds.amazonaws.com  -U twitter -c "EXPLAIN ANALYZE ${Q}" | grep  "Execution time" ; i=$(expr $i + 1);done



測定時間の結果をchromeのdevtoolのコンソールで計算
a=`[user@fushihara.io ~]$i=1; while [ $i -le 10 ]; do psql -d twitter -h twitter-r3-2xlarge.czpa3unkkrto.ap-northeast-1.rds.amazonaws.com -U twitter -c "EXPLAIN ANALYZE ${Q}" | grep  "Execution time" ; i=$(expr $i + 1);done
 Execution time: 4312.636 ms
 Execution time: 4314.856 ms
 Execution time: 4339.720 ms
 Execution time: 4319.702 ms
 Execution time: 4301.736 ms
 Execution time: 4306.114 ms
 Execution time: 4312.707 ms
 Execution time: 4317.436 ms
 Execution time: 4306.224 ms
 Execution time: 4307.491 ms`;//例
b = a.split("n").
    map((i)=>i.trim()).
    map(i=>i.match(/time: ([0-9.]+) ms/)[1]-0).
    sort().slice(1, 9);
console.log(`MAX=${b[0]} MIN=${b[7]} AVG=${b.reduce((a,b)=>{return a+b})/8}`);

さくらvpsの使ってるプランはこちら。メモリ8GB、HDD 800GBモデル。この1台をDB専用にしてる訳ではなく、他にもnginxとか入ってるけど参考までに。

image.png

VPSが月8000円とすると、t2.midium相当。それでも自鯖だと6100ポイントが4000ポイント。自鯖がDB専用じゃない事を考えると、AWSにはもっと頑張って欲しい所だけどどうしよう…

続きを読む