nologyance.net

日々のアウトプット

mvとmoveでリネーム

書いてますか、batスクリプト

私は結構嫌いです。 今日もまさかのハマり方をしました。

リネームできない

bashのmvと同じようにbatのmoveでファイルのリネームをしようとしたところうまくいきませんでした。

原因

mvと違ってmoveを使ってリネームする場合、第2引数はパスではなくファイル(ディレクトリ)名である必要があります。 AをBにリネームする場合はこんな感じ。

move pathToA B

mvの場合は両方ともフルパス指定でないとカレントディレクトリにファイルが移動してしまったりするので勘違いしていました。

gradleビルドを高速化したい

非常に柔軟なビルドスクリプトが書けるGradle

業務システム界隈ではまだまだ普及期、Android界隈では標準といった具合の知名度でしょうか。 柔軟な記載ができる一方でgoovyのシンタックスシュガーに悩まされている方も多いのではないでしょうか。 私もその一人です。ちなみに特にこの記事でgradleの文法について触れるつもりはありません。

今回は高速化のお話

ローカル環境にしてもCI環境にしてもビルド時間は短いに越したことはないですよね。 開発者フィードバックが早まるため、バグの検出が前倒し出来て生産性の向上に直結します。 最近はそのあたりの課題に取り組んでいたので知見を書き残しておこうと思います。

まずは計測

課題解決は現状と理想を定義するところから始まります。 何かビルドが遅い気がするからなんとかしたい、ではなく「ベストプラクティスとしては一回のビルドが〇分以内と定義されているから今のビルド時間とギャップがある」のように具体的に課題を設定しましょう。 計測にはJUnitが出してくれるレポートや、gradle自体にもレポートや分析の機能が搭載されているため、利用しましょう。 調査の結果、実はビルドが遅いわけではなかった、なんて結論になるかもしれません。

計測したら現状を分析

現状を分析していくと大抵の場合、ボトルネックとなっている部分があるはずです。 それはコンパイルだったり、テストだったり、特定のプロジェクトだったり・・・ 原因によって有効な対処法は異なります。

改善

私が実施した改善策をいくつかご紹介しておきます。 特にheap領域の割り当てはデフォルト設定のまま利用されている場合、結構な効果が期待できると思います。

コンパイルが遅い

  • gradleが利用するjvmのheap領域を増やす。 GRADLE_OPTSやgradle.propertiesで設定できます。
  • --parallelオプションを利用する こちらは独立したマルチプロジェクト構成のときにのみ有効

テストが遅い

俺たちのテスト改善はこれからだ

まだプロジェクト初期段階であればJUnitの@Categoryをつけておくと後から困らない気がします。 年代物のプロジェクトの場合は・・・頑張ってください。

ECSデビューメモ

クラスター、サービス、タスク定義、タスクの違い

クラスターはただの箱。 タスク定義からタスクを生成する、それを束ねたものがサービス。 タスクが協調して一つのサービスを提供する。

動的ポートマッピング

タスク定義でポートを0にすると、動的ポートマッピングが行われる。 タスクのポート管理をよしなにやってくれるらしいけど、向けたいポートはどうやって管理されるのだろうか。

タスクの停止

ECSは高いので使わないときは停止しておきたい。 しかし、単純にタスクを停止しただけではすぐに新しいタスクが立ち上がってしまう。 完全に停止させたい場合は必要なタスク数を0にすることで、停止状態を維持できる。 自動起動と停止を実現するにはlambdaでECSサービスを更新するfunctionを書いてやればよい。

amplifyで作成したAppSyncのAPIKeyが失効した

amplify pushに失敗する

こんな感じのエラーが出て失敗する。

UPDATE_FAILED               GraphQLAPIKey                                      AWS::AppSync::ApiKey        Fri May 17 2019 00:37:17 GMT+0900 (JST) API key not found: xxxxxxxxxxxxxx (Service: AWSAppSync; Status Code: 404; Error Code: NotFoundException; Request ID: xxxxx)

API Keyが失効

API Keyによる認証方式はあくまで開発ユースを想定しており、7日間で失効するらしい。 https://aws-amplify.github.io/docs/js/api#aws-appsync-sdk

自動更新設定

${project}/amplify/backend/api/motibetas/parameters.jsonに "APIKeyExpirationEpoch": "-1" を設定することでKeyの失効時に自動更新してくれるようになる。

https://aws-amplify.github.io/docs/cli/graphql#apikeyexpirationepoch

ELBを作成する際の注意点

そこまで冗長化は必要ないけどそれなりにセキュアにしたい場合のVPC構成

このスライドの右(あるいは左)半分のみ構築してEC2を運用されている方もいるのではないでしょうか。 私もその一人です。

この構成の何が良いかというと、 見出しのとおり、そこそこセキュアで安いという点。

すべてをpublic subnetに曝け出しているよりはかなり安全になります。

ELBを追加

この環境でAutoscalingを実施するためにELBを立てるとします。 すると困るのがsubnetの扱い。

ALBを作成する際には配置するsubnetを2つ指定しなければなりません。 今存在するsubnetは2つしかないのでそれぞれ指定します。

すると「次のサブネットにはインターネットゲートウェイが存在しません。」との表示が。 そりゃprivate subnetはNATゲートウェイ経由にしてるからな! と自信満々に作成してしまったあなた(私)、こんな現象に出くわしていませんか?

たまにインスタンスに繋がらない(極端にレイテンシが増加する)

低負荷状態であるにもかかわらず、なぜかインスタンスに繋がらないことがある。 ヘルスチェックを確認しても特に異常なし。 繋がらない、ではなく繋がらないことがある。というのがやっかいなところ。 私もかなり頭を捻りました。

するとこんな記事を発見

https://stackoverflow.com/questions/35523421/aws-elastic-load-balancing-seeing-extremely-long-initial-connection-time

どうやらインターネット向けのELBにprivate subnetを紐づけるのは間違いらしい。

ちゃんと公式にも回避策が書いてありました。 https://aws.amazon.com/jp/premiumsupport/knowledge-center/public-load-balancer-private-ec2/ 空のpublic subnetを作って紐づければよいみたいですね。

ELBが配置される場所

作成時にsubnetを指定するので、てっきりターゲットが存在するsubnetに配置しなければいけないものだと思い込んでいましたが、どうやら違うみたいです。 バランシングの候補になるのはおそらくELBが配置されているAZ全体。

むしろインターネット向けのELBをprivate sunbetに配置すると外からは見えない様子・・・ おそらくですが、繋がったり繋がらなかったりしたのはpublic subnet側のAZを経由してprivate側にアクセスが行われていたためと推測しています。

ちゃんと警告は読みましょう

ちゃんと作成時の警告を素直に受け取っていればこんなことにはならなかったのにね。

AWS Amplify Vue.js vuetifyでサンプル実装

ついに始動

AWSソリューションアーキテクトの勉強等もあり、プロジェクトの構想からはずいぶんと時間が経ってしまいましたが、 いよいよ本格的にオリジナルアプリの開発に着手しました。

まずは基盤づくり

https://qiita.com/shunp/items/d491adfadd570f66f990

こちらの記事を参考にプロジェクトのセットアップを行いました。 ただし、私の場合はBuefyではなくvuetifyを使うため、vuetify公式サイトを参照しながら必要な部分は書き換えています。

<template>
  <div>
    <nav class="level">
      <div class="level-item has-text-centered">
        <v-form ref="form">
          <v-text-field v-model="input.name" label="Task"></v-text-field>
          <v-text-field v-model="input.description" label="Description"></v-text-field>
        </v-form>
      </div>
      <div class="level-item has-text-centered"></div>
    </nav>
    <button class="button is-link" @click="createTodo">ADD</button>
    <ul id="todo">
      <li v-for="todo in todos" :key="todo">
        <span class="todo-wrapper">{{ todo.name }}</span>
      </li>
    </ul>
  </div>
</template>

<script>
import { API, graphqlOperation } from "aws-amplify";
import * as mutations from "@/graphql/mutations";
import * as queries from "@/graphql/queries";

export default {
  name: "todo",
  data: function() {
    return {
      input: {
        name: "",
        description: ""
      },
      todos: []
    };
  },
  created: async function() {
    await this.listTodos();
  },
  methods: {
    createTodo: async function() {
      if (this.input.name !== "" || this.input.description !== "") {
        await API.graphql(
          graphqlOperation(mutations.createTodo, { input: this.input })
        ).catch(err => console.error(err));
        await this.listTodos();
      } else {
        console.info("input empty");
      }
    },
    listTodos: async function() {
      const res = await API.graphql(graphqlOperation(queries.listTodos)).catch(
        err => console.error(err)
      );
      this.todos = res.data.listTodos.items;
    }
  }
};
</script>
<style scoped>
</style>
import Vue from 'vue'
import './plugins/vuetify'
import App from './App.vue'
import router from './router'
import store from './store'
import Amplify, * as AmplifyModules from 'aws-amplify' // 追記
import { AmplifyPlugin } from 'aws-amplify-vue' // 追記
import aws_exports from './aws-exports' // 追記
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css'
Vue.use(Vuetify)
Amplify.configure(aws_exports) // 追記

Vue.use(AmplifyPlugin, AmplifyModules) // 追記

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

動作確認

タスクの名前と説明を入力して「ADD」をクリックすると、タスクリストに入力した値が表示されました。

勉強メモ

・async await ・createdのタイミング

AWSソリューションアーキテクトアソシエイト試験に合格しました

祝合格

タイトルの通りです。 これから挑戦される方の参考になればと思い、私の経歴と試験対策について書いておこうと思います。

AWS

業務で約半年ほど利用。 利用経験があるサービスはec2,vpc,s3,codebuild,codepipeline,lambda,cloudwatch,cloudformation等。 DB、コンテナやデータ処理系のサービスはほとんど触ったことがありません。

勉強法

ちょうどAWS reinventで対策講座があったので一通り視聴 ⇒Udemyの講座で触ったことのないサービスの説明を中心に一周して模擬試験で理解度確認 ⇒間違えたところをホワイトペーパーで確認 という流れを時間がある限り繰り返しました。

https://www.udemy.com/aws-associate/

丸3日ほどの勉強時間でなんとか合格できました。 実務経験のある方ならサクッと合格できるのではないでしょうか。 決して安い受験料ではないのでしっかり準備して臨むに越したことはないですが。