2014-12-30

Intel Dual Band Wireless-AC 7260 でスリープ解除後 Wi-Fi が繋がらなくなる

スリープ解除後 Wi-Fi が繋がらなくなって、再度スリープ、スリープ解除するか、デバイスの有効無効を切り替えないと復帰しない不具合が、Intel Dual Band Wireless-AC 7260 (Intel® PROSet/Wireless Software and Drivers 17.1) と NEC Aterm WF800HP (ファームウェア Ver1.0.16) の組み合わせで発生していました。

Intel 側も相互運用性に関する問題を認識しているらしく、この解説 の通りデバイスの詳細設定で、省電力に関する機能 U-APSD 対応を無効とすることで繋がらなくなる現象は発生しなくなりました。 直っていませんでした。以下の追記のご参照をお願いします。



2015/01/22 追記
U-APSD 無効の設定でもしばらく使っていると切れたままになる現象は起こったので、この機能は原因ではなかったようです。

ドライバのバージョンを 17.13.11 に更新して、設定は U-APSD も含めて初期状態で、2週間ほどスリープを駆使しながら使っているのですがまだ一度も発生していないので、ドライバの更新をお勧めします。



リンク
Intel® Wi-Fi Products — TechNote: Access Point Interoperability Issue with uAPSD
Windows 8.1* 用インテル® PROSet/Wireless ソフトウェア - インテル® ダウンロード・センター

2014-12-29

CloudFlare: サブドメイン毎に Flexible, Full SSL を設定する

CloudFlare の SSL 設定の種類 (What do the SSL options (Off, Flexible SSL, Full SSL, Full SSL Strict) mean?) の設定について、ドメイン全体に適用されるグローバルな設定だけでは不十分なときは、Page rules の SSL から個別に Flexible SSL にするか Full SSL にするかなどの設定を行うことが出来ます。

設定画面へは My websites から、右の歯車を押して、Page rules で行けます。対象とするパスは www.example.com/* のように入力すれば OK みたいです。

Page rules の設定は Free plan だとドメインあたり3個までなので、足りない場合は Pro plan に移行する必要があります。

2014-12-28

.htaccess を使って利用可能な Apache モジュールの一覧を取得する

共有サーバーなど、httpd.conf や mod_info の server-info を確認できない状況で、組み込まれているモジュールを確認するには、IfModule と Header append を組み合わせると、指定した中で利用可能なモジュールをレスポンスヘッダー X-Module に出力することができます。

# .htaccess

<IfModule mod_deflate.c>
    Header append X-Module mod_deflate
</IfModule>
<IfModule mod_expires.c>
    Header append X-Module mod_expires
</IfModule>
<IfModule mod_rewrite.c>
    Header append X-Module mod_rewrite
</IfModule>
<IfModule mod_ratelimit.c>
    Header append X-Module mod_ratelimit
</IfModule>
<IfModule mod_setenvif.c>
    Header append X-Module mod_setenvif
</IfModule>

2014-12-13

Chrome でダウンロードしたファイル名の一部がハイフンになる

Google Chrome で Content-Disposition ヘッダでファイル名に時刻 (12:34:56) のような文字列を入れてダウンロードするとなぜか勝手に 12-34-56 のようにハイフンになってしまう理由が良く分からなかったのですが、Windows ではそもそもファイル名にコロンは使えないので、安全のため全プラットフォームでファイル名にコロンを含む文字列を設定しないようになっているからみたいです。

変換対象の文字一覧は、filename_util_unsafe.cc の illegal_characters に入っていて、変換先がハイフンになる理由は、filename_util_internal.cc の GetSuggestedFilenameImpl でコールバック関数 replace_illegal_characters_callback を第二引数を '-' として呼び出しているからのようです。

ReplaceIllegalCharactersInPath の使い方は変換先を ' ' にしたり '_' にしたりするバリエーションがあったので、必ずしもハイフンに変換されるという訳ではないみたいです。

リンク
https://chromium.googlesource.com/chromium/src.git/+/39.0.2171.95/net/base/filename_util_unsafe.cc
https://chromium.googlesource.com/chromium/src.git/+/39.0.2171.95/net/base/filename_util_internal.cc

2014-11-24

Cocos2d-x で dlopen failed: cannot locate symbol "rand"

EABI は正しいのに Cocos2d-x v3 のアプリが立ち上がらずに即座にクラッシュする場合、ログに dlopen failed: cannot locate symbol "rand" が出ていないかを確認してみてください。

これはどうやら NDK が Android 5.0 (Lollipop) 64bit でしか動かないバイナリを作ってしまっているのが原因のようで、Cocos2d-x で公式に推薦されている Android NDK r9d を使うと大丈夫でした。

リンク

Issue 168 - android-developer-preview - libc removed issetugid - A public project for reporting issues with Android Developer Preview releases - Google Project Hosting
NDK r9d url - Compiling and linking error when using NDK r10 to build cocos2d-x v3.2 | Cocos2d-x

2014-11-06

CloudFlare: 自動スクリプト挿入を止める方法

無料で使える Universal SSL がどんな仕組みなのか気になったので、最近 CloudFlare を試しているのですが、初期状態でなぜか全ページに cloudflare.min.js が head 内に挿入されるのが気になったので、入らないようにする設定について調べてみました。

CloudFlare Apps で最初から有効になっているものが2つあって、ScrapeShield の E-mail obfuscation と SmartErrors で、両方を Off にするとスクリプトは入らなくなりました。上手く消えない場合は何度か On, Off を繰り返すか、Purge Cache するか、ページを Ctrl + Reload すると良かったです。



2014-10-03

ISUCON4 に挑戦して予選敗退しました

アプリの実装は Node.js を選択、データストアは MySQL のままで、login_log を ban_ip, ban_user, last_login の3つのテーブルに分割して作り直してみましたがいまいちスコアを伸ばすことができず (14629) 予選敗退しました。

途中 /report の不整合が報告される問題が起こりましたが、これは login_log の7万件の初期データが反映されている必要があることに気づかなくて少し手間取りました。

マルチプロセス化のセッション共有方法は memcached、ローカルポート枯渇は sysctl.conf を設定、nginx の接続数上限は設定の変更で対応しました。

とても楽しいイベントを開催していただいた運営の方々にはとても感謝します。また挑戦しようと思います。

コード
hidekiy/isucon4 - GitHub

2014-09-28

Uptime Robot API を使って監視設定を一括更新する

Uptime Robot という無料で 50サイトまで死活監視してくれるサービスについて、監視設定を一括更新するには以下のように API を使うと簡単にできます。

requests ライブラリを使用しているので事前に pip install requests が必要です。

import requests

urlBase = 'https://api.uptimerobot.com'
baseParams = {
    'apiKey': 'u123123-ffffffffffffffffffffffffff',
    'format': 'json',
    'noJsonCallback': 1,
}

# alert contact id を取得します
for alertcontact in requests.get(urlBase + '/getAlertContacts', params=baseParams).json()['alertcontacts']['alertcontact']:
    print alertcontact['id']

# 全監視設定を更新します
for monitor in requests.get(urlBase + '/getMonitors', params=baseParams).json()['monitors']['monitor']:
    print monitor['id'], requests.get(urlBase + '/editMonitor', params=dict(baseParams, **{
        'monitorID': monitor['id'],
        'monitorAlertContacts': '123-456', # ハイフン区切り
        'monitorInterval': 5,
    })).json()

リンク
Uptime Robot API Documentation

2014-09-16

映画「STAND BY ME ドラえもん」を見ました

レイトレーシング による正確な光の表現の涙、ドラえもんの鈴、ドラえもんボディの光沢感の違う素材は技術の進歩を感じる。タイムマシンの中の表現、のび太の机のデスクライトのシェードが透ける表現も良かったと思う。

鍵盤ハーモニカのケースの色合いの違いはとても良い。一方でドラえもん登場シーンでは量が正確に揃いすぎているお茶が出てきて笑った。

しつこく見せつけられるトヨタ。のび太の車のロゴ、未来の街に看板が2つ (TOYOTA, FUN TO DRIVE, AGAIN.)、一方ヒミツ道具は操作盤が白地に黄緑の光で、角が丸っこい感じが何となく Panasonic 感がするものが多かった。看板も1つ出ていた (Panasonic)

相変わらずのび太の車はのび太が運転していたし、脈拍数低下してきても音声アラートを鳴らすだけでオーナーを見殺しにするスマートウォッチは何も進歩しておらず、ココセコム の方がずっと先を行っていると感じた。

序盤は、好奇心ではなくそれぞれ恐怖にドライブされているドラえもんとのび太 (仕込まれたプログラムに違反すると電撃、このままでは就職できないぞ) にはクリエイティビティを感じないし見ていて辛かった。

中盤以降は、のび太の、人のことを思いやる気持ち、というのが引き出されていて良かったと思う。

映画「STAND BY ME ドラえもん」公式サイト

2014-09-14

StatusCake API を使って監視設定を一括更新する

StatusCake とは基本無料でサイト数の制限なく Web サイトの死活監視を行えるとても便利なサービスです。監視設定は管理画面より一つづつ設定を更新することは可能なのですが、複数の監視設定の変更を一度に行う一括更新機能は無いようなので、StatusCake API を使って変更を行ってみました。

API Key はアカウント情報のページより取得できます。Username はログイン時のユーザー名を入力してください。以下のサンプルコードは Python で requests ライブラリ を使った場合の例です。動作させるには pip install requests を実行してライブラリを追加してみてください。

import requests

urlBase = 'https://www.statuscake.com/API'
authHeaders = {'API':'APIKEY', 'Username':'USERNAME'}

# 各テストをすべて更新する例
for test in requests.get(urlBase + '/Tests', headers=authHeaders).json():
    print test['TestID'], requests.put(urlBase + '/Tests/Update', headers=authHeaders, data={
        'TestID': test['TestID'],
        'Confirmation': 3,
        'TriggerRate': 1,
        'CheckRate': 300,
    }).json()

# テスト詳細の取得
requests.get(urlBase + '/Tests/Details', params={'TestID': 123123}, headers=authHeaders).json()

# コンタクトグループ一覧を取得
requests.get(urlBase + '/ContactGroups', headers=authHeaders).json()

メモ
Web の管理画面ではテストに対してコンタクトグループを複数指定できるのですが、API からは最初の1つのみ更新できるようです。

API の末尾のスラッシュは無くても大丈夫みたいです。

StatusCake に似たサービスで、50個まで監視項目を設定できる Uptime Robot というサービスもあります。

リンク
StatusCake - Website Uptime Monitoring & Alerts – Free Unlimited Downtime Monitoring
StatusCake API Documentation
Requests: HTTP for Humans

2014-08-30

[windows] ハードディスクの内容を完全に消去する

Windows Vista 以降では、OS 標準のフォーマットツールで、クイックでない完全なフォーマットを行うと、Windows Vista の format コマンドの動作の変更 の通り、ゼロフィルを行うように仕様が変更されたので、GUI/CUI で通常のフォーマットを行えばそれで良いです。

考慮すべきこととしては、通常の方法以外でデータが読み取られる可能性が考えられます。バッドセクタになってしまった場所の機密情報を HDD のコントローラーを操作して読み取ったり、磁気力顕微鏡 を使ってプラッタの残留磁気を読み取られる可能性を考慮しないなら、消去方法は1回のゼロフィルで十分実用的と思います。

Windows XP 以降をお使いの場合は、diskpart の clean all コマンドを使うとディスク全域へのゼロフィルを行うことが出来ます。具体的な手順は以下のようにすれば OK です。

diskpart を管理権限で実行

list disk
select disk 123 # 消去対象を選択する
detail disk # 確認
clean all

OS のディスクを消去したいなど、OS を使わずにディスクを抹消したい場合や、1回のゼロフィルではなく政府機関認定の消去シーケンスを実行したい場合は、DBAN (Darik's Boot And Nuke) を使えば良いです。

DBAN の無人モードは全ディスクを消去する機能で、あるディスクのみ消去するときはインタラクティブモードを使います。消してはいけないディスクがある場合、念のため BIOS/UEFI で ATA ポートを Disable にしておくと良いです。

本当にディスクが消去されているのかを目視確認するには、ディスクをローレベルで見ると良いです。Windows の場合は HxD - Freeware Hex Editor and Disk Editor などで確認できます。

SSD を消去したい場合は、製造元の提供するツールを用いて消去を行うと早く完全な消去が行えると思います。具体的には、Intel SSD Toolbox, Samsung Magician Software, OCZ Toolbox などに存在する、Secure Erase 機能が該当します。

2014-08-24

Google Tag Manager を使って JavaScript エラーを収集する

Google Tag Manager は単にアクセス解析のタグを配信するだけでも、サイト自身にトラッキング ID などを直接埋め込まずに Tag Manager 管理画面から誰でも変更可能な状態に出来てとても便利です。

今回はさらにエラーリスナータグと、ユニバーサルアナリティクスのイベントトラッキングを組み合わせることで、サイトに変更を加えることなく、サイト上で発生したエラーを Google Analytics のイベントとして収集する方法を考えてみます。

設定方法

まず、エラーリスナータグを全ページに配信するように設定します。

次に、エラーリスナータグの発生させたイベントをユニバーサルアナリティクス (トラッキングタイプ=イベント) を使って報告したいのですが、エラー情報を受け渡す方法が一見したところ良く分かりません。色々触ってみたところ、受け渡し方法は、マクロを経由してデータレイヤ変数を引き渡せば良いみたいです。

こちらのヘルプ JavaScript エラー リスナー - イベント リスナー - Tag Manager ヘルプ
に書かれている通り、データレイヤ変数が設定されるので、以下のようなマクロをまず設定します。

マクロ名 dataLayer gtm.errorLineNumber
マクロのタイプ データ レイヤー変数
データ レイヤー変数名 gtm.errorLineNumber
データ レイヤーのバージョン バージョン2

このようなマクロを使って、以下のようなイベントトラッカーを設定します。

配信条件 {{event}} が gtm.pageError に等しい

タグの種類 ユニバーサルアナリティクス
トラッキング タイプ イベント

イベント トラッキングのパラメータ
  カテゴリ gtm
  操作 {{event}}
  ラベル {{dataLayer gtm.errorUrl}}:{{dataLayer gtm.errorLineNumber}}: {{dataLayer gtm.errorMessage}}
   (空欄)
  非インタラクション ヒット True

レポートの見方

エラー統計情報は、レポートで、行動 > イベント > 上位のイベント > イベントカテゴリ、から順番にクリックして以下のように絞り込めば OK です。
すべて » イベント カテゴリ: gtm » イベント アクション: gtm.pageError

追加情報

イベント リスナー - Tag Manager ヘルプ によると、同様のイベントリスナーは他にも以下のものが利用可能です。例えばクリックリスナーを使用すると、どの DOM 要素がクリックされているかを、要素の ID などで識別して収集することが出来ます。

クリック リスナー
フォーム送信リスナー
リンク クリック リスナー
タイマー リスナー
履歴リスナー
JavaScript エラー リスナー

ユーザーの安全のためこのイベントトラッキングはユニバーサルアナリティクスの SSL 有効モードで行うのが良いと思います。

[java] Lombok と AspectJ を組み合わせて使う

Lombok はリフレクションなどは使用せず、コンパイル時にゲッターやセッター、ロガー、toString、hashCode, equals など自動生成出来そうなものを生成してくれる大変便利なライブラリです。これと、AspectJ を組み合わせようとすると、厄介な問題が発生したのでメモしておきます。

まず、よく使用されているらしい aspectj-maven-plugin を使おうとすると、ソースコードに対する weaving は Lombok が処理する前のコードをコンパイルして weaving しようとして、コンパイルに失敗しました。そこで処理対象を Java バイトコード (.class) に変更しようとして、この方法 を見つけました。頑張れば出来そうな気はしますが spring-aspects を使うプロジェクトでまだ上手くビルド出来ていません。

次に見つけた、jcabi-maven-plugin の ajc ゴール を使う方法は、特に何も追加の設定をすることなく、Lombok 経由で作られた .class に対して weaving を行ってくれました。この組み合わせが良いと思います。


<!-- project > build > plugins -->
<plugin>
  <groupId>com.jcabi</groupId>
  <artifactId>jcabi-maven-plugin</artifactId>
  <version>0.9.3</version>
  <executions>
    <execution>
      <goals>
        <goal>ajc</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Spring Framework + AspectJ
少し蛇足ですが、@Transactional, @Scheduled, @Async, @Cacheable を使うには、mode = AdviceMode.ASPECTJ に加えて spring-aspects をコンパイル時依存に追加する必要があります。同じく @PreAuthorize, @PostFilter, @Secured など、@EnableGlobalMethodSecurity で有効になる仕組みを使うには spring-security-aspects が必要です。

また実行時依存に aspectjrt も追加しておきましょう。通常時は使われる気配はありませんがこちらの FAQ によると異常時の挙動に関係するようです When I run, I get a NoAspectBoundException or a ClassNotFound message for NoAspectBoundException.

今回はコンパイル時の weaving について記述しましたが実行時の weaving も可能なので、興味のある方は @EnableLoadTimeWeaving のあたりを調べてみてください。

[android] 定期的に位置情報を取得するアプリ

Android 4.2 にて、GPS 有効の状態で、バックグランド時も定期的に詳細な位置情報を取得するという動きをするアプリが1つでも存在すると、電池がどんどん無くなるので、この現象が起こりうるアプリについてメモしておきます。

新しくインストールしたアプリが原因で、この不可解な電池消費が起こり得ることが心配な方は、高精度の位置情報が必要な時以外は GPS 無効にしておくのが良いと思います。

Google の現在地送信機能
Path の近所機能
Path Talk の Ambient Status の Location 自動更新機能
Facebook の近所通知機能 (過去存在したが最新バージョンでは削除されているようです)

また、このアプリを使うと、どのアプリのせいでスリープ状態が解除されているか分かって大変便利です。
Wakelock Detector

2014-08-23

Google Analytics でサイトの速度サンプルレートを設定する

Google Analytics にはサイトの速度を計測する仕組み (レポート > 行動 > サイトの速度 を参照) が存在するのですが、デフォルトのサンプリングレートが 1% になっているので、アクセスの少ないページの情報が少なくて寂しいです。そこで、全アクセスについて計測対象とするように、サンプリングレートを 100% とするには、以下のようにすれば良いです。

新しい方の Universal Analytics (analytics.js) を使用している場合以下のようにパラメータ siteSpeedSampleRate を与えます。

(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');

// こっちは削除
// ga('create', 'UA-XXXX-Y', 'auto');
ga('create', 'UA-XXXX-Y', 'auto', {'siteSpeedSampleRate': 100});
ga('send', 'pageview');

古い方の ga.js を使用している場合は以下のように設定用メソッド _setSiteSpeedSampleRate を呼び出します。

var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-X']);
// 次の行を追加
_gaq.push(['_setSiteSpeedSampleRate', 100]);
_gaq.push(['_trackPageview']);

 (function() {
  var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
  ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
  var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();

Google Tag Manager でユニバーサルアナリティクスを使用している場合は、詳細設定 > 設定するフィールド に以下の設定を追加します。
フィールド名 siteSpeedSampleRate, 100

確認方法
正しく設定されたことを確認するには、ユニバーサルアナリティクスの場合、www.google-analytics.com/collect に対して、t=pageview の他に、t=timing のリクエストが行われていることを確認すると良いと思います。

ga.js の場合は、http://www.google-analytics.com/__utm.gif に対するアクセスを見ると何か分かりそうです。

リクエストが全く無くなってしまっている場合、トラッキングコードがおかしくなっている可能性があります。

注意
ga.js より以前に使われていた urchin.js を使用している場合はサイト速度計測は利用できないようです。

速度の計測に際してクライアント側に多少のオーバーヘッドが発生することは確かなので、本当にサンプリングレートを上げても良いかについては各自検討が必要です。

リンク
analytics.js のフィールドに関するガイド - Google アナリティクス - Google Developers - analytics.js (Universal Analytics) の場合について
_setSiteSpeedSampleRate() - Tracking Code: Basic Configuration - Google Analytics - Google Developers - ga.js (一つ前のバージョン) の場合について

2014-07-23

[Android] Facebook, Twitter アプリのベータテスターになる方法

ベータテスタープログラムに参加して Facebook, Twitter アプリの最新版を試してみてはいかがでしょうか?

多少の不完全さ (ローカライズの不備、便利なのか良く分からない機能など?) を受け入れることで、正式版を使っている人より1か月 (体感値) ほど先を行くことが出来ます。また、UI の変更などもいち早く察知することができ、アプリ開発者でなくとも興味のある方もいらっしゃるのではないかと思います。

Facebook

  1. こちらのグループに参加する: Facebook for Android Beta Testers
    「自分の表示名」の欄は何でもよいので入れる必要があります。あとで変更も可能です。
  2. こちらで「テスターになる」を押す: Android アプリのテスト - Google Play

Twitter

  1. こちらのグループに参加する: Twitter for Android Experiment
    Facebook の場合と同様ですが、加えて Google+ プロフィールでの参加はできない設定のようです。
  2. こちらで「テスターになる」を押す: Android アプリのテスト - Google Play

補足

「テスターになる」のページではテスターをやめることも可能です。ダウングレードは行われないので、元に戻すにはアンインストール、再インストールを行えばよいです。

テスター設定は端末単位ではなく同一の Google アカウントすべてに影響します。現行リリースバージョンと比較するためには別の Google アカウントを用意する必要があります。

モバイル版 Google グループ はエラーが適切に表示されない (バリデーションエラーが全て500エラーと表示されるなど) 気がするので PC 版を使うことを推奨します。

リンク

Android用Facebookのベータプログラム
Twitter for Android experiment agreement - 利用規約

2014-05-19

静的ファイルの配信を Google Cloud Storage に移行しました

ブログの静的ファイルの配信を Amazon S3 + CloudFront の構成から、Google Cloud Storage へ移行してみました。Google Cloud Storage の方は単体で CDN 付なのでオブジェクトの ACL を一般公開設定にするだけで CDN 部分の設定が不要なのが便利です。

具体的には、Cloud Storage のコンソールで配信したいドメイン名でバケットを作成し、CNAME を c.storage.googleapis.com に向ければよいです。ドットを含む名前でバケットを作成する際は、それがドメインの所有権の確認が済んでいるドメイン以下である必要があるみたいです。
Bucket and Object Naming Guidelines - Google Cloud Storage

準備
Web UI はありますが細かい設定をしようとすると現時点では1ファイルずつしか設定できないので、速やかにCLIツールをインストールすることをお勧めします。

使用するコマンドは gsutil (Google Storage Util?) で、これのみインストールする方法もありますが gcloud コマンドからインストールすると自動更新対象になって良いと思います。gcloud コマンドのインストールは、Google Cloud SDK Quick Start で、インストール中にお勧めされるがままに進めると自動で gsutil も使用可能になると思います。

コマンド集

# バケット一覧
gsutil ls

# ヘルプ
gsutil help cp

# ファイルをアップロード
gsutil cp SRC DEST

# ディレクトリをアップロード
gsutil cp -r SRC_DIR DEST

# 今回アップロード時に使ったコマンド
gsutil -h "Cache-Control: public,max-age=31536000" cp -a public-read -z js,css,txt,html -r SRC_DIR gs://static.hidekiy.com/1/

setmeta が遅い
オブジェクトの新規作成 cp に比べてメタデータ (HTTP ヘッダー) の設定 setmeta は2倍~3倍ほど遅いように思ったので、配信を中断してよいのであればいったん削除してアップロードすると良いと思います。

遅い理由は、現在の ACL を読み取り、書き込みの2操作が余計に必要だからのようで、あらかじめバケットのデフォルト ACL を defacl で設定しておき、その設定のままで良いのであれば -n オプションを使って高速にメタデータを設定できるみたいです。

# gsutil help setmeta

-n          Causes the operations for reading and writing the ACL to be
             skipped. This halves the number of operations performed per
             request, improving the speed and reducing the cost of performing
             the operations. This option makes sense for cases where you want
             all objects to have the same ACL, for which you have set a default
             ACL on the bucket(s) containing the objects. See "help gsutil
             defacl".

gzip 済みで配信する方法
gsutil cp -z <ext,...> を使うと良いです。

デフォルト1時間になっている max-age を長くしたい
gsutil -h "Cache-Control: public,max-age=31536000" cp
で OK でした。cp の前に書くのがポイント。

全エッジサーバーからキャッシュを削除したい
オブジェクトを削除するとエッジサーバーにも伝搬するような挙動があるみたいです。これが公式仕様なのかは良く分かりません。

S3 との相違点
S3 では存在したアップロード先リージョンの指定がないので、その辺は Google が責任をもってデータを配置してくれるのだろうと思います。

追記 (2014/12/10)
データの保管されるリージョンはバケットの作成時に CLI で指定することが出来て、作成時に指定しなかった場合のデフォルトは US でした。+Shingo Ishimura さんご指摘ありがとうございます。
mb - Make buckets - Google Cloud Storage — Google Cloud Platform

また、S3 には存在したデータ喪失の可能性が上がるのを認めることでコストを下げるストレージタイプ (Reduced Redundancy Storage) の代わりに、耐久性ではなく可用性 (Availability) を下げるストレージタイプが Google Cloud Storage にはあるみたいです (Durable Reduced Availability Storage)。

QUIC 対応
とくに頼んでないですが Alternate-Protocol:80:quic になっているので可能な場合は QUIC で配信してくれるみたいです。


リンク
Concepts and Techniques - Google Cloud Storage — Google Cloud Platform
GoogleAppEngine - GCP エッジキャッシュ - Qiita

2014-05-11

Google Cloud DNS を使ってみました

Google が 2014/3/25 発表した Google Cloud DNS を個人用ドメイン hidekiy.com で使い始めてみました。値段も AWS に比べて少し安く設定されているみたいです。

2014/5/11 時点

Amazon Web Services
0.50 USD(ホストゾーンごと)/月 – 最初の25のホストゾーン
0.10 USD(ホストゾーンごと)/月 – それ以上のホストゾーン
0.500 USD(100万クエリごと)-最初の10億クエリ/月
0.250 USD(100万クエリごと)-10億クエリ以上/月

Google Cloud Platform
Managed Zones: 0-25  $0.20 per managed zone per month
Managed Zones: 25+  $0.10 per managed zone per month for each additional zone after 25.
Queries: 0-1 billion  $0.40 per million queries.
Queries: over 1 billion  $0.20 per million queries per month.

AWS Route 53 の SLA (Service Level Agreement) は 100% Available なことで有名ですが、先日の以下の件について、何ら公式発表はなく、何も起こっていないかのように処理されているようなので、個人的に AWS の極東地域用の IP エニーキャストの運用についてちょっとした疑問が生じています。


手順
公式ドキュメント Getting started with Google Cloud DNS の通りで問題なく使えたので是非チェックしてみてください。gcloud コマンドも大変良くできていて、ログインはブラウザで認可ボタンを押すだけで済みます。

コマンド集

# コマンドを忘れていても適当に叩くとコマンド一覧が出るので安心
gcloud
gcloud dns

# きちんとヘルプ付いてる
gcloud dns managed-zone create -h

# managed-zone を作成
gcloud dns managed-zone create --description DESCRIPTION --dns_name DNS_NAME

# managed-zone 一覧
gcloud dns managed-zone list

# 現在のレコード内容を表示
gcloud dns records -z ZONE list

# レコードを編集
gcloud dns records -z ZONE edit

# 編集結果が反映されているかを確認
gcloud dns changes -z ZONE list

# 念のため自分でも確認
nslookup -debug -type=SOA example.com ns-cloud1.googledomains.com

Route 53 と異なる点
現在のところ Web 上の管理画面は無く、設定内容の確認にも CUI もしくは JSON API を使う必要があります。

Managed Zone 作成に先立ってドメインの所有権確認を TXT レコードか CNAME レコードを追加することで行う必要があります (Route 53 では無審査で作成できました)。

Managed Zone 料金は日割り計算されるようです (Route 53 では作成から24時間経過後から1か月分単位の請求になります)。Managed Zone の値段がちょっと違う気がします ($0.10 / month になってる?) が請求額が確定するまで様子見します。


Route 53 と違って Cloud DNS は IPv6 対応

C:\Users\Hideki>nslookup -type=aaaa ns-419.awsdns-52.com 8.8.8.8
サーバー:  google-public-dns-a.google.com
Address:  8.8.8.8

名前:    ns-419.awsdns-52.com


C:\Users\Hideki>nslookup -type=aaaa ns-cloud1.googledomains.com 8.8.8.8
サーバー:  google-public-dns-a.google.com
Address:  8.8.8.8

権限のない回答:
名前:    ns-cloud1.googledomains.com
Address:  2001:4860:4802:32::6a

メモ
SOA Serial は自動設定ではなく、変更したいのであれば明示的に変更する必要があり、そのためには、gcloud dns records edit 時の初期入力されている SOA レコードについての内容をそのまま使えば良さそうです。

お勧めする理由はありませんが SOA Serial を変更せずにレコードを変更することも出来ました。

自分の引っかかった点をメモしておくと、TXT, SPF レコードの値にスペースを含む場合は、ダブルクォートで囲む必要があります。正しい例:

{
   "kind": "dns#resourceRecordSet",
   "name": "hidekiy.com.",
   "rrdatas": [
       "\"v=spf1 +a +include:_spf.google.com ~all\""
   ],
   "ttl": 86400,
   "type": "TXT"
}

gcloud dns records edit の時のエディタの決定方法は、Windows の場合は .txt に対する関連付けにより、それ以外の OS では環境変数 EDITOR を参照するみたいです。

# google-cloud-sdk/lib/googlecloudsdk/core/util/edit.py

  if os.name == 'nt':
    subprocess.check_call([fname], shell=True)
  else:
    editor = os.getenv('EDITOR', 'vi')
    # We use shell=True and manual smashing of the args to permit users to set
    # EDITOR="emacs -nw", or similar things.
    subprocess.check_call('{editor} {file}'.format(editor=editor, file=fname),
                          shell=True)

gcloud dns records edit で保存する JSON ファイルで文法エラーが起こった時は、%TEMP% ディレクトリや /tmp を見に行くと最近作られた *.txt のファイルが残っているはずなのでそれで編集内容を救出できると思います。

リンク
Google Cloud DNS
Amazon Route 53