ずいぶん時間が空いてしまったが、

MariaDBのHAで続きが出来たので、

記載します。

 

前回、負荷試験前でありましたが、

諸々実施後、以下の問題点が出てきました。

  • 秒間300コミットを超えると、slaveが遅延する
  • slave遅延により、Semiレプリケーションが外れる

 

秒間300コミット以上の場合は、

slave側で、innodb_flush_log_at_trx_commitを2にしないと追いつけなくなる。

これで秒間600コミットくらいまで耐えれるが、それ以上である場合、0にしないとダメであった。

同時に、Semiレプリケーションが外れて、通常レプリケーションとなると、

レプリケーションによるfailoverでのロスト率が高まってしまうため、

rpl_semi_sync_master_timeoutを1500ミリ秒に設定した。

同時に、slaveのデータ保全性を高めるため、

rpl_semi_sync_master_wait_pointにAFTER_SYNCを設定した(いわゆるロスレスレプリケーション)。

さらに、slaveの更新性能をアップするため、

  • slave_parallel_threads

というMariaDB特有のパラメータを設定した。

slave_parallel_threadsの特徴は、MariaDBではグループコミットという機能があり、

MySQLの並列レプリケーションよりも細かい粒度で書き込みをまとめることが出来る。

 

そんなこんなで出来上がった設定は以下の通り。

ちなみに、16CORE/104GBの仮想マシンです。


##########
# mysqld
##########
[mysqld]
# --------------------------------------------------
# base
# --------------------------------------------------
user=mysql
bind-address=0.0.0.0
port=3306
pid-file=/var/run/mysqld/mysqld.pid
datadir=/var/lib/mysql
socket =/var/lib/mysql/mysql.sock
symbolic-links=0
sql_mode=TRADITIONAL
default-storage-engine=InnoDB
transaction-isolation=READ-COMMITTED
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
skip-character-set-client-handshake=0
innodb_buffer_pool_load_at_startup=1
innodb_buffer_pool_dump_at_shutdown=1
innodb-defragment=1
innodb_fast_shutdown=0
thread_pool_max_threads=1000
thread_handling=pool-of-threads

extra_port=3307
extra_max_connections=10

# --------------------------------------------------
# replication
# --------------------------------------------------
server-id=1
binlog_format=row
log-bin=mysql-bin
max_binlog_size=128M
sync_binlog=1
expire_logs_days=2
innodb_flush_log_at_trx_commit=1
innodb_autoinc_lock_mode=2
plugin-load=rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1500
rpl_semi_sync_slave_enabled=1
rpl_semi_sync_master_wait_point=AFTER_SYNC
log-slave-updates
relay_log_recovery=1
slave_parallel_threads=8

# --------------------------------------------------
# network
# --------------------------------------------------
max_connections=7200
max_connect_errors=999999999
connect_timeout=10
max_allowed_packet=10M
back_log=1024

# --------------------------------------------------
# logging
# --------------------------------------------------
log_output=FILE
log_warnings=1
log_error=/var/log/mysql/error.log
slow_query_log=1
long_query_time=0.5

slow_query_log_file=/var/log/mysql/slow.log
innodb_file_per_table=1
innodb_log_buffer_size=16M

# --------------------------------------------------
# cache, memory
# --------------------------------------------------
query_cache_size=0
max_heap_table_size=32M
tmp_table_size=32M
thread_cache_size=2400
innodb_buffer_pool_size=72G
innodb_flush_neighbors=0
innodb_read_ahead_threshold=0
innodb_log_file_size=4G
innodb_buffer_pool_instances=16
innodb_lru_scan_depth=2048

# --------------------------------------------------
# IO
# --------------------------------------------------
innodb_read_io_threads=16
innodb_write_io_threads=16
innodb_io_capacity=5000
innodb_io_capacity_max=20000
innodb_open_files=2048
innodb_purge_threads=4
innodb_sync_array_size=32

# --------------------------------------------------
# query
# --------------------------------------------------
sort_buffer_size=4M
read_rnd_buffer_size=2M
read_buffer_size=512K
join_buffer_size=512K

##########
# mysqldump
##########
[mysqldump]
default-character-set=utf8mb4
max_allowed_packet=1G

##########
# mysql
##########
[mysql]
default-character-set=utf8mb4

##########
# mysqld-safe
##########
[mysqld_safe]
log-error=/var/log/mysql/error.log

あとは、maxscaleで各種イベントを拾った時、
slave側には、以下のクエリーを投げてやることにした。


set global read_only = 1; set global innodb_flush_log_at_trx_commit = 0;

 

これで、slave側も秒間1000コミット近く耐えらる。

 

投稿日時:2017年03月14日 22:17   カテゴリー:mariadb  

以前の記事で、monitいいね!なんて書いたので、

monitの設定を残しておく。

なお、バージョンは5.1.4である。

 

[monit.rc]

set daemon 30

set logfile syslog

set eventqueue basedir /var/monit slots 100

set mailserver smtp.gmail.com port 587
 username XXX password XXX
 using tlsv12 with timeout 30 seconds

set mail-format {
 from: XXX@XXX
 subject: Monit Alert ($HOST)
 message: Monit
 ACTION : $ACTION
 SERVICE : $SERVICE
 EVENT : $EVENT
 at $DATE on $HOST.
 DESCRIPTION : $DESCRIPTION
}

set alert XXX@XXX not on {
 instance, action, exec
}

set httpd port 2812 and
 use address 0.0.0.0
 allow localhost
 allow XXX.XXX.XXX.XXX/255.255.255.0
 allow XXX:XXX
 allow XXX:XXX read-only

include /etc/monit.d/*.rc

monit.d以下のファイル。

[disk.rc]

check device root with path /
if space usage > 80% for 5 times within 15 cycles then alert
if inode usage > 90% then alert
if space usage > 95% then stop

[net.rc]

check network eth0 interface eth0

[system.rc]

check system XXX
if cpu > 80% for 5 cycles then alert
if memory usage > 90% for 5 cycles then alert
[mariadb.rc]
check process mariadb with pidfile /var/run/mysqld/mysqld.pid
start program "/usr/bin/systemctl start mariadb.service"
stop program "/usr/bin/systemctl stop mariadb.service"
[maxscale.rc]
check process maxscale with pidfile /var/run/maxscale/maxscale.pid
start program "/usr/bin/systemctl start maxscale.service"
stop program "/usr/bin/systemctl stop maxscale.service"

ほんとはもっとあるけど、

重要なもののみとしました。

 

ポイントとしては、

「データを保持するものは、安易に再起動をかけない」

というところでしょうか。

mariadbについては、今回レプリケーションを組んでいる関係上、

落ちた場合の即再起動が、逆に悪影響を及ぼす可能性があるためです。

 

あとは、うまいこと通知をいれること、

monit自体のプロセス監視などをいれておくことも大事です。

現状、以下2つのcron処理において、

  • monitプロセスの死活監視および再起動
  • monitの再監視設定

を行うようにしています。

*/5 * * * * /usr/bin/pgrep "monit" || /usr/bin/systemctl start monit > /dev/null 2>&1
7 * * * * /usr/bin/pgrep "monit" && /usr/bin/monit monitor all > /dev/null 2>&1

 

やはり、m/monitと連動させたいな。。

 

投稿日時:2016年12月26日 23:48   カテゴリー:server  

MariaDBを3台構成で、

準同期レプリケーション&スレーブ自動昇格

のクラスターを組んだので、備忘録として記載しておく。

 

[ソフトウェア]

  • MariaDB 10.1.18
  • Maxscale 2.0.1
  • MariaDB Replication Manager 0.6.4(以下MRM)

 

[インフラ]

  • web × 3 → MariaDB client, Maxscale, MRMを配備
  • db × 3 → MariaDB serverを配備

 

[処理概要]

webに配備されたMaxscaleはReadWriteSplitterで起動し、

127.0.0.1:4000のアクセスを、dbに振り分ける。

同時に、Maxscaleのmonitor機能により、

masterがフェイルオーバした際は、

MRMがコールされ、スレーブの自動昇格を実現する。

 

[注意したこと]

執筆時点でMRMの0.7rc3はリリースされていたが、どうも不具合があり、0.6.4で対応した。

ただし、issueでも上がっていたので、近日中には修正されると期待している。

 

MaxscaleからMRMを呼び出すのだが、

masterダウンイベントが走った際、3つのMRMが同時に検知してフェイルオーバ処理を実施した場合、

昇格の一貫性を保証するかわからなかったので、

masterダウンイベントを受け取った、webノード3台が相互に生き死にを確認し、もっとも優先順位が高いノードが、

フェイルオーバ処理を実行するようにした。

 


 

上記により、現状手動によるフェイルオーバ検知はすべて正常に行わるが、

MRMを呼び出す部分においてラップしているrubyスクリプトが、

ゾンビプロセスとなる不具合がある。

これについては、現状理由がよくわかっていないが、

Maxscaleを再起動すればなくなるので、一旦放置とした。

参考に、各設定を残しておく。

 

[maxscale.conf]

# Global parameters
[maxscale]
threads=2

# Server definitions
[s-db01]
type=server
address=XXX.XXX.XXX.1
port=3306
protocol=MySQLBackend
[s-db02]
type=server
address=XXX.XXX.XXX.2
port=3306
protocol=MySQLBackend
[s-db03]
type=server
address=XXX.XXX.XXX.3
port=3306
protocol=MySQLBackend

# Monitor for the servers
[m-db]
type=monitor
module=mysqlmon
servers=s-db01,s-db02,s-db03
user=XXX
passwd=XXX
monitor_interval=3000
script=/usr/local/bin/mrm.rb -u XXX:XXX -r XXX:XXX -h $INITIATOR,$NODELIST -e $EVENT -m m-db --live_nodes $NODELIST
events=master_down,master_up,slave_down,slave_up,new_master,new_slave

# Service definitions
[rw-db]
type=service
router=readwritesplit
servers=s-db01,s-db02,s-db03
user=XXX
passwd=XXX
max_slave_connections=100%
localhost_match_wildcard_host=1

[maxadmin service]
type=service
router=cli

# Listener definitions for the services
[l-db]
type=listener
service=rw-db
protocol=MySQLClient
port=4000

[maxadmin listener]
type=listener
service=maxadmin service
protocol=maxscaled
port=6603

 

[mrm.rb]

#!/usr/bin/ruby
# -*- encodinfg: utf-8 -*-
 
#
# maxscaleからfailoverを実行させるためのスクリプト
#
 
# 引数解析ライブラリ読み込み
require 'optparse'
 
##############################
# 初期化
admin_user = nil
replication_user = nil
target_hosts = nil
event_name = nil
monitor_name = nil
live_nodes = nil
 
# 引数解析
OptionParser.new do |opt|
 # 管理ユーザ
 opt.on('-u VALUE', 'admin user and password') do |v|
 admin_user = v
 logger.info('admin_user => %s' % v)
 end
 # レプリケーションユーザ
 opt.on('-r VALUE', 'replication user and password') do |v|
 replication_user = v
 logger.info('replication_user => %s' % v)
 end
 # 対象ホスト
 opt.on('-h VALUE', 'target hosts') do |v|
 target_hosts = v
 logger.info('target_hosts => %s' % v)
 end
 # 監視名
 opt.on('-m VALUE', 'monitor name') do |v|
 monitor_name = v
 logger.info('monitor_name => %s' % v)
 end
 # イベント名称
 opt.on('-e VALUE', 'event name') do |v|
 event_name = v
 logger.info('event_name => %s' % v)
 end
 # 稼働中ノード
 opt.on('--live_nodes [VALUE]', 'live nodes (optional)') do |v|
 live_nodes = v
 logger.info('live_nodes => %s' % v)
 end
 
 # 解析
 opt.parse!(ARGV)
end
 
# チェック
if !admin_user || !replication_user || !target_hosts || !event_name || !monitor_name
 # 終了
 exit
end
 
# クラスターを取得
got_result_ip_list = []
cluster_ip_list = getClusterInternalIpList('web')
cluster_ip_list.each do |cluster_ip|
 # maxadminの状況確認
 command = '/usr/bin/timeout 3 /usr/bin/maxadmin -pmariadb -h %s list monitors | grep -F "%s" | grep -F "Running"' % [cluster_ip, monitor_name]
 result = exec(command)
 
 # 結果を取得できたIPを取得
 if result.length > 0
  got_result_ip_list.push(cluster_ip)
 end
end
 
# 結果を取得できたIPの先頭が自分のIPなら実行する
self_internal_ip = getSelfInternalIp()
if self_internal_ip != got_result_ip_list.shift
 # 終了
 exit
end
 
# eventチェック
command = nil
result = nil
if event_name == 'master_down'
 # replication-manager実行
 raw_command = <<EOF
/usr/local/bin/replication-manager\
 --user=%s\
 --rpluser=%s\
 --hosts=%s\
 --failover=force\
 --interactive=false\
 --gtidcheck=true\
 2>&1 | cat
EOF

 command = raw_command % [admin_user, replication_user, target_hosts]
 result = exec(command)
end
 
# メール通知など

 

[my.cnf]

※3台とも同じ設定で、マシンスペックは4CORE/26GBの仮想マシンで、更新系に重点を置いている
##########
# mysqld
##########
[mysqld]
# --------------------------------------------------
# base
# --------------------------------------------------
user=mysql
bind-address=0.0.0.0
port=3306
pid-file=/var/run/mysqld/mysqld.pid
datadir=/var/lib/mysql
socket =/var/lib/mysql/mysql.sock
symbolic-links=0
sql_mode=TRADITIONAL
default-storage-engine=InnoDB
transaction-isolation=READ-COMMITTED
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
skip-character-set-client-handshake=0
innodb_buffer_pool_load_at_startup=1
innodb_buffer_pool_dump_at_shutdown=1
thread_handling=pool-of-threads

# --------------------------------------------------
# replication
# --------------------------------------------------
server-id=1
binlog_format=row
log-bin=mysql-bin
max_binlog_size=128M
sync_binlog=1
expire_logs_days=3
innodb_flush_log_at_trx_commit=1
innodb_autoinc_lock_mode=2
plugin-load=rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000
rpl_semi_sync_slave_enabled=1

# --------------------------------------------------
# network
# --------------------------------------------------
max_connections=1500
max_connect_errors=999999999
connect_timeout=10
max_allowed_packet=1G

# --------------------------------------------------
# logging
# --------------------------------------------------
log_output=FILE
log_warnings=1
log_error=/var/log/mysql/error.log
slow_query_log=1
long_query_time=0.5
slow_query_log_file=/var/log/mysql/slow.log
innodb_file_per_table=1
innodb_log_buffer_size=16M

# --------------------------------------------------
# cache, memory
# --------------------------------------------------
query_cache_size=0
max_heap_table_size=32M
tmp_table_size=32M
thread_cache_size=500
innodb_buffer_pool_size=20G
innodb_flush_neighbors=0
innodb_log_file_size=!G

# --------------------------------------------------
# query
# --------------------------------------------------
sort_buffer_size=512K
read_rnd_buffer_size=512K
read_buffer_size=512K
join_buffer_size=512K

##########
# mysqldump
##########
[mysqldump]
default-character-set=utf8mb4
max_allowed_packet=1G

##########
# mysql
##########
[mysql]
default-character-set=utf8mb4

##########
# mysqld-safe
##########
[mysqld_safe]
log-error=/var/log/mysql/error.log

 

今後、高負荷状況において、テストを行うので、

修正があれば別途記載しようと思う。

 

以上

投稿日時:2016年12月26日 23:36   カテゴリー:mariadb, mysql  

Google Computer Engineにおいて、

いつの間にか、google-cloud-sdkのインストール方法に変更があった。

古いインスタンスと、新しいインスタンスで操作方法が異なってしまったので、

備忘録として残しておく

 

(古いインスタンス)

  • OS:CentOS Linux release 7.2.1511 (Core)
  • 構築日時:2016年3月ごろ

最初から、google-cloud-sdkがはいっており、

gcloudコマンド等が使えた。

そして、

# gcloud components update

が実行できた。

→ おそらく、これはマニュアルにある、install.shを実行したやつなのだろう。

 

(新しいインスタンス)

  • OS:CentOS Linux release 7.2.1511 (Core)
  • 構築日時:2016年12月ごろ

gcloudコマンドが最初から使えない代わりに、

yumでインストール可能となっていた。

このインストール方法だと、

# gcloud components update

が実行できなくなっていた。

→ いつの間にか、/etc/yum.repos.d/google-cloud.repoファイルに、

google-cloud-sdkのセクションが追加されていた。

 

というわけで、

古いインスタンスの/etc/yum.repos.d/google-cloud.repoファイルを以下のように変更。

[google-cloud-compute]
name=Google Cloud Compute
baseurl=https://packages.cloud.google.com/yum/repos/google-cloud-compute-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg

[google-cloud-sdk]
name=Google Cloud SDK
baseurl=https://packages.cloud.google.com/yum/repos/cloud-sdk-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg

 

そして、

# yum install -y google-cloud-sdk

を実行し、最新のsdkをインストール。

 

・・・すれば行けるはず。

↑はまだ実行してないんだけどね。。

ひょっとしたら、古いgcloudを削除する必要ありそう。。

 

GCPは変更があっても、

マニュアルの反映が遅かったりして、ちょっとわかりづらいわ。。

stackdriverだって、2016年10月にGAになったのに、

日本語マニュアルを見ると未だにベータ版って記述残ってるし。。

このあたりしっかりやって欲しいわ。。

 

投稿日時:2016年12月11日 00:06   カテゴリー:gcp  

ここ最近、インフラ寄りの話ばかりであるが、

GooglePlatformで使えるCloudCDNについて書いておく。

 

CloudCDNはawsのcloud frontなどとは違い、

ロードバランサーの一機能として利用できる。

特徴としては、

ロードバランサーと同一ドメインで利用できるところである。

イメージ的には以下のようになる(実際は違いますけど。。)

 


    user <--> load balancer <--> cloud cdn <--> vm instance 

 

この構成のよいところは、オリジンであるVMインスタンス(awsでいえばEC2)に置いてあるキャッシュさせたいコンテンツを、

ロードバランサーと同じドメインで取得できるところである。

そのため、VMインスタンスに画像等を丸々配備できるため、開発者がインフラを意識する必要がなくなるということだ。

 

これに対し、他CDNの場合、キャッシュさせたいコンテンツを他ドメインから取得させるよう、

HTMLをコーディングする必要がある。

しかし、CloudCDNなら、それを意識する必要はない。

これは開発者から見ると非常に大きな利点である。

(awsのcloud frontのL7機能でキャッシュの有無を調整することは可能だが、キャッシュさせないコンテンツでも瞬間的にはキャッシュされるので、

一意URLによるGETなどはあらかじめ注意して開発する必要がある)

 

ただし、HTTP/1.1の場合、同一ドメインから同時にアクセスできるURL数というのはブラウザで制御しているため、

実際には様々なドメインから取得させた方がユーザへの体感速度の向上が図れるのは周知の事実である。

(HTTP/2ではこの問題も多少はマシになるとは期待してますが、、)

 

ただ、CloudCDNの残念なところは、現状キャッシュされているものの情報や、ヒット率等の統計が取れないところである。

しかし、何度も書いたように、開発者(もっといえばコンテンツ開発者)にありがたいインフラ構成というのは、特筆すべき点かと思われる。

 

以上

投稿日時:2016年10月17日 00:54   カテゴリー:cdn, gcp  

以前の記事で、CDNについて書いてみようかなということにしていたので、

次世代CDNとうたわれるfastlyについて書いてみる。

 

fastlyの最大の特徴は、

0.5秒で世界中のキャッシュを消す

というインスタントパージ機能である。

これはほんとにすごい。

他のCDNでは実現できていない高機能である。

 

実際にキャッシュが消えたかを確認するには、

キャッシュを消す前後で、以下APIをたたいてHASHを確認することができる。

https://docs.fastly.com/api/tools#content

実際にHASHは異なっていたし、キャッシュも消えていた。

 

もうひとつfastlyはすごいと思ったことがある。

それはキャッシュしなかった場合でも、

選択される回線の速度が非常に速い

実際にルータのホップ数などを見ても、とても少ない。(そのため、オリジンとfastly間の転送料金が高めだが)

 

広域にコンテンツを展開したいとき、

非常に有効なCDNだと思われる。

 

以上

投稿日時:2016年10月17日 00:26   カテゴリー:cdn  

awsのIPv6対応状況をまとめてみる。

 

■ELB

dualstackから始めるドメインであれば、IPv6対応である。

Route53を使う場合は、AAAAのaliasを貼ればよく、

他DNSを使う場合は、CNAME設定になるのかな?


dualstack.XXX.ap-northeast-1.elb.amazonaws.com

 

■S3

こちらもdualstackのドメインであれば対応済みということである。

https://aws.amazon.com/jp/blogs/news/now-available-ipv6-support-for-amazon-s3/

 

■Cloud Front

こちらは執筆時点では対応発表済みであるが、

逐次対応が進んでいる状況である。

そのため、ひょっとしたら、設定したにも関わらず、

名前解決できない可能性もある。

https://aws.amazon.com/jp/blogs/news/ipv6-support-update-cloudfront-waf-and-s3-transfer-acceleration/

 

その他、EC2などはIPv4を前提とした設計となっているため、

対応にはしばらくかかるだろう。

ただ、外向きの部分において、awsはIPv6対応を着実に進めているため、

appleのATS問題などは回避できそうである。

 

その他、私が知っている限りだと、

  • さくらVPS
  • さくらクラウド

はIPv6対応が結構すすんでいる。

ただし、さくらクラウドは共用ネットワークではIPv6が利用できなかったので、注意が必要。(※あくまで執筆時点)

さくらは比較的早期からIPv6対応していたので、近いうちにもろもろ対応してくれるだろう。

 

以上

投稿日時:2016年10月17日 00:07   カテゴリー:aws  

以前の記事でnginxのIPv6対応を書いた。

しかし、設定上、


ipv6only=on

という記述は、1度しか書けないため、

virtualhostで複数運用している場合に、この設定は邪魔となる。

 

virtualhostで運用する場合が多いので、

最終的には以下のようにすればよいのではないだろうか。

 

/etc/nginx/nginx.conf

http {
    :
    :
    # serverディレクティブは書かない
    include /etc/nginx/conf.d/*.conf;
}

 

/etc/nginx/conf.d/default.conf

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name localhost;
    :
    :

 

/etc/nginx/conf.d/your-ssl-vh.conf

server {
    listen                  80;
    listen                  [::]:80;
    listen                  443 ssl;
    listen                  [::]:443 ssl;
    server_name             your-ssl-vh;
    ssl_certificate         /etc/pki/tls/certs/server.crt;
    ssl_certificate_key     /etc/pki/tls/certs/server.key;
    :
    :   

 

このように記載しておくと、your-ssl-vhホストでは、

ipv4、v6の、non-sslまたはsslでのlistenとなる。

non-sslサイトを生きにしつつ、sslも併用し、

念のためipv6対応も入れたいというケースはこのような対応となるだろう。

 

以上

投稿日時:2016年10月16日 23:52   カテゴリー:nginx, server  

GCPからのメール送信というと、

  • 外部サービス(SendGrid)に接続してのSMTP通信
  • GoogleAppsへのSMTPリレー

などがよく出てくるが、

SendGridを使うほどではなく、

たまにアラートなどで使いたい場合に、

上記どちらの方法もやりにくい。

 

実際にrubyスクリプトから、SMTP接続してメール送信をするケースにおいて、

どうもSMTPリレーが上手くいかなかった(Postfixでちゃんとリレー設定しないと難しいのかな?)ので、

アプリパスワードを発行して、GoogleAppsへSMTP接続すれば、無事送信できることが確認できた。

詳しくは以下。

https://support.google.com/mail/answer/185833?hl=ja

 

最近はwebhookなども通知に使われるが、

やはり入れておきたいメール通知。

 

以上

投稿日時:2016年08月15日 23:14   カテゴリー:gcp  

AWSのCDNであるCloudFrontを利用したので、

その特徴を記載しておく。

 

良い点
・L7レベルで動作
たとえば2つのオリジンを設定して、
パスパターンによって、振り分け先を変更できること。
静的コンテンツはS3に、動的コンテンツはELBに振るなどが可能。

・独自ドメインでのSSLが利用可能
S3では出来ない独自ドメインSSLが利用可能。

・AWS内のオリジンとは高速な通信
オリジンがELBの場合、ELB配下のインスタンスが巨大な画像等を返す場合、
通信が安定しているcloudfrontに返すほうが、インスタンスの負荷は下がる。

悪い点
・変更反映が遅い
15分くらいかかるのだろうか。

・キャッシュ削除が遅い
これも15分くらいかかっている感じがする。

・連続的にGETアクセスした場合にキャッシュさせたくなくてもキャッシュされる
例えば2つオリジンを設定して、片方を静的、もう片方を動的とする。
動的コンテンツ側に振られるURLに瞬間的に連続アクセスした場合、すべてのリクエストが動的コンテンツ側に来るわけではなく、
cloudfrontにキャッシュされてしまう。
後述するキャッシュのヒット条件にもよるが、
キャッシュさせないはずの動的コンテンツが、実際にはキャッシュからエンドユーザに返される可能性がある。
最も簡単・確実に回避するためには、URLに一意のクエリ文字列を付ければよい。(JSを使って、タイムスタンプ+ランダム文字列などを付与する)

・オリジンへ渡すヘッダー情報がキャッシュキーの種となる
オリジンへ渡すヘッダーとしては諸々設定が可能だが、
動的コンテンツをオリジンとする場合、user-agentなどを通ししまうと、
それがキャッシュキーの種となり、結果としてキャッシュヒット率が下がる。
この場合は、cloudfront独自の「IS_MOBILE」的なヘッダーを付けて、オリジン側で判定として使える。
逆に言うと、cloudfrontを使う場合、オリジンで「IS_MOBILE」などの判定処理を用意しておく必要がある。

 

CloudFrontは設定が細かく、結構難しい。

ただ、統計情報も充実しており、

なんといっても高負荷に強く、エッジロケーションも広いので、

上手く使えば非常に強力な製品だと感じた。

気を付けるべきは、動的コンテンツを背後に置く場合だろう。

キャッシュ条件、キャッシュ生存期間など、動的コンテンツ作成者側が意識しておくことで、

より有用なものとすることが出来ると思う。

 

最近は、CDNが多用されているので、

各CDNの特徴をよく確認し、十分に検証したうえで、

導入を検討するとよいと思う。

 

他のCDNについても、機会があれば書いてみようと思います。

 

以上

投稿日時:2016年08月13日 23:36   カテゴリー:aws, cdn