LoginSignup
22
21

More than 5 years have passed since last update.

マイクロサービス作成時におこなった負荷対策

Last updated at Posted at 2016-07-04

マイクロサービスをつくった。
一からマイクロサービスの開発フローを作った話

そこで、実際にどのように開発していたかを共有する。

今回は
- テスト
- ドキュメント作成
- エラー/負荷対策、負荷テスト (←今回はここ)

今回は負荷対策に関して。
開発するときにどのような点に気をつけて、
どのようにテストしたかを書く。

前提として、過去の開発で負荷が起こるのって以下のどれかだった。
どれも起こらないようにするために、どういう開発にしたか、というのを書く。

負荷対策

負荷が大きくなる原因

基本的にサーバ負荷はよほどループを挟んだり、メモリリークがなければ、なんとかなることが多い。
サーバのループ数に関しては、コードチェック時に確認しているので、大きな問題は起こらないだろうと予想。

これまでの負荷による障害は、多くの場合はDBが原因。
DBの中でも、以下のパターンが多い。

  • 走査するデータの量が大きい
    • INDEXを貼られていないデータを検索している
    • パーティションが適切に設定されていない
  • 実行するクエリが多い
    • キャッシュが効果的に利用されていない

負荷対策のため開発で確認するログ

indexをはられていないクエリの確認

INDEXがはられていないカラムで検索された場合、
SLOW QUERYとして出力されるようにする。

[mysqld]
long_query_time=1
log-queries-not-using-indexes
log-slow-queries=/var/log/mysql/log-slow-queries.log

実行されたクエリの確認

同じクエリを複数回走らせていないかを確認する。
同じクエリを走らせている場合は、キャッシュを利用する。

log=/var/log/mysql/query.log

その他TIPS

以下の場合はindexが利用できないので、それぞれ別の解決方法を用意する。

offsetを利用したい

offsetを使うと、一度全件取得を行うので、直接利用しない。
offsetを使う場合、インクリメンタルなIDなどの場合は、IDを引数として、そのIDからn件取得という形にする。

<before>
SELECT * FROM account WHERE status = "valid" LIMIT 10 OFFSET 10;

<after>
SELECT * FROM account WHERE status = "valid" AND id > 10 LIMIT 10

rand()は直接使用しない

randで、indexがはられていないカラムを取得しようとすると、indexが利用できない。
面倒だが、indexが効いているカラムを指定してprimary keyを取得し、そこから値を取得する。

<before>
SELECT * FROM account ORDER BY RAND() limit 0,20;

<after>
SELECT * FROM account,
(SELECT id FROM account ORDER BY RAND() LIMIT 0,20) AS random
WHERE account.id = random.id LIMIT 0,20;

負荷テスト

以前利用したものでJMeterがあったが、ユーザシナリオを書くのが面倒で、これはエンジニアの仕事なのか、と思った。

今回はせっかくCucumberを使ってAPIを呼び出せるようにして、全機能のテストもできるようになっていたので、それを利用して負荷テストを行った。
時間がなかったから、というのが最も大きい理由の一つ。

負荷テストの手順

わざわざ書くほどのものではないが、以下のとおり。

  1. 本番サーバを用意。当たり前だが、本番とまったく同じ性能にしなければ意味がない。
  2. 負荷テスト用サーバを複数台用意 ※ 本番サーバよりいいものを用意
  3. 負荷テスト用の全サーバから、本番サーバに向けてcucumberを並列実行
  4. 本番サーバの負荷状況などは、Amazon Cloud Watchなどを使ってみる。

その他システム側でできそうなこと

今回、データ設計/コードを書く際に、以下のルールを設けた。
- foreign keyを利用しない
- JOIN句を利用しない

これはDBを垂直分割する際に、移行をスムーズにするため。

エラー対策

エラー対策はテストコードをしっかり書くこと。

またエラーが発生し、それが致命的なエラーだった場合は、
指定のメールリストにメールが届くようにした。
メールリストには関係者全員が入っており、エンジニア以外にも送信する。

メールの内容

調査時に、必要最低限となる情報を入れている。

エラーが発生しました。

Server : https://api.sampleerror.com

Endpoint : /v1/sample/endpoint

IP : xxx.xxx.xxx.xxx

Time: 2016-07-02 13:03:21

Msg : Call to a member function set() on a non-object

File: /home/ec2-user/projects/sample-api/src/Account.php

Line: 114

今後は、致命的ではないエラーに対しても、エラーの種類ごとに分類して、1日に1回まとめてメールを送付するようにしたい。

22
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
21