Dartの変数
変数を宣言
基本形はこう。 型 変数名 = 値;
という形をとる。
int number = 1; String name = 'hoge';
さらにDartは型推論機能を持っているので、var記法
を使って、型を指定せずに変数を宣言することも可能。
var number = 1; var name = 'hoge';
dynamic型
dynamic
を使うと、動的に変数宣言できる。
他の言語にもあまりない名前の型ですが、 TypeScriptだと Any
に近い振る舞いをする型っぽい?(詳しい方、教えてくださいmm)
dynamic型
の変数にはどんな型のオブジェクトでも入れることが可能となるため、型安全が保証されなくなるので、使う時は本当に必要な時だけにしたほうがよさそう。
ってことで、軽く検証してみる。
dynamic型
を使えば変数宣言時は何も考えず宣言ができるが、その変数を利用する際には、呼び出し側が変数の型を知っている必要があることがわかる。
void main() { void foo(String name) { print(name); } void bar(int name) { print(name); } dynamic name = "hoge"; foo(name); // hoge bar(name); // type 'String' is not a subtype of type 'int' }
bar(name)
を呼び出すと、bar(name)
は int型
の引数を期待しているのに、Stringが入ってきたのでエラーにしたよ、という結果になります。
この場合、開発者は bar()
を使う時に 変数name
の実際の型が String
になっていることを知っていなければなりません。
RubyスクリプトからMySQLにログインする
ActiveRecord上からDBに接続すると実際にどんなふうにDB操作をプログラムからやれるものかのかイメージしづらくなる。そこで今回はRubyのプログラムを書いて、MySQLにログインするためのスクリプトを書いてみる。
対象読者
構成
こんな感じ。 RDSとか使ってもよいのだけども、検証のためなので、擬似外部サーバとしてDockerを採用した。
STEP0: 前提とする環境
STEP1: MySQLコンテナをつくる
Docker使っているならわりと簡単。
docker pull mysql docker run --name mysql-server -e MYSQL_ROOT_PASSWORD=root -d -p 33066:3306 mysql
これでMySQLサーバが作成された。 これでコンテナ上にもmysqlのプロセスも立ち上がっているはず。
STEP2: ローカルからコンテナ上のMySQLにログインしてみる
mysql -h 0.0.0.0 -uroot -p # パスワードは root mysql >
無事、mysqlにログインできたらOK.
STEP3: コンテナ上で少し下準備
コンテナ上のmysqlにログインしたまま、下準備をする。 具体的には、データベース・テーブルの作成を行ないます。
CREATE DATABASE test; mysql> CREATE TABLE users(id int, name varchar(50)); mysql> use test; mysql> show tables; mysql> show tables; +----------------+ | Tables_in_test | +----------------+ | users | +----------------+ 1 row in set (0.00 sec) mysql> DESC users; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | name | varchar(50) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 2 rows in set (0.00 sec)
こんな感じのデータベースになればOK.
STEP4: Rubyスクリプトを書く
test.rb
require 'mysql' connection = Mysql::connect("0.0.0.0", "root", "mysql", "test", 33066) # 文字コードをUTF8に設定 connection.query("set character set utf8") # DBに問い合わせ # 挿入するデータ data= { 1: 'hoge', 2: 'fuga' } # 用意したデータの分だけINSERT文を実行 data.each do |id, name| connection.query("INSERT INTO test.users(id, name) VALUES(#{id}, '#{name}')"); end # SELECT文の結果を取得 rs = connection.query("SELECT * FROM users") # 検索結果を表示 rs.each do |r| puts r.join ", " end # コネクションを閉じる connection.close
実行してみる
書いたスクリプトを実行してみる。
[localhost]$ ruby test.rb 1, hoge 2, fuga
利用できるデバイス情報を把握する lsblkコマンド
ハードデバイスについて勉強してみた。
Linuxはデバイスファイルを通してデバイスを利用することができる
すべてをファイルとして扱う思想のLinuxでは、接続されたデバイスもファイルを通して利用することになっている。 そのホストとデバイスの入出力を扱うための特殊なファイルをデバイスファイルとよぶ。 IDEなのかSCSI系なのか、ハードディスクによって多少仕様は変わるが、ここでは割愛する。
ホストからどんなデバイスを利用することができるのか確認してみる
lsblkコマンド
を使えば、対象ホストから利用できるデバイスの詳細情報を確認することができる。
root@ip-xxx-xxx-xxx-xxx:/# lsblk -l NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT xvda 202:0 0 8G 0 disk xvda1 202:1 0 8G 0 part /
上記の出力について、少し説明。
項目 | 説明 |
---|---|
NAME | デバイス名 |
MAJ:MIN | デバイス番号(メジャー:マイナー) |
RM | リムーバブルディスクかどうか |
SIZE | 容量 |
RO | 読み取り(ReadOnly)専用か否か |
TYPE | デバイスの種類 |
MOUTPOINT | マウント先 |
さらに詳細を説明
気になった項目に絞って調べてみた
TYPE
主なデバイスの種類として以下の3つがあるようです。
デバイスの種類 | 説明 |
---|---|
disk | 物理ドライブ |
part | パーティション |
lvm | Logical Volume Manager。複数のハード・ディスクやパーティションにまたがった記憶領域を一つの論理的なディスクとして扱うことのできるディスク管理機能で作られた論理ボリューム |
なぜRMの欄が存在するか?
そもそもRMとは、記録メディアを取り出して交換できる記憶装置のことを指す。 ストレージ運用は、内臓ハードディスクか取り外し可能なハードディスクなのかによって大きく変わるため、表示されるものだと推測される。
結局のところ、lsblkコマンドでどんなことができるのか?
使い方: lsblk [オプション] [<デバイス> ...] オプション: -a, --all すべてのデバイスを表示します -b, --bytes 可読性の高い形式ではなく、バイト単位でサイズを表示します -d, --nodeps スレーブデバイスやホルダーを表示しません -D, --discard discard 関連の機能を表示します -e, --exclude <一覧> メジャー番号を利用して、除外するデバイスを指定します (既定値: RAM ディスク) -f, --fs ファイルシステムに関する情報を出力します -i, --ascii ASCII 文字のみを使用します -I, --include <一覧> 指定したメジャー番号のデバイスのみを表示します -l, --list 一覧形式で出力します -m, --perms パーミッションに関する情報を出力します -n, --noheadings ヘッダを表示しないようにします -o, --output <list> 出力する列を指定します -O, --output-all output all columns -p, --paths 完全なデバイスパスを表示します -P, --pairs キー="値" の出力形式を使用します -r, --raw 加工を行なわない出力形式を使用します -s, --inverse 依存関係を逆転します -S, --scsi SCSI デバイスに関する情報を出力します -t, --topology トポロジに関する情報を出力します -x, --sort <column> sort output by <column> -h, --help このヘルプを表示して終了します -V, --version バージョン情報を表示して終了します 利用可能な列 (--output で指定します): NAME デバイス名 KNAME カーネル内部デバイス名 MAJ:MIN メジャー:マイナーデバイス番号 FSTYPE ファイルシステムの種類 MOUNTPOINT マウントされている場所 LABEL ファイルシステムのラベル UUID ファイルシステムの UUID PARTTYPE partition type UUID PARTLABEL パーティションのラベル PARTUUID パーティション UUID PARTFLAGS パーティションフラグ RA デバイスの先読み RO 読み込み専用デバイス RM リムーバブルデバイス MODEL デバイス識別子 SERIAL ディスクのシリアル番号 SIZE デバイスのサイズ STATE デバイスの状態 OWNER ユーザ名 GROUP グループ名 MODE デバイスノードのパーミッション ALIGNMENT アライメントオフセット MIN-IO 最小 I/O サイズ OPT-IO 最適 I/O サイズ PHY-SEC 物理セクタサイズ LOG-SEC 論理セクタサイズ ROTA ローテーションデバイス SCHED I/O スケジューラ名 RQ-SIZE 要求キューサイズ TYPE デバイスの種類 DISC-ALN discard アライメントオフセット DISC-GRAN discard 粒度 DISC-MAX discard 最大バイト DISC-ZERO discard ゼロデータ WSAME write-same 最大バイト WWN ユニークなストレージ識別子 RAND 乱数シードへの追加 PKNAME 親のカーネル内部デバイス名 HCTL SCSI 向けのホスト:チャンネル:ターゲット:LUN TRAN デバイス伝送タイプ REV デバイスのリビジョン VENDOR デバイスの製造元 ````
macosでJVMのスレッドダンプを取得する
JVMのこと、詳しくなりたくって、でも何もできずにいる自分がただそこにいるだけで、悔しくて泣きたくて。
そんな気持ちを最近持ったので、勉強しはじめた。
とりあえずjavaをインストールする
ORACLEのインストールガイドを読むのが一番。
MacでのJavaのインストール方法
インストール完了後、こんな感じでバージョンを確認できたらよさげ。
$java -version java version "1.8.0_131" Java(TM) SE Runtime Environment (build 1.8.0_131-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
javaのプログラムを起動する
とりあえず簡単なプログラムを起動させて、立ち上がっているプロセスを確認したい。
ただ、ずっと起動しぱなっしのプロセスにしてあげる必要があるので、BufferedReader
というやつを使って、入力完了するまでプロセスが死なないようにした。
import java.io.*; public class HelloWorld { public static void main (String[] args) throws IOException { InputStreamReader is = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(is); System.out.println("何か入力してください."); String str = br.readLine(); System.out.println(str + "が入力されました."); } }
HelloWorld.java
として保存して、 javac HelloWorld.java
, java HelloWorld
を実行すると実行される。
javaプロセス起動中にスレッドダンプを取得
プログラムを実行すると、 何か入力してください.
と出たまま入力せずに別のコンソールから起動中のプロセスを確認する。
$ps aux | grep java user 34577 0.0 0.0 2432804 776 s021 S+ 2:27AM 0:00.00 grep java user 34573 0.0 0.3 6026488 22852 s019 S+ 2:27AM 0:00.16 /usr/bin/java HelloWorld
ちゃんと立ち上がったままになってて良い感じ。
次にスレッドダンプを取得。
$jps 34582 Jps 34573 HelloWorld
jps
コマンドで、pidに紐づいたjavaの実行プログラムがリストで取れるっぽい。
さらに jstack
コマンドでpidを指定するとそのプロセスのスレッドダンプを出力できる。
$jstack 34420 2017-05-17 02:13:46 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.131-b11 mixed mode): "Attach Listener" #9 daemon prio=9 os_prio=31 tid=0x00007fc815083800 nid=0x1307 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Service Thread" #8 daemon prio=9 os_prio=31 tid=0x00007fc815025800 nid=0x4903 runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C1 CompilerThread2" #7 daemon prio=9 os_prio=31 tid=0x00007fc816008800 nid=0x4703 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread1" #6 daemon prio=9 os_prio=31 tid=0x00007fc81582c800 nid=0x4503 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread0" #5 daemon prio=9 os_prio=31 tid=0x00007fc815871800 nid=0x4303 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Signal Dispatcher" #4 daemon prio=9 os_prio=31 tid=0x00007fc815871000 nid=0x4103 runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Finalizer" #3 daemon prio=8 os_prio=31 tid=0x00007fc815857800 nid=0x3103 in Object.wait() [0x000070000dd8e000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x0000000795588ec8> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143) ...
あとはよさげに
jstack 34420 > hoge.log
とかしてあげるとよい。
なお、スレッドダンプの読み方も調べてみたけど語るには知識がなさすぎるので、参考になった記事を共有するに留めておくことにします。
Java書かないのでまったくここらへんのことわからないけど、少しずつこうやって知見を貯めていきたい。
Infrastructure as Codeの価値・原則・プラクティス・評価軸
Infrastructure as Code ―クラウドにおけるサーバ管理の原則とプラクティス
- 作者: Kief Morris,宮下剛輔,長尾高弘
- 出版社/メーカー: オライリージャパン
- 発売日: 2017/03/18
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (2件) を見る
Infrastructure as Code本の読書まとめ。
1周目は理解仕切れていないところ多くて、2周目でなんとなーくわかってきて、3周目の今、自分なりにまとめていこうと思いまして、記事にしてます。
ほとんどの項目がまんま書かれていますが、いまいちわかっていなかったとこは自分なりのメモを残すことにした。
価値
- 変化を支えられるインフラをつくれる
- システムの更新を日常のものにできる
- プロダクト開発者地震がリソースのメンテナンスを行える
- 障害が起きてもすぐに対応できる
原則
- 簡単に再現できるシステムであること:ほとんどの作業が自動化されている状態であること
- 使い捨てにできるシステムであること:変化に合わせて今あるものを除却/追加しやすい状態であること
- 統一的なシステムであること:同じ役割をもつサーバがほとんど同じ状態であること
- 反復できるプロセスであること:誰がいつやっても同じ状態をつくれる状態であること
プラクティス
- 定義ファイルを使いましょう
- 自己記述システムでプロセスを担保しましょう
- VCSを使いましょう
評価軸
- 労力をかけずにインフラ開発・運用ができているか
- 常にサーバは最新の状態かつ統一性が担保されているか
- CI/CDの仕組みが整っており、開発者がそれを容易に実行できるか
- 営業中にデプロイできるような状態か
- MTTRをKPIとして改善に取り組めているか
nginxの負荷分散手法(1) 重み付け
nginxでは、リバースプロキシ機能を使って、負荷分散を行なうことができる。
主なやり方は3つ。
- 重み付けによる負荷分散
- 稼働系と待機系
- 接続数による負荷分散
今回は、 1. 重み付けによる負荷分散 について。
設定方法は簡単。
upstreamコンテキストでまとめた複数のバックエンドサーバにweightオプションと重みパラメータをつけるだけ。
upstream backend { server xxx.xxx.xxx.xxx weight=3; server yyy.yyy.yyy.yyy weight=2; server zzz.zzz.zzz.zzz weight=1; }
この設定で、
- xxx.xxx.xxx.xxx サーバは 全アクセスの3/6 の割合を捌くこととなる
- yyy.yyy.yyy.yyy サーバは 全アクセスの2/6 の割合を捌くこととなる
- zzz.zzz.zzz.zzz サーバは 全アクセスの1/6 の割合を捌くこととなる
サーキットブレイカーパターン:連続して起こる同様の障害への対応策
障害が起こりにくい・万が一、障害が起きた時にシステム側で早急な対応をするような仕組みを勉強しております。そこでサーキットブレイカー。
サーキットブレイカーパターンとはなにか
電子回路にも使われている遮断機が主な概念になっているパターン。何かしらのReq/Resに対して、良くない事象(つまり障害)が頻発すると「あ、これはやばいから一旦この導線をオフにしていこう」という仕組みのことを指します。リモートコールはインメモリコールと比べ、いくつか障害になりえる要素が多く、考慮が必要です。例えば、リモートコールはそもそも受信失敗しやすかったり、サプライヤー側からのレスポンスが頻繁にタイムアウトしてしまったりすることがあります。原因がリモートにある以上、対処がしにくく、かつ一度起きてしまったら、連続的に起こりうるような障害対応のために生まれたのがサーキットブレイカーパターンです。
仕組みと処理の流れ
- 中間層にサーキットブレイカーを設けます(処理の流れの中に組み込めばOK)
- クライアントがリクエストを投げると、そのリクエストはサーキットブレイカーを介してサプライヤー(リモートにあるサーバ側)に向かいます
- サプライヤー側になんの問題もなければサーキットブレイカーもそのまんまクライアントにレスポンスを渡します(正常系)
- もしサプライヤー側で処理が滞っていたり、そもそも何かしらの問題でサプライヤー側にリクエストが届いていなかったりしてレスポンスがなかったらサーキットブレイカーはその障害発生数を記録
- サーキットブレイカーで設定している閾値に達してしまうと、サーキットブレイカーは自身の処理を切り替え(これをトリップというらしい)、クライアント側へ早急にエラーメッセージを配信するようにします(この時点で、サプライヤーへの通信をしなくなる)。
- 妥当だと思われる障害復旧時間を設定しておけば、サーキットブレイカーは自己復旧を行ない、サプライヤー側へ疎通を図ります。問題がなさそうであれば、2の状態に戻ります。
なお、サーキットブレイカーはこのような状態を切り替えながら(トリップしながら)、障害検知・切り替え・復旧を行なっております。
Closedは電子回路でいうと電流が流れている状態なので正常系処理をしている状態。Openは導線を断ち切り、電流が止まっている状態なので「今サプライヤー側でなんか知らないけどよくない事態が起きてるのでそのリクエスト受け付けられないんです」とエラーメッセージを返している状態。HalfOpenがプログラム内で設定した時間間隔のもとサプライヤーへヘルスチェックしに行き、Closedに戻せるか確認している状態を意味します。
サーキットブレイカーの長所
自分らでは障害が起きても、根本的な対応が取れない外部サービスと連携している場合、導入する意味があるように思えます。一度Openになると、サプライヤーまでの通信は切られるので、ユーザーに時間的なストレスを感じさせないという点で、早急にエラーを返すことができるのがメリットだと思います。
ソース元: martinfowler.com