Varnishについて

今週FastlyのStockholm(BMA)で障害が発生1し、私たちのサイトも影響を受けました。その際出てきた「varnish」というミドルウェアについて調べたときのメモです。

Varnishとは

github.com

Varnish Cache is a web application accelerator also known as a caching HTTP reverse proxy.

Introduction to Varnish

  • HTTPレベルでキャッシュを行うHTTPアクセラレータ。
  • カーネルの機能を最大限利用することで高速化を図っている。
  • ディスクへのデータ書き込みをデフォルトでは一切しないので、プロセス終了時に全てのキャッシュが消える。
  • 設定はVCL(Varnish Configuration Language)というDSLで記述する。動的に変更可能。
  • ログもデフォルトではファイルに書き込まれない。
  • Fastlyの中心技術2。各リージョンにVarnishキャッシュサーバを置いていると雑に考えても間違いではなさそう。
  • SSLが使えないのでnginxを前に置く構成が多いらしい。

動かしてみる

varnishをnginxの手前に置いて、nginxのindex.htmlをvarnish経由で返してみる。

参考記事: Getting Started with Varnish Cache

環境

1. コンテナの起動 3

$ docker run --privileged -d -p80:80 --name=varnish centos /sbin/init

2. nginxのインストール&起動 4

$ sudo vi /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
gpgcheck=0
enabled=1
$ yum install -y nginx
$ systemctl start nginx

3. Varnish Cashのインストール

$ yum install -y epel-release
$ yum install -y varnish

4. nginxのポートを8080に変更

etc/nginx/conf.d/default.conf

server {
    listen       8080;

    ...
}

リロード

$ systemctl reload nginx

5. varnishのポートを80に変更

etc/varnish/varnish.params

VARNISH_LISTEN_PORT=80

起動

$ systemctl start varnish

6. アクセスしてみる

$ curl -I http://localhost
HTTP/1.1 200 OK
Server: nginx/1.13.6
Date: Sun, 19 Nov 2017 10:46:05 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 10 Oct 2017 15:59:40 GMT
ETag: "59dcee6c-264"
X-Varnish: 22 20
Age: 3
Via: 1.1 varnish-v4
Connection: keep-alive

2回目アクセス以降X-Varnishの値が2つ返っていればキャッシュされている5

また、nginxのアクセスログに2回目以降のアクセスログが残らないことも確認できた。(キャッシュ間隔のデフォルトは5分。)

疑問

  • (リバースプロキシとしている)nginxでも同じことができるのではないか。
    • わざわざnginxの後ろにVarnishを置く理由。

参考

JSON-RPCについて

JSON-RPCについて調べた際のメモです。

特徴

JSON-RPC is a stateless, light-weight remote procedure call (RPC) protocol.

JSON-RPC 2.0 Specification

  • データのエンコードJSONを利用したRPC(Remote Procedure Call)1プロトコルの一種。
  • レスポンスを期待しない「通知」、複数の呼び出しを一度に行う「Batch」が可能。
  • リクエスト、レスポンスのjsonに含めるべきフィールドが決められており(プロトコルなので)、それを満たしさえすればよい。
  • HTTPメソッドは全てPOSTとするのが通例。

リクエス

以下、例は主にJSON-RPC 2.0 Specificationから拝借いたしました。

  • jsonrpc [string]: JSON-RPCのバージョン(現在2.0)
  • method [string]: 呼び出したいメソッド名
  • params [array|object]: メソッドの引数(単純に列挙する場合はarray、ラベルを使う場合はobject)
  • id [string|int]: リクエストを識別するID、レスポンスに同じ値が含まれる、よってBatch(後述)で送ってもどのリクエストに対するレスポンスかを識別できる
{
  "jsonrpc": "2.0",
  "method": "subtract",
  "params": [42, 23],
  "id": 1
}

ラベル付き

{
  "jsonrpc": "2.0",
  "method": "subtract",
  "params": {
    "subtrahend": 23,
    "minuend": 42
  },
  "id": 3
}

レスポンス

成功時:

  • jsonrpc [string]: JSON-RPCのバージョン
  • result [object]: 成功時のデータ、特にフォーマットの指定はない
  • id [string|int]: リクエストID

失敗時:

  • jsonrpc [string]: JSON-RPCのバージョン
  • error [object]: 失敗時のデータ、フォーマットは以下の通り
  • id [string|int]: リクエストID

errorのフォーマット

  • code [int]: エラーコード、あらかじめ定義されている → error object
  • message [string]: エラーメッセージ
  • data [any]: 追加情報用のフィールド、型の指定もなく、省略も可能

成功時:

{
  "jsonrpc": "2.0",
  "result": 19,
  "id": 1
}

失敗時:

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32601,
    "message": "Method not found"
  },
  "id": "1"
}

通知

リクエスト時にIDフィールドを省略すると、レスポンスを期待しないと解釈され、何も返ってこない。これを「通知」と呼んでいる。

{
  "jsonrpc": "2.0",
  "method": "update",
  "params": [1,2,3,4,5]
}

Batch

トップレベルを配列にし、リクエストを複数一気に送ることができる。

リクエスト:

[
  {"jsonrpc": "2.0", "method": "sum", "params": [1,2,4], "id": "1"},
  {"jsonrpc": "2.0", "method": "notify_hello", "params": [7]},
  {"jsonrpc": "2.0", "method": "subtract", "params": [42,23], "id": "2"},
  {"foo": "boo"},
  {"jsonrpc": "2.0", "method": "foo.get", "params": {"name": "myself"}, "id": "5"},
  {"jsonrpc": "2.0", "method": "get_data", "id": "9"} 
]

レスポンス:

[
  {"jsonrpc": "2.0", "result": 7, "id": "1"},
  {"jsonrpc": "2.0", "result": 19, "id": "2"},
  {"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request"}, "id": null},
  {"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found"}, "id": "5"},
  {"jsonrpc": "2.0", "result": ["hello", 5], "id": "9"}
]

GoでJSON-RPCを扱う代表的なパッケージは以下の3つ

【思ったより手間取っているので追記予定】

疑問

  • JSON-RPCを使う理由
    • URL設計が鍵になるRestAPIとメソッド設計が鍵になるJSON-RPCだと大分性格が違うと感じたが、どのケースはRestAPI向きでどのケースはJSON-RPC向きなのか
  • 一般的なidの割り振り方

参考


  1. RPCの例 wiki

ISUCONカンニングペーパー

【10/23追記】 f:id:KK462:20171024034517p:plain

残念ながら本選に出場することはできませんでした。

インデックス貼ったりN+1を直したりはできたのでせめて最後にスコアを残したかったと後悔しています。

とはいえ8時間があっという間に感じるくらい楽しかったです。 夜中の2時のサイクリングも最高にエキサイティングでした。

準備不足につきます。 来年こそは本選出場できるように頑張ります。


サーバーの状態確認コマンド群

pstree
ps auxwf
top
htop
dstat -ta
glances

ユーザーの追加

adduser username
usermod -aG sudo username

git

git init
git add .
git commit -m "first commit"

ファイルの転送

remote → local

# file
scp your_username@remotehost.edu:foobar.txt /some/local/directory
# directory
scp -r your_username@remotehost.edu:/some/remote/directory/foo bar

local → remote

# file
scp foobar.txt your_username@remotehost.edu:/some/remote/directory
# directory
scp -r foo your_username@remotehost.edu:/some/remote/directory

ディレクトリのときは

local$ tar -czvf local.tar directory/
local$ scp local.tar user@remote:/directory
ssh user@remote
remote$ tar -xzvf local.tar

がよい。

言語の切り替え

systemdに登録されたサービスは /etc/systemd/system/ 以下。

sudo -s
systemctl stop XXX
systemctl start YYY
journalctl -f

netdata の設定

bash <(curl -Ss https://my-netdata.io/kickstart-static64.sh)

して <host>:19999 にアクセス。

alp の設定

1.Releases · tkuchiki/alp · GitHub で最新版を確認する

2.インストール

wget https://github.com/tkuchiki/alp/releases/download/v0.3.1/alp_linux_amd64.zip
unzip alp_linux_amd64.zip
sudo install ./alp /usr/local/bin

3.access.log の設定 /etc/nginx/nginx.conf を以下のように修正

...

http {
    log_format ltsv "time:$time_local"
                "\thost:$remote_addr"
                "\tforwardedfor:$http_x_forwarded_for"
                "\treq:$request"
                "\tstatus:$status"
                "\tmethod:$request_method"
                "\turi:$request_uri"
                "\tsize:$body_bytes_sent"
                "\treferer:$http_referer"
                "\tua:$http_user_agent"
                "\treqtime:$request_time"
                "\tcache:$upstream_http_x_cache"
                "\truntime:$upstream_http_x_runtime"
                "\tapptime:$upstream_response_time"
                "\tvhost:$host";
    access_log /var/log/nginx/access.log ltsv;
}

...

4.再起動

rm /var/log/nginx/access.log && systemctl reload nginx

5.実行

alp --sum -r -f /var/log/nginx/access.log --aggregates='/keyword/.*'

slow query

1.my.conf の設定

以下を追記

[mysqld]
...
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 0

2.mysql、アプリの再起動

systemctl restart mysql
systemctl restart XXX

3.percona-toolkit のインストール (Debian8: jessie)

wget https://www.percona.com/downloads/percona-toolkit/3.0.3/binary/debian/jessie/x86_64/percona-toolkit_3.0.3-1.jessie_amd64.deb
apt install libdbd-mysql-perl libdbi-perl libio-socket-ssl-perl libnet-ssleay-perl libterm-readkey-perl
dpkg -i percona-toolkit_3.0.3-1.jessie_amd64.deb

4.解析

pt-query-digest --limit 10 /var/log/mysql/slow.log

再起動用のスクリプト

#!/bin/sh
set -e

now=`date +%Y%m%d-%H%M%S`
mv /var/log/nginx/access.log /var/log/nginx/access.log.$now
systemctl reload nginx

mv /var/log/mysql/slow.log /var/log/mysql/slow.log.$now
mysqladmin -uisucon -pisucon flush-logs

systemctl restart XXX

journalctl -f

静的データのnginxでの配信

location / {} の前に、

location ^/(img|css|js|favicon.ico) {
    root /path/to/static/files;
}

my.cnf

innodb_buffer_pool_size = 1G
innodb_flush_log_at_trx_commit = 0
innodb_flush_method=O_DIRECT

nginx.conf

とりあえず、

# Worker connections
events {
    worker_connections XXX;
    use epoll;
    multi_accept on;
}

http {
    ...

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    etag off;

    ...
}

worker_connections = ulimit -n

あとは How to Configure nginx for Optimized Performance

autostart (with sysetmd)

check

systemctl is-enabled <SERVICE_NAME>

enable

systemctl enable <SERVICE_NAME>

参照


雑記

  • systemctl restartsystemctl reload の違い

reload: Unitに対して設定ファイルの再読み込みを促す。(対象のUnitがreload動作に対応している必要がある)

restart: 起動中のUnitを停止後、起動(stop -> start)する。対象のUnitが停止中である場合、起動操作のみ実施する。

「Systemd」を理解する ーシステム管理編ー | ギークを目指して

【メモ】Redisについて

Redisについての雑多なメモです。

特徴

Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker.

Redis

  • Key-Valueストレージで、NoSQLに分類される
  • そういう文脈上キャッシュというよりはデータストレージ
  • 最大の特徴は構造を持つデータ(リストやオブジェクト)をそのまま保存できること
  • パフォーマンスはmemcachedremarkably similarらしい
  • データは定期的にディスクに保存されるためサーバが落ちてもデータが残るし、再起動時にはロードされる
  • データのサイズに制限はないが、全体サイズがメモリ容量に収まる必要がある、あるいは削除の設定をする必要がある

導入

// ダウンロード
$ wget http://download.redis.io/redis-stable.tar.gz
$ tar xzf redis-stable.tar.gz
$ cd redis-stable
// ビルド
$ make

// 起動
$ src/redis-server

PHPでの利用方法

PHPでRedisを利用する際は、以下の2つがメジャー。

どちらのクライアントも基本的にRedisのコマンド名と同じメソッドが定義されているので利用法に大きな差異はないが導入方法が異なる。また、phpredisはextensionなのでpredisよりも高速で動作することが予想される。

predis

ライブラリなのでcomposer経由でインストール。

{
    "require": {
        "predis/predis": "^1.1.1"
    }
}

アプリケーション側からは以下のように利用する。

<?php
require __DIR__ . '/../vendor/autoload.php';

use Predis\Client as PredisClient;

try {
  $redis = new PredisClient();
} catch (Exception $e) {
  die($e->getMessage());
}

// 値の設定
$redis->set('message', 'Hello world');
// 値の取得
$value = $redis->get('message');

print($value); // Hello world

phpredis

こちらはextensionとなっているので、

ダウンロード & ビルド → php.iniにモジュールの登録

の手順を踏む必要がある。

  • ダウンロード & ビルド
$ git clone git://github.com/nicolasff/phpredis.git
$ cd phpredis
$ phpize // エクステンションを追加する際に,phpを最初からコンパイルし直す必要なく,追加するためのコマンド(*)
$ ./configure
$ make && make install

(*) Redisの使い方

  • モジュールの登録

ビルドされたredis.soというファイルをphpのextensionが入っているディレクトリにコピーし、php.iniに登録する。

$ cp modules/redis.so {php-config–extension-dir}
$ sudo echo “extension=redis.so”  > /etc/php5/conf.d/redis.ini

アプリケーション側からは以下のように利用する。

<?php
$redis = new Redis(); // extensionとして登録しているからロードせず使える
$redis->connect('127.0.0.1',6379);

$redis->set('dog', 'bow-bow');
$res = $redis->get('dog');
echo $res . PHP_EOL;

$redis->close();

気になる点

  • 導入するタイミングはいつなのか
  • 結局memcachedとどっちがいいのか
    • データ構造が保存できるとはいえmemcachedシリアライズの方法、共通の実装が揃えば使い勝手は一緒な気がする。

参考

【2016】読書リスト

年の瀬を感じる今日この頃。
備忘録を兼ねて、2016年に読んだ技術書・参考書を一覧にまとめました。

参考にしたサイト

読む本は主に以下の二つのQiitaエントリーを参考にしています。

qiita.com

qiita.com

エントリの筆者の二人に感謝申し上げます🙇

2016読書リスト(計:45冊)

※読んだ順序はこの通りではありません。

  1. リーダブルコード

  2. インフラエンジニアの教科書

  3. UI Graphics - 世界の成功事例から学ぶ、スマホ以降のインターフェイスデザイン

  4. ハッカーと画家

  5. TEAM GEEK

  6. アジャイルサムライ

  7. 伽藍とバザール

  8. マスタリングTCP/IP 入門編

  9. ネットワークエンジニアの教科書

  10. Unixという考え方

  11. Unix考古学

  12. プログラミングHaskell

  13. Core Image for Swift

  14. エリックエヴァンスのドメイン駆動開発

  15. 人月の神話

  16. ソフトスキルズ

  17. アルゴリズムの基本

  18. 暗号技術入門 秘密の国のアリス

  19. デザインのルール、レイアウトのセオリー。

  20. タイポグラフィーの基本ルール

  21. iPhone Core Audioプログラミング

  22. プロトタイピング実践ガイド

  23. はじめて学ぶUML

  24. 独習UML

  25. Arduinoをはじめよう

  26. プログラミングの基礎

  27. functional swift

  28. すごいHaskellたのしく学ぼう

  29. Kotlinスタートブック -新しいAndroidプログラミング

  30. プログラミングErlang

  31. いまから始めるWebフロントエンド開発

  32. 詳細!PHP7+MySQL入門ノート

  33. いちばんやさしいWordPressの教本

  34. プログラマのためのDocker教科書 インフラの基礎知識&コードによる環境構築の自動化

  35. サイトの拡張性を飛躍的に高めるWordPressプラグイン開発のバイブル

  36. みんなのPython 第3版

  37. 一歩先にいく WordPressのカスタマイズがわかる本

  38. Flask Web Development

  39. MySQL徹底入門

  40. よくわかるHTML5+CSS3の教科書

  41. よくわかるJavaScriptの教科書

  42. Learning JavaScript

  43. パーフェクトPHP

  44. シングルページWebアプリケーション

  45. nginx 実践入門

  46. Swift Internal Introduces

  47. SWIFT ALGORITHMS & DATA STRUCTURES

  48. Web API: The Good Parts

  49. コンピュータの構成と設計 第5版 上

振り返り

振り返ってみると前半の方は「え、これ読んだの今年!?」っていうくらい昔のことに感じます。

中にはあまり面白くなかったもの、ちゃんと理解できなかったものもありますが、
数多くの好奇心刺激する本に出会えて楽しかったです。
幅広い知識に触れることができた一方、どれも実用レベルでないのは残念なところです。
結局手を動かさないと使える知識にならないんだなと実感しました。

来年は

本を選ぶ上で特に戦略は持っておらず、興味の向くままに選んでいます。
戦略があった方がいい気もするし、このスタンスに特に自信があるわけではありませんが、
来年もこのスタイルで読む本を選んでいきたいと思います。
みなさんどのように本を選んでいるのでしょうか。

来年は実務で使う技術に加え、

などに挑戦したいなーと思います。
オススメの書籍、書籍を紹介しているサイト等あれば是非是非教えてください🙇

FrenchKit

先週末9/23,24にフランスのパリで行われたFrenchKitに参加して来ました。

f:id:KK462:20161002174855j:plain

2日間のうち1日目の23日はトークのみ、2日目24日はライブコーディング及びクラスルーム、クロージングというコンテンツでした。

コンテンツ

f:id:KK462:20161002175055j:plain

全てを見つけることはできませんでした。。(Realmで公開されるのかな?)

【LT】Human Engineering

スピーカー:Jeremie Giraultさん(@kamidude)
github.com

Designing Pro Apps

スピーカー:Piet Brauerさん(@pietbrauer)
speakerdeck.com
github.com

【LT】Building your UI Developer's Toolbox with Playground

スピーカー:Hugues Bernet-Rollandeさん(@rompelstilchen)
speakerdeck.com
github.com

Reactive Programming with RxSwift

スピーカー:Florent Piletさん(@fpillet)

www.slideshare.net

Mixins vs Inheritance

スピーカー:Olivier Haligonさん(@aligatr)
speakerdeck.com

【LT】Swift script all the things!

スピーカー:Roy Marmelsteinさん(@marmelroy)
github.com (未更新ですが、後々更新されることと思います。)

Swift Evolution - 140 proposals in 30 minutes

スピーカー:Jesse Squiresさん(@jesse_squires)
speakerdeck.com
github.com

Optimizing Your App's Performance - How to Do It Right

スピーカー:Bruno Virletさん(@bvirlet)

【LT】Swift Package Manager

スピーカー:JC Pastantさん

Core Data - it's not dead yet

スピーカー:Abizer Nasirさん(@abizern)
speakerdeck.com

End-To-End Application Development with Swift

スピーカー:Chris Baileyさん(@Chris__Bailey)

An Overview of Verification Techniques Today

スピーカー:Fabrice Kordonさん(@fabricekordon)

Extending Xcode

スピーカー:Boris Buglingさん(@neonacho)

Launch Arguments: the Mysteries

スピーカー:Marin Usaljさん(@_supermarin)

Live Streaming Swift Talk

スピーカー:Chris Eidofさん(@chriseidhof)&Florian Kuglerさん
SortDescriptorの話。(関連:http://chris.eidhof.nl/post/sort-descriptors-in-swift/)

MVC Supercharged

スピーカー:Grégoire Lhotellierさん(@greg3z)&Jéremie Giraultさん(@kamidude)
github.com

Classroom

各ブースに分かれてのハンズオンでした。 ソースコードこちら

  • RxSwift Hands-on(Florent Pilletさん@fpillet)
  • Core Data Hands-on(Abizer Nasirさん@abizern)
  • Introduction to Bluetooth LE and IoT(Hugues Bernet-Rollandeさん@rompelstilchen)
  • DTrace: Beyond Instruments(Frank Lefebvreさん)
  • Accessibility for iOS Applications: the Main APIs, the Best Practices and Beyond the Technique(Amadou Amath Ndiayeさん)
  • Reactive Programming with Realm(Marius Rackwitzさん)
  • Server-Side Swift Hands-on(Chris Baileyさん@Chris__Bailey)

How to Become an iOS Full-stack Developer in Just 60 Minutes

ゲーム大会with🍷&🧀

食事

初日朝 f:id:KK462:20161002175230j:plain

初日昼 f:id:KK462:20161002175255j:plain

初日夜 f:id:KK462:20161002175312j:plain f:id:KK462:20161002175334j:plain

2日目🍷&🧀 f:id:KK462:20161002175412j:plain f:id:KK462:20161002175427j:plain

おすすめトーク

Designing Pro Apps
git2goを作ったpietさんによるiPad Proを開発機として使うお話。
Playgroundも使えるようになったし、休日に作業したい時とかアリかも。
そのほかいいiPad Proアプリの作り方など。

Swift Evolution - 140 proposals in 30 minutes
try!swiftでもお話しされたJesseさんによるSwiftEvolutionのプロポーザルを解析されたお話。
Q&Aの「Erica Sadunさんは実在するんですか?」がウケてた。

[Optimizing Your App's Performance - How to Do It Right]
画像のフィルタリングを最適化する話。
標準のAPIからCを経てアセンブリ言語まで。結果は、アセンブリまで最適化する必要はないそう。
最近命令セットなどを学んだのでタイムリーで面白かった。

[End-To-End Application Development with Swift]
IBMのChrisさんによるSwiftをサーバーとモバイル両方で使うメリットについてのお話。
前日にKitura1.0がリリースされており、"Server side Swift is getting real"だそうです。

感想

  • トーク後の司会役含めた3人でのセッションが面白かった。(Q&A含む)
  • 会話の多くはフランス語で行われており、現地の方が多かった様子。
  • 男女比は9:1くらいで、パリでもそうなんだなあと。

カンファレンスを口実に海外に行くのは充実した旅行ができるのでオススメです😄。

ブログ等

www.jessesquires.com

2015-2016書籍目録

去年の5月にキャリアスタートしたエンジニア2年生です。
備忘録を兼ねて、一年間で読んだ書籍を赤裸々に列挙したいと思います。
気づけば7月も後半で、タイミングは謎ですがご容赦ください🙇

iOSObjective-C・Swift

インフラ・ネットワーク

Haskell

データベース

Git

UNIX

デザイン

プロジェクト

一般

おわりに

2016-2017はとりあえずこれ以上の冊数読めるよう精進いたします。
おすすめの本ありましたら是非教えてください。

メモ