月別: 2015年9月

ISUCON5に参加しました。

チーム名「京都スイーツnext」でISUCON5に参加しました!

 

昨年に続き2回目の参加です。

昨年はサーバーもシステムも先輩方に頼りっきりで、

僕は邪魔にならないように応援することしかできませんでした( ̄▽ ̄;)

挙句の果てに唯一任せていただいたSELECT文 の「*」をカラム名指定で書くという修正でヘマをして

失格になるという。。

 

今回はスーパープログラマーの先輩がいなかったので、システムの修正は僕が担当しました!

サーバーエンジニアのはらぐちさんと相談しながら、うまく役割分担して修正を進めました。

今回はそこそこ貢献できたと思います。

まだまだできることがたくさんある中終了してしまい、結果は惜しくも本戦出場なりませんでした。

簡単なこともググりながらの作業で、基礎力のなさを痛感しました。

来年も参加して次こそは本戦出場したいです(`・ω・´)

 

ほぼ感想だけになってしまいましたが、修正内容とかはサーバーエンジニアのはらぐちさんもブログにまとめていただいてます。

ISUCON5に「京都スイーツnext」で参加してきました

 

 

ISUCON5に「京都スイーツnext」で参加してきました

同僚のishinoと2名でisucon5に参加してきました。

僕はISUCON1の時から参加してるので、今のところ皆勤賞です。
毎年楽しみにしているイベントで今年もすごく楽しかったです。
運営の皆さま、本当にありがとうございました。

結果はスコア、13094。使用言語はPHPです。

しかし本戦出場ならず、、、

「ISUCON5 本選出場者決定のお知らせ」
http://isucon.net/archives/45532743.html

残念。おしかったな~

事前準備

今回、いつも一緒に参加しているスーパープログラマがいなかったので
いつも丸投げしていたアプリ周りの修正に不安を感じていました。
ですので普段業務で一番使っている「PHPを使う」という事にしました。

使った事のなかったGCPの練習もかねて、
Isucon4の問題のイメージが提供されていましたので、起動して
PHP実装を眺めてたりしました。

GCP、すごく使いやすいのですが、インスタンスへのSSHログインにGCP専用のツールみたいなのが必要なのが嫌で
練習中も本番中も ParmitRootLoginはYesだったりパスワード認証許可したりして
ターミナルから直接SSHできるようにしてました。

当日

前日に会社で「キャンプ」が行われて、深夜まで雑談したりで疲れ切ったのちの参加。
ほんと直前までキャンプ場にいましてバタバタしてました。
ですが、アウトドアでIT関連の事から離れた状態でしたので、逆にすっきりした気持ちで参加できたかも。

本戦開始

イメージデータの共有がきたので、ひとまずインスタンスを起動し、
何も触ってない状態でベンチマークをリクエストしました。
が!ベンチが通らない!!(Fail)

え。初期で通らない実装なの?
みたいな感じでプチパニックになりました。

このとき、ベンチからのリクエストが届いてるか、などを確認すればよかったのですが、
GCPの設定がおかしいのか?と無駄に時間を使ってしまいました。

初期で通ってた人もいたようですが、僕らは一度も通らなかったのでいまだに原因ふめい。なんでだろう。
ですが、ログインがめちゃくちゃ重かったり、スコアが80とかから300くらいの人もいたので、
「きっと初期の実装の時点で重すぎてベンチ通らないに違いない」、と結論付けて
PHPへの切り替え作業をしました

systemd

もちろん使った事なかったので、PHPへの切り替えでも時間がかかりました。
PHPのnginx.confは静的ファイルの配信があらかじめnginxからになっててらっくちーん。
もちろんPHPに変えてもいまだベンチは通らない。
でも画面は表示されているのでとりあえず、チューニング開始

チューニング開始

ひとまず、ベンチが通らないと心が不安でいっぱいだったので
簡単に修正できる部分をとりあえずやってみましょう、となりました。

ささっと見てログインの部分でハッシュにしたりしてるのが簡単そうだったので、
パスワード部分に平文を入れちゃってベンチ。
これでようやくスコアが出るようになってた気がします。

ひたすらSQLを書く

・N+1問題
・commentsテーブルにAlterでカラム追加。(30分以上かかった)
・relationsのデータが必ず2つ1組みで入ってたのでselectをoneだけにする
・ORDER BYのcreated_atをidにしてCreated_atのindex消す
・footprintsのgroup byの部分を修正

ほっとんどの時間を/のSQL改修に充てててました。
ミドルウェアの設定はAlterの実行中に設定などを確認、修正をしたくらいです。
(若干my.cnfにははまりました)

結局、ボトルネックmysqlで改修できる部分もまだまだ残したままフィニッシュ
となりました。

全体的に

今回のお題がほんとに楽しく感じました。

・DBのデータが非常に多く複雑なので全メモリ化は実質不可能。
・ログイン処理があり、ログインによって表示される情報が異なるので、フロント側でのキャッシュは難しい(あまりキャッシュヒットしなさそう)
・実際にありがちな「小規模なときはよかったけど、サービスが成長してから問題が出始めた」みたいなリアルな感じ

というところが特に楽しかったです。

あとは例年どうり、新しい事をいろいろ知れてよかったです。
systemdは見ないふりしてたんですが、やっぱり少し触ると、「いいなこれ」ってなりますね。

今年も楽しかったです。
ありがとうございました!

Windows 10にしたら Macからリモートデスクトップが繋がらなくなった

こんにちは、はらぐちです。

最近までWindouwsのパソコンを起動すると、デスクトップ画面右下のインジケーターに
「Windows10を入手する」というボタンが表示されるようになっていましたが、皆さんご存知でしょうか?
これは、今年7月にリリースされた、Windows10への無料アップグレードを予約できるというもので、
Windows利用者の間で話題になっています。

私もこの機会にアップグレードしてみたのですが、その際Remote Desktop Client for Macを使った
リモートデスクトップが使用できなくなってしまったので、その時のお話しをします。

具体的には、Windows10にしてから「接続先のコンピューターのIDを確認できません。」
というエラーが出て繋がらなくなりました。
Windows8Windows Server 2012でも同様の現象となる、との事。

AppStoreにある Microsoft リモート デスクトップというアプリだと問題ないのですが、
こちらはキーボードのキーバインドが個人的に気に入らないので、
Remote Desktop Client for Macを使い続けたいと思っているので、調べてみることにしました。

結果、以下のようにすると接続できるようになりました。

検索で "gpedit.msc" を入力し、以下のように設定を変更します:
ローカルコンピュータポリシー
コンピュータの構成
管理用テンプレート
Windows コンポーネント
リモートデスクトップサービス
リモートデスクトップセッションホスト
セキュリティ
リモート(RDP)接続に特定のセキュリティレイヤーの使用を必要とする: 有効
オプションパネルで、セキュリティレイヤーを "RDP" に変更する
リモート接続にネットワークレベル認証を使用したユーザー認証を必要とする: 無効
再起動

(参考)
http://zakkied.hatenablog.com/entry/2013/09/30/132342

具体的にどのような作業なのかよくわかっていないのですが、ローカル内で使いたいだけなのでOKとしました。

なにかの参考になれば幸いです。

読み込みのタイミング

こんにちは、永井です。

最近はなかなか多忙な日々を送っており、業務で手一杯になってしまうので
何か+αできるように頑張っていきたいと思います。

さて今回は、業務中に困ったことがあったので、それについて書きたいと思います。

追従メニューが最後まで動きません

javascriptで画面スクロールに追従するメニューを設置したのですが、
意図しない中途半端な位置で追従が止まるという挙動になり困りました。

原因

意図しない誤動作の原因とは、ウィンドウの高さの取得などを行い、
追従のプログラムを組んだのですが、その際に値が正しく取得できていなかったためでした。
なぜ正しく取得できなかったかというと、ページ内のコンテンツに画像が複数設定されており、
その画像の高さが定義されておらず、その影響でウィンドウの高さが正しく取得できなかったようです。

解決策

結果から述べますと、”読み込みのタイミング”を変えることで解決できました。
最初はjQueryのお約束の

$(function(){
ここにプログラムを書き書き...
});

としていたところを

$(window).load(function(){
こっちにプログラムを書き書き...
});

と読み込みのタイミングを変えることで、キチンと最後まで追従するようになりました。

$(function(){})と$(window).load(function(){})の違い

正直なところよくわかっておらず、どちらもそこまで違いがないものと思い込んでおりました。
そこでGoogle先生にご相談したところ、ざっくり述べると、

$(function(){})は、HTMLの構築が完了した時点で処理を実行する。
$(window).load(function(){})は、HTMLの構築だけでなく、画像やFlashなどのデータの読み込みが完了してから処理を実行する。

だそうで、$(window).load(function(){})内ににプログラムを書くことで、コンテンツ内の画像データも含めて
ウィンドウの高さなどを取得することができるようになり、解決につながりました。

注意点

ただし、$(window).load(function(){})には注意すべき点があります。
それは、”画像やFlashなどのデータの読み込みが完了してから”なので、使用箇所、使用機能によっては
ユーザーは反応が遅く感じてしまうことがあると思われるので、
その辺りは、実際にテストを行い考慮していく必要がありそうです。

まとめ

普段は気にせず$(function(){})内に書き込んでいましたが、プログラムによっては
読み込みのタイミングを考慮する必要があるとわかりました。
また、できたから良いのではなく、機能の反応のユーザー体験(ユーザーエクスペリエンス)を
考えるということも大事なのだと思いました。

td-agentにてAWSのRDS(postgres)のログをTDに送信

AWSのRDSはLinuxサーバではない為、こちらからいろいろな設定ができません。

その為、どのようにPostgresのログを送信すればよいか、いろいろ試行錯誤したのでその備忘録です。
前提として、RDSに接続できるLinuxインスタンスにtd-agentが入っている状態が必要です。

fluent-plugin-rds-pgsql-log

https://github.com/shinsaka/fluent-plugin-rds-pgsql-log
RDSのpostgresのログを取得するには上記のプラグインを利用します。

このプラグインはAWS RDSのログを取得し、td-agentのsourceとして利用できるようにするプラグインです。

ただ導入にあたり、依存関係に「AWS SDK」があるのですが、パッケージで導入したtd-agentでは
fluentd-gem fluent-plugin-rds-pgsql-log にて導入ができませんので、以下のように導入します。

まず、td-agentに入っているrubyからaws-sdkをインストール

/usr/lib64/fluent/ruby/bin/gem install aws-sdk

fluent-plugin-rds-pgsql-logのプラグインを直接プラグインディレクトリにほおりこむ

wget https://raw.githubusercontent.com/shinsaka/fluent-plugin-rds-pgsql-log/master/lib/fluent/plugin/in_rds_pgsql_log.rb -P /etc/td-agent/plugin

これでpostgresのログをTDに送信できました。

<match td.postgres.log>
type tdlog
apikey *****************************
auto_create_table
database postgres
table log
buffer_type file
buffer_path /var/log/td-agent/buffer/td
flush_interval 180s
</match>
<source>
  type rds_pgsql_log
  region ap-northeast-1
  db_instance_identifier prod-auth
  access_key_id ******************
  secret_access_key *********************************
  refresh_interval  30
  tag td.postgres.log
  pos_file /var/log/td-agent/pgsql-prod-auth-log-pos.dat
</source>

こんな感じのデータが送信されます

{"message_level"=>"LOG", "time"=>"1436510427", "ident"=>"postgres", "host"=>"10.0.0.21(22112)", "database"=>"[unknown]", "user"=>"[unknown]", "pid"=>"6080", "log_file_name"=>"error/postgresql.log.2015-07-10-00", "message"=>"  connection received: host=10.0.0.21 port=53253"}

host部分がSQL発行元IPになる

管理の上ではhost部分はRDSの名前になっているのが望ましいので、host部分を強制的に変更します。
データをリフォームする為に「fluent-plugin-record-reformer」というプラグインを利用しました。

https://github.com/sonots/fluent-plugin-record-reformer

wget https://raw.githubusercontent.com/sonots/fluent-plugin-record-reformer/master/lib/fluent/plugin/out_record_reformer.rb -P /etc/td-agent/plugin

最終的なtd-agent.confは以下のようになりました。

<match td.postgres.log>
type record_reformer
renew_record false
enable_ruby false
tag reformed.td.postgres.log
# 強制的に文言を変更する
host rds-postgres01
ident postgres
</match>
<match reformed.td.postgres.log>
  type tdlog
  apikey *****************************
  auto_create_table
  database postgres
  table log
  buffer_type file
  buffer_path /var/log/td-agent/buffer/td
flush_interval 180s
</match>
<source>
  type rds_pgsql_log
  region ap-northeast-1
  db_instance_identifier prod-auth
  access_key_id ******************
  secret_access_key *********************************
  refresh_interval  30
  tag td.postgres.log
  pos_file /var/log/td-agent/pgsql-prod-auth-log-pos.dat
</source>

© SEEDS Co.,Ltd.