t-sanoブログ

メモです。マイペースにアウトプットします。

転職ドラフトの体験談

※こちらの記事は転職ドラフト体験談投稿キャンペーンに参加しています。

job-draft.jp

自己紹介

これまで直近5年間はフリーランスのエンジニアとして、様々な業界のクライアント様の開発業務を支援してきました。

転職ドラフトに登録したきっかけ

単純に転職ドラフトというサービスが面白そうなのでやってみようというのが最初のきっかけです。

どんな指名を受けてどのように受け止めたか

基本的にはテックリードのポジションで指名を受けることが多かったです。その時点でどう受け止めたとかは特になく、ワクワクするような指名には一旦話を聞きに行ってみようというスタンスで取り組んでいました。

面談や面接へどんな期待をしてどのように臨んだか

ワクワクするような話を聞けたらいいな〜という期待が強かったです。実際にオファーを受けると決めた企業もワクワク度が強い企業に決めました。

参加前の予想と異なったことや印象的だったこと

参加前の予想と異なったことは、自分が思っている以上に自分が希望する年収以上の指名が来ることです。また、自分が希望する開発言語よりも自分が長年使ってきた開発言語の経験からご指名をいただくことが多かったことです。この対策として、自分が希望する開発言語や開発環境を明記するようにしたところ、希望に沿った指名が多くを占めるようになりました。 印象的だったことは指名期間の終了日に近づくほど、多くの会社から一気に指名が来ることです。ドラフト指名期間の前半は指名数が少なく、企業からレジュメを見られる頻度が高い期間になっていました。

転職ドラフトへの改善要望

以下のような機能があればいいなと感じました。 入社前に企業と求職者間での体験期間として業務委託期間を用意し、期間中は業務委託として、指名した際に提示されている業務委託金額で契約する。 上記期間で双方問題なければ、指名した際に提示した年収額で正社員として契約する。

これから参加する方へのメッセージ

まずは参加してみて、自分の経歴と強みを整理するだけでも価値があると思います。 以下、私の友達紹介コードです。よければ使ってください。

「DGGA」

転職ドラフトに参加するための審査に通過すると、以下のプレゼントが貰えるみたいです。

  • お好きなO’REILLY JAPANの本(税抜5000円以内)を1冊
  • 転職ドラフトオリジナル ドラフトビール 6本入り
  • ACTUSギフトカタログ Straw(ストロー)
  • Amazonギフト券 3000円分

TerraformでECS環境を構築する。

驚くほど簡単にAWSでDocker環境ができてしまいます。 Terraformの基本的な話は割愛します。

設定内容(例)

EC2

ポイントはiam_instance_profileuser_dataです。

resource "aws_instance" "testInstance" {
    ami = "${data.aws_ami.amazon_linux.id}"
    instance_type = "t2.micro"
    key_name = ${var.key_name}
    vpc_security_group_ids = [
      "${aws_security_group.hoge.id}",
      "${aws_security_group.hogehoge.id}"
    ]
    subnet_id = "${aws_subnet.public-c.id}"
    associate_public_ip_address = "true"
    iam_instance_profile = "instance_role"
    root_block_device = {
      volume_type = "gp2"
      volume_size = "8"
    }
    tags {
        Name = "testInstance"
    }
    user_data = "${file("userdata.sh")}"
}

userdata

ECSクラスターと関連付けます。

#!/bin/bash
echo ECS_CLUSTER=hogehoge >> /etc/ecs/ecs.config

ECS

resource "aws_ecs_cluster" "hogehoge" {
  name = "hogehoge"
}

resource "aws_ecs_task_definition" "hogehoge" {
  network_mode = "bridge"
  family = "hogehoge"
  container_definitions = "${file("task-definitions/hogehoge.json")}"
}

resource "aws_ecs_service" "hogehoge" {
  name = "hogehoge"
  cluster = "${aws_ecs_cluster.hogehoge.id}"
  task_definition = "${aws_ecs_task_definition.hogehoge.arn}"
  desired_count = 1
}

container_definitions

[
  {
    "name": "hogehoge",
    "image": "hoge/hogehoge",
    "cpu": 10,
    "memory": 400,
    "essential": true,
    "portMappings": [
        {
            "hostPort": 114514,
            "containerPort": 114514,
            "protocol": "tcp"
        }
    ],
    "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
            "awslogs-group": "hogehoge",
            "awslogs-region": "ap-northeast-1",
            "awslogs-stream-prefix": "hogehoge"
        }
    }
  }
]

IAM role

resource "aws_iam_instance_profile" "instance_role" {
    name = "instance_role"
    roles = ["${aws_iam_role.instance_role.name}"]
}

resource "aws_iam_role" "instance_role" {
    name = "instance_role"
    assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF
}

resource "aws_iam_role_policy" "instance_role_policy" {
    name = "instance_role_policy"
    role = "${aws_iam_role.instance_role.id}"
    policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "ecs:*",
        "logs:CreateLogStream",
        "logs:PutLogEvents",
        "logs:Describe*"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}
EOF
}

CloudWatchLogs

ECSでLogDriverにawslogsを指定した場合、LogGroupを設定している必要がある。

resource "aws_cloudwatch_log_group" "hogehoge" {
  name = "hogehoge"
}

AWSでドメイン、ポートのヘルスチェックをする。

AWSドメインやポートに対するヘルスチェックができます。 下記はサービス停止をいち早く検知するためにドメインヘルスチェックを設定する方法です。

方法

  1. AWSにログインし、Route53メニューを開く。
  2. Route53の利用が初めての場合は「Availability monitoring」の[Get started now]ボタンを押下する。Route53を既に利用している場合は左メニューの「Health checks」メニューを選択し、[Create health check]ボタンを押下する。
  3. 監視したいドメインまたはポートの情報を入力する。 f:id:t-sanox:20170126094921p:plain f:id:t-sanox:20170126094944p:plain
  4. アラームが必要な場合、アラームを設定する。 f:id:t-sanox:20170126095041p:plain
  5. ヘルスチェックが開始される。 f:id:t-sanox:20170126095128p:plain
  6. アラームはバージニアリージョンに作成されている。
  7. 復旧した場合のアラームも受け取りたいので、状態がOKになった場合の通知も追加する。
  8. LambdaとSNSを連携し、アラームをidobataに通知する。(SNSバージニアリージョンなので、Lambdaも同じリージョンにする必要がある。)

オプション説明

String matching(追加料金0.5USD/月)

HTTP および HTTPS のみ利用可能。Amazon Route 53 で、HTTP または HTTPS リクエストをエンドポイントに送信、または指定文字列のレスポンス本文を検索することにより、エンドポイントの状態を判断するかどうか。[Search String] で指定した値がレスポンス本文に含まれる場合、Amazon Route 53 は、そのエンドポイントが正常であると見なします。レスポンス本文に含まれない場合、またはエンドポイントが応答しない場合、Amazon Route 53 は、そのエンドポイントを異常と見なします。検索文字列全体が、レスポンス本文の最初の 5,120 バイト内に出現している必要があります。

Latency graphs(追加料金0.5USD/月)

Amazon Route 53 コンソールの CloudWatch グラフに次の値を表示することができます。

  • Amazon Route 53 ヘルスチェッカーがエンドポイントとの TCP 接続を確立するのにかかる平均時間 (ミリ秒)
  • Amazon Route 53 ヘルスチェッカーが HTTP または HTTPS リクエストへの応答の先頭バイトを受け取るまでにかかった平均時間 (ミリ秒)
  • Amazon Route 53 ヘルスチェッカーが SSL ハンドシェイクを完了するまでにかかる平均時間 (ミリ秒)

Invert health check status

Amazon Route 53 でヘルスチェックのステータスを反転させるかどうかを選択します。このオプションを選択した場合、Amazon Route 53 はステータスが正常であればヘルスチェックに不具合があると見なします。逆も同様です。

参考

ヘルスチェックの作成と更新

AWS CLIでCloudWatchのアラームを制御する

はじめに

サービス運用していく上で、サービスレベルを保つためには監視が必須なわけですが、 監視をどうしても止めなきゃいけないときってありますよね。関係各位に通知が飛んじゃうので。 例えば、サーバメンテナンスでサーバを止めなきゃいけないときとか。

そういったケースにおいて、AWSではどうしたらいいんだろう?と考えました。 CloudWatchってアラームで通知設定してるけど、通知停止とかしてないんですよね・・・私。 ということで、気になって調べてみました。

目的

AWS CLIでCloudWatchのアラームを制御する。

できること

CLIを見ると、下記ができるらしい。 disable-alarm-actionsenable-alarm-actions! 通知止められそうなコマンド発見〜。 set-alarm-stateでアラームのテストもできそうだ。

  • delete-alarms
  • describe-alarm-history
  • describe-alarms
  • describe-alarms-for-metric
  • disable-alarm-actions
  • enable-alarm-actions
  • get-metric-statistics
  • list-metrics
  • put-metric-alarm
  • put-metric-data
  • set-alarm-state

検証

コマンド名を見れば何ができるかだいたいわかるので、アラーム制御できるっぽいコマンドを試してみる。

とりあえず、検証用のメトリクスとアラームを作る。

aws cloudwatch put-metric-data \
    --namespace 'test-metrics' \
    --metric-name 'test-metrics' \
    --unit 'Count' \
    --value '1'

aws cloudwatch put-metric-alarm \
    --alarm-name test-alarm \
    --actions-enabled \
    --alarm-actions arn:aws:sns:ap-northeast-1:ACCOUNT_ID:test-sns \
    --metric-name test-metrics \
    --namespace test-metrics \
    --statistic Sum \
    --period 60 \
    --evaluation-periods 1 \
    --threshold 1 \
    --comparison-operator GreaterThanOrEqualToThreshold

作ったアラームがこちら。 f:id:t-sanox:20161123193058p:plain

アラームのアクションを無効化する。

aws cloudwatch disable-alarm-actions \
    --alarm-name test-alarm

無効にした結果がこちら。 f:id:t-sanox:20161123193039p:plain

下記のコマンドでアラームのアクションを有効化する。

aws cloudwatch enable-alarm-actions \
    --alarm-name test-alarm

まとめ

AWS CLIでCloudWatchアラームの通知を停止、再開できることがわかりました。 このコマンドをJenkinsか何かで利用しやすくしてやれば、メンテナンス時に無駄な通知が飛ぶこともなくなりますね!

参考

AWS CLI Command Reference - CloudWatch

jQueryのDeffered、whenを使いこなして、非同期処理のコールバック地獄から抜け出す

ubw.hatenablog.com

先日、S3に対して署名付きURLを用いて、大容量のファイルを分割してアップロードするということをやりました。 こちらをブラウザから非同期で実施する際に、コールバック処理をうまく制御する方法について、とても勉強になったのでメモします。

やりたいこと

ざっくり言うと、非同期処理で、ブラウザからS3にファイルをマルチパートアップロードすることです。 具体的には、下記のような処理を実現することになります。

  1. APIサーバに署名付きURLの発行リクエスト
  2. (1の処理が完了したら)APIサーバから受け取った署名付きURLに対してマルチパートアップロード
  3. (2の処理が完了したら)APIサーバにマルチパートアップロードの完了リクエスト

補足すると、上記、1と3は1回の非同期処理、2については複数回の非同期処理になる。 2では、並列にファイルをアップロードし、アップロード処理を素早く完了させたい。

jQuery.Defferedで処理の完了結果を通知する

1の処理が完了 -> 2の処理実行という流れを作るため、下記のようにDefferedを利用した。 簡単に言うと、関数内でDefferedのpromiseを返し、非同期処理が完了後、結果(成功だったらresolve、失敗だったらreject)をpromiseに返す。 Defferedの使い方について書こうと思ったのですが、本記事の一番下に記載している参考リンクをご覧になったほうが、 かなり参考になるため、ここで記載するのはやめておきます。

function hoge(){
  dfd = $.Deferred()

  $.get(requestUrl, requestParam
  ).done(function(data){
    dfd.resolve data
  }).fail(function(){
    dfd.reject
    alert '処理に失敗しました。'
  })

  return dfd.promise()
}
hoge().then(function(data){
  console:log('非同期処理の結果:');
  console.log(data);
})

whenを利用し、非同期処理を並列連結し、完了結果を通知する

2の処理が完了(並列実行) -> 3の処理実行という流れを作るため、下記のようにwhenを利用した。 whenを利用すると、複数のpromiseをまとめて、新しいpromiseを返してくれます。 これにより、すべてのpromiseで結果が帰ってきたら、次の処理に移行することができます。 こちらも参考リンクがとても参考になります。

dfds = []

$.each(array, function(index, value){
  dfd = new $.Deferred()

  $.ajax(
    url: value
    type: 'PUT'
    data: data[index]
    cache: false
    contentType: false
    processData: false
  ).done(finction(data){
    dfd.resolve()
  }).fail(function(){
    alert '処理に失敗しました。'
    dfd.reject()
  })
  dfds.push(dfd.promise())
})

$.when.apply($, dfds).done(hogehoge())

参考

techblog.yahoo.co.jp

S3に大容量ファイルを直接アップロードする(署名付きURL + マルチパートアップロード)

ubw.hatenablog.com

前回、署名付きURLを利用し、S3に対してファイルを直接アップロードできることを確認した。 この方法で、curlコマンドで大容量のファイルがアップロードできることも確認した。 ブラウザからも200MB程度のファイルをAJAXでアップロードできることを確認した。

しかし、300MBのファイルがブラウザからアップロードできず。。。 何か設定が足りていない・・・? どうやら調べていると、大容量ファイルのアップロードはマルチパートアップロードを推奨しているとのこと。

そこで、署名付きURL + マルチアップロードを試してみることにした。

目的

クライアントは署名付きURLを利用してファイルをマルチパートアップロードする

環境

構成

f:id:t-sanox:20160814161940p:plain

処理の流れ

  1. create_multipart_upload
  2. 署名付きURLの生成(ファイル分割数だけ)
  3. partsの取得
  4. complete_multipart_upload

やり方

前提として、AWSの設定は前回と同じように実施した。

1. create_multipart_upload

upload_id等を発行する。upload_idは署名付きURLを発行する際に利用する。

s3 = Aws::S3::Client.new
uploader = s3.create_multipart_upload(bucket: bucket_name, key: key)

2. 署名付きURLの生成(ファイル分割数だけ)

分割してアップロードするファイルの数だけ署名付きURLを発行する。

presigner = Aws::S3::Presigner.new
urls = []
(1..part_number).each do |num|
  urls.push(
    presigner.presigned_url(:upload_part,
                            bucket: uploader.bucket,
                            key: uploader.key,
                            upload_id: uploader.upload_id,
                            part_number: num))

3. partsの取得

署名付きURLでのアップロード完了後に実施する。 マルチアップロードの完了には、etagとpart_numberが必要になる。 下記コードで、マルチアップロードのpart一覧から、etagとpart_numberを取得する。

parts = []
parts_info = s3.list_parts(bucket: uploader.bucket_name, key: uploader.key, upload_id: uploader.upload_id).parts
parts_info.each do |part|
  part_info = { etag: part.etag, part_number: part.part_number }
  parts.push(part_info)
end

4. complete_multipart_upload

マルチアップロードを完了する。 完了させないと、ファイルはS3バケットに表示されない。

s3.complete_multipart_upload(
  upload_id: uploader.upload_id,
  multipart_upload: parts,
  bucket: uploader.bucket_name,
  key: uploader.key
)

AJAXで署名付きURLの発行、S3アップロードをする際の注意点(CORS)

ubw.hatenablog.com

 前回、署名付きURLを発行し、S3にファイルを直接アップロードすることに成功した。 次のステップとして、署名付きURLを利用し、ブラウザからのファイルアップロードを試してみた。 formで署名付きURLに対してPUTする方法もあるのだが、今回はAJAXでファイルをアップロードした。
 しかし、素直にアップロードできるはずもなく、CORSで何回か躓いたので記録しておく。
 当たり前だが、下記について、CORSの設定が必要だった。

  • 署名付きURLを発行するサーバ(Rails5 APIモード)
  • S3バケット

署名付きURLを発行するサーバ(Rails5 APIモード)

下記のgemを利用する。

gem 'rack-cors'

initializerのcors.rbに許可するOriginを追加する。

S3バケット

利用するリクエストに応じて、CORSの設定を変更する必要がある。 例えば、PUTリクエストをする場合は、下記のような設定を追加する必要がある。

<AllowedMethod>PUT</AllowedMethod>

リクエストヘッダーにContent-Typeを含める場合は、下記のような設定を追加する必要がある。

<AllowedHeader>Content-Type</AllowedHeader>

どのような設定をすればよいかは、ブラウザの開発者ツールでリクエストの内容を確認すればわかる。

CORSの設定変更は、AWSコンソールからできる。