White Box技術部

WEB開発のあれこれ(と何か)

【duolingo】最近の英語学習方法

duolingoを使って英語の勉強をしています。

www.duolingo.com

どういうものか?

ざっくり言うと、文法、用途でジャンル分けされた内容の小テストをひたすら消化していくものになります。

f:id:seri_wb:20160328210001p:plain

出題される問題は、英文を音読するだけのもあれば、翻訳(日英、英日)を文字入力で回答するものもあります。 さらに、翻訳の日英は発声で答える場合もありますし、選択肢で答える場合もあります。

このように回答方法が多岐にわたるので、ジャンルで似たような英文問題が続いても、丸暗記になりづらい学習ができている気がします。 1回の学習時間が3分位で終わるのも、気が向いたときにやりやすくていい感じです。

無料で利用することができるので、試してみてもらったほうがわかりやすいかもしれませんね。

ただ、英語の音声認識の方は、結構発音を正しくしないと認識しなかったり、間違ったことを言っても正解と認識したりと、 まだ改善の余地はありそうです。なので気になるようなら、発声テストは無効にして学習するのもありかと思います(オプションで選択可能)。

あえて問題を上げるとしたら、開くたびにちょいちょい私に友達がいないことを煽ってくるところですかね!

f:id:seri_wb:20160328210004p:plain

Phoenix Frameworkのドキュメント翻訳始めました

いつも英語が話せるようになりたいなと漠然と思っていたので始めた英語学習ですが、 今は特に英語を使う機会がないので、Phoenix Frameworkのドキュメント翻訳をすることでモチベーションを保とうかと考えています。

これからも折を見て残りを訳していこうと思います。

しかし、日本語に直すっていうのは別スキルかなと翻訳作業しながら思いました。

【Linux】メモリがカツカツなサーバのメモリを復活させる

メモリ枯渇の背景

仕事で、PHPのPhalcon FWで作ったAPIアプリケーションが乗ったphp-fpmサーバを運用しているのですが、 こやつで大量のリクエストをさばけるよう、負荷試験を行ってチューニングした結果、 現在php-fpmプロセスは、staticでリクエストを待つようになっています。

そのせいなのか、リクエストが少ないとプロセスのリフレッシュまで時間がかかり、 結果、APIサーバのメモリを食い潰すという事態にちょいちょいなります。

これは負荷試験で大量リクエストを投げているときは出てこない事象なので、完全に盲点でした。

問題発覚後は、設定値チューニングしたり、php-fpmをreloadしたりして適時対応してきたのですが、 本日ふと、サーバ上のメモリのほとんどが、reloadでも開放されていないことに気付きました。

・解放前
$ free -m
             total       used       free     shared    buffers     cached
Mem:          7871       7592        279          1        167        308
-/+ buffers/cache:       7116        755
Swap:         1023          0       1023

・reloadで解放
$ sudo service php-fpm reload
Reload service php-fpm  done

・解放後
$ free -m
             total       used       free     shared    buffers     cached
Mem:          7871       5080       2791          1        167        308
-/+ buffers/cache:       4603       3267
Swap:         1023          0       1023

そういえば、php-fpmのrestart/reloadは公式ドキュメントにGracefull restartと書かれていますが、 実際には期待する動作をしませんでした。この件の対応法についてはまた別途記事にしようと思います。

メモリ使用の詳細を確認する

以下のコマンドでメモリ情報を確認したところ、Slabという領域が4Gほど確保していることに気付きました。

$ view /proc/meminfo

Slabとは?

わからなかったので調べました。
以下のサイトにお世話になった結果、どうもKernelキャッシュの一種のようですね。

詳細はリンク先で☆

Slabキャッシュをクリアした話 – CLARA ONLINE techblog

Slabキャッシュの確認

slabtopコマンドで上位2つの消費が多いものを見たところ、 参考サイトと同様にdentryのキャッシュが肥大化しているようでしたので、 このキャッシュをクリアすることにしました。

Slabキャッシュのクリア

以下が各フェーズの実行結果です。

・slabtopの結果(reload後)
  OBJS ACTIVE      USE OBJ SIZE   SLABS OBJ/SLAB CACHE SIZE NAME
20941060 20940019  99%    0.19K 1047053       20   4188212K dentry
  302198   301745  99%    0.06K    5122       59     20488K size-64

・Slabキャッシュクリアとその後のfree
# sync
# echo 2 > /proc/sys/vm/drop_caches
# free -m
             total       used       free     shared    buffers     cached
Mem:          7871        791       7080          1        167         56
-/+ buffers/cache:        567       7304
Swap:         1023          0       1023

・slabtopの結果(Slabキャッシュクリア後)
  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME
110580 110572  99%    0.19K   5529       20     22116K dentry
 83068  82608  99%    0.20K   4372       19     17488K vm_area_struct

drop_cachesを変更するにはrootになって実行する必要がありました。

Slabキャッシュクリアの結果

freeコマンドの結果だけからもわかるように、3Gなかったメモリの空き量が、 一気に7Gまで上昇しました。これはすごい!

そしてその後の経過を1日Zabbixで見守っていたのですが、 クリアしたSlabキャッシュをすぐに同じレベルまで確保することはなさそうでしたし、 アプリケーションにも不具合が出てなかったので、この対応で一旦メモリ枯渇の心配は(しばらく)なくなりました。

結論

アクセスが少ないうちは、php-fpmのプロセス管理をdynamicにしましょう。

MacPortsでMySQL5.7をインストールする

homebrewが猛威を振っていますが、MacPortsおじさんの私は元気です。

MySQL 5.7をインストールする

仮想環境にはMySQL 5.7を入れたりしていましたが、そういえばMacには入れてなかったのでインストール作業をしてみました。

環境情報

とりあえずport install

まずはsudo port selfupdateして、portを最新にしつつ(これで2.3.4になりました)、 mysqlの5.7がリポジトリに存在することをport search mysql | grep ^mysqlで探して、 おもむろに以下のインストールコマンドを叩きます。

$ sudo port install mysql57

すると以下のようなエラーが発生しました。

--->  Configuring mysql57
Error: The file /opt/local/lib/libwrap.dylib does not exist, though it was
Error: expected to have been provided by one of mysql57's dependencies. Try
Error: rebuilding the port that should have provided that file by running
Error: 
Error:     sudo port -n upgrade --force <portname>
Error: 
Error: org.macports.configure for port mysql57 returned: missing required file
To report a bug, follow the instructions in the guide:
    http://guide.macports.org/#project.tickets
Error: Processing of port mysql57 failed

depsチェック

mysql57をインストールするときに期待する依存ライブラリないというようなことを言われているので、 おもむろに以下のコマンドを叩いて依存ライブラリを確認します。

$ port deps mysql57 

すると以下のような結果になりました。

Full Name: mysql57 @5.7.11_1
Build Dependencies:   cmake
Library Dependencies: zlib
Runtime Dependencies: mysql_select

port installedで確認すると、どれもインストールされているので少し調べ、 その調べた感じだとcmakeがちゃんと入ってるか?みたいなことが書かれていたのでチェックしましたが、 ちゃんと現時点の最新のcmake @3.5.1_0が入っていました。

libwrap.dylibとは?

次にエラーになっているこのファイルが何なのか調べたら、 TCP Wrapperだったみたいなので、以下を実行してインストールし、 その後mysql57のインストールを実行したところ、いい感じに進みました。

$ sudo port install tcp_wrappers

mysql57-serverのインストール

とはいえ、以下のようなメッセージが出ており、mysql57-serverのインストールが別途必要なことをここで知ります。

--->  Computing dependencies for mysql57
--->  Configuring mysql57
--->  Building mysql57
--->  Staging mysql57 into destroot
--->  Installing mysql57 @5.7.11_1
The mysql57 client has been installed.
To install the mysql57 server, install the mysql57-server port.
--->  Activating mysql57 @5.7.11_1

On activation if no /opt/local/etc/mysql57/my.cnf file exists one
will be created which loads
/opt/local/etc/mysql57/macports-default.cnf.

If a /opt/local/etc/mysql57/my.cnf file exists MacPorts does not
touch it and any changes you make to /opt/local/etc/mysql57/my.cnf
will be preserved (e.g., during port upgrades, deactivations or
activations). /opt/local/etc/mysql57/my.cnf is a good place to
customize your mysql57 installation.

Any changes made to /opt/local/etc/mysql57/macports-default.cnf
will be lost during port upgrades, deactivations or activations so you
are advised to not make changes here. Currently
/opt/local/etc/mysql57/macports-default.cnf contains only one
directive; to disable networking. With disabled networking it is
possible to install and have running all the MacPorts mysql ports
simultaneously.

ちなみにこの時点のmy.cnfはmacports-default.cnfを見るという設定しか無いですし、 macports-default.cnfはコメント除くと以下だけです。

[mysqld]
skip-networking

実行結果

インストールコマンドを実行すると以下のようになります。

$ sudo port install mysql57-server
--->  Computing dependencies for mysql57-server
--->  Fetching archive for mysql57-server
--->  Attempting to fetch mysql57-server-5.7.11_0.darwin_14.noarch.tbz2 from https://packages.macports.org/mysql57-server
--->  Attempting to fetch mysql57-server-5.7.11_0.darwin_14.noarch.tbz2.rmd160 from https://packages.macports.org/mysql57-server
--->  Installing mysql57-server @5.7.11_0
--->  Activating mysql57-server @5.7.11_0

If this is a new install you might want to run:

$ sudo /opt/local/lib/mysql57/bin/mysqld --initialize --user=_mysql
$ /opt/local/lib/mysql57/bin/mysql_secure_installation

--->  Cleaning mysql57-server
--->  Updating database of binaries
--->  Scanning binaries for linking errors
--->  No broken files found.

これでインストールはおしまいですね。
あとは上のログにもあるようにmysqldを立ち上げて、Initializeコマンドを叩けばOKです。

でも今日はもうやりません。

後始末

これらの流れでmysqlコマンドにはPATHが通らなかったので、適当に/opt/local/lib/mysql57/binをPATHに通しておきましょう。

bashなら.bashrcに以下を追記してsource ~/.bashrcですね。

  • ~/.bashrc
export PATH=$PATH:/opt/local/lib/mysql57/bin

ついでにMacPortsも綺麗にする

MySQLのインストール前にport outdatedで更新が必要なパッケージがどのくらいが見て、 sudo port upgrade outdatedをしてからのほうが、依存性で怒られる可能性が減っていいと思いますが、 upgradeの際に-uオプションを付けていないと、過去バージョンのパッケージも残っている場合があるので、 port installedで確認して特に問題なければ(過去バージョンが必要なければ)、 以下のコマンドでささっと使ってないパッケージを削除してしまいましょう。

$ sudo port uninstall inactive

お疲れ様でした。

結論

MySQLなんてそうそう簡単にバージョン上げたりしないので、MySQLの公式サイトからdmgファイルを落としてきて入れるのが一番いいのではないでしょうか。

MySQL :: Download MySQL Community Server

追記

試しにdmgでインストールしてみたところ、 PATHは通ってないし、Initializeコマンドの説明も出てこなかったので、思っていたのとは違いました。 もう少しサポートしてくれるのかなと期待していたので。

ちなみにインストールが終了するとダイアログが表示され、デフォルトパスワードが設定されたことがわかります。

2016-04-01T05:55:51.394996Z 1 [Note] A temporary password is generated for root@localhost: XXXXXXXXX(←パスワード)

If you lose this password, please consult the section How to Reset the Root Password in the MySQL reference manual.

インストール先などの情報は以下の通りで、rootのファイルになっています。

  • インストール先:/usr/local/mysql(/usr/local/mysql-5.7.11-osx10.9-x86_64のエイリアス
  • my.cnfサンプル:/usr/local/mysql/support-files/my-default.cnf

my-default.cnfはMacPorts版より詳しい説明がある気がします。

# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
# *** DO NOT EDIT THIS FILE. It's a template which will be copied to the
# *** default location during install, and will be replaced if you
# *** upgrade to a newer version of MySQL.

[mysqld]

# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M

# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin

# These are commonly set, remove the # and set as required.
# basedir = .....
# datadir = .....
# port = .....
# server_id = .....
# socket = .....

# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M

sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

Phoenix Framework Documentの翻訳:Overview

www.phoenixframework.org

概要

Phoenixは、サーバサイドMVCパターンを実装するためにElixirで書かれたWebフレームワークです。 その構成要素と概念の多くは、Ruby on RailsPythonDjangoのような、他のWebフレームワークの経験を持つ私たちに馴染みのあるものだと思います。

Phoenixは、開発者に高い生産性を与えつつ、アプリケーションがハイパフォーマンスとなるように設計されています。 また、リアルタイム機能を実現するためのチャネル(Channels)や、燃え盛る炎のようなスピードをだすために事前コンパイルされるテンプレート(Templates)のような、興味深くて新しい、ひねりのある仕組みをいくつか持っています。

もしあなたがすでにElixirに精通しているのであれば、最高です! そうでなくても、Elixirを学ぶための場所はいくつかあります。 Elixirガイドは学び始める場所として最適です。 また、私たちもElixirとErlangの学習ガイドに役立つ情報をまとめています。

この入門ガイドの目的は、Phoenixを構成するパーツとPhoenixがサポートするレイヤーについて、簡潔かつ高レベルな概要をお伝えすることにあります。

vimeo.com

Phoenix

Phoenixは、モジュール構造で、かつ柔軟であるようにデザインされた多重レイヤーシステムの最上位レイヤーになります。 他のレイヤーには、このPhoenixの概要のすぐ後で言及する予定の、PlugとEctoが含まれます。 ErlangのHTTPサーバであるCowboyは、PlugとPhoenixの基盤として機能しますが、私たちがこのガイドで直接Cowboyの説明をすることはありません。

Phoenixは、Webアプリケーションを構築するために独自の目的や役割を持った、いくつかの個別パーツで構成されています。 これらすべてについて、ガイド全体を通して深く解説していきますが、以下に簡単な内容を記載します。

  • エンドポイント
    • ルータに処理を引き継ぐまで、リクエストのすべての側面を処理する
    • すべてのリクエストに適用するPlugの主要なセットを提供する
    • 指定されたルータにリクエストを割り当てる
  • ルータ
    • 受け取ったリクエストを解析し、適切なコントローラ/アクションに、必要に応じてパラメータと共に割り当てる
    • リソースへのルートパスとURLを生成するヘルパーを提供する
    • パイプラインという名前で定義された機能を使って、リクエストを渡すことができる
    • パイプライン
      • ルートのセットで、Plugグループが簡単に利用できるようにする
  • コントローラ
    • リクエストを処理する、アクションと呼ばれる機能を提供する
    • アクション
      • データを準備し、ビューに渡す
      • ビュー経由でレンダリングを実行する
      • リダイレクトを行う
  • ビュー
    • テンプレートをレンダリングする
    • プレゼンテーション層として振る舞う
    • テンプレートで利用可能な、プレゼンテーション用のデータを装飾するヘルパー関数を定義する
  • テンプレート
    • テンプレートは顔文字表現のようなものだ
    • テンプレートは事前コンパイルされ、高速に動作する
  • チャネル
    • 簡単にリアルタイム通信用のソケットを管理する
    • チャネルは、チャネルが永続コネクションとの双方向通信を許可していることを除いて、コントローラに類似している
  • PubSub
    • チャネルレイヤーの下にあり、クライアントはトピックを購読(サブスクライブ)することができる
    • サードパーティのpubsubインテグレーションのために、基底となるpubsubアダプタを抽象化する

プラグ(Plug)

Plugは、Webアプリケーションを作るために利用する、組み立て可能なモジュールを構築するための仕様です。 プラグは、その仕様によって作られた、再利用可能なモジュール、または関数です。 それらは、リクエストヘッダの解析やロギングのように、別個の動作を提供します。 Plug APIは小さく、一貫しているため、複数のプラグを定義し、パイプラインのようにセットした順で実行することができます。 それらは、プロジェクト内、または別のプロジェクトで再利用することもできます。

プラグには、認証からパラメータの事前処理まで、ほぼ全ての処理を記述することができます。レンダリングでさえ記述可能です。

Phoenixは全般的に、プラグによって大きなアドバンテージを得ています。ルータとコントローラが特にそうです。

プラグで最も重要なことの一つは、それが最終的に私たちのユーザーにアプリケーションコンテンツを配信するHTTPサーバへのアダプタを提供しているということです。 現在のところプラグは、99sのLoïc HoguinによってErlangで書かれたWebサーバであるCowboyのアダプタのみ提供しています。

より詳しい内容については、Plugガイドをご覧ください。

Ecto

Ectoは、クエリ組み立てツールと、データベースラッパーを統合したElixirのための言語です。 Ectoを使うことで、異なるデータベースへのRead/Write、ドメインデータの作成、型安全な方法での複雑なクエリ記述、SQLインジェクションを含む攻撃ベクトルからの保護など、多くのことができます。

Ectoは、4つの主要な抽象概念を中心に作られています:

  • Repo - リポジトリは個々のデータベースへの接続を表します。全てのデータベース操作は、リポジトリを介して行われます。

  • Model - モデルはデータ定義です。テーブル名やフィールドだけでなく、各フィールドの型を定義します。またモデルは、モデル間の関係も定義します。

  • Query - クエリは、モデルとリポジトリの両方を一緒に結びつけます。これにより私たちは、リポジトリからデータをエレガントに取得し、モデルにデータをキャストすることができます。

  • Changeset - チェンジセットは、アプリケーションがモデルデータを使用する前に、モデルデータに実行する必要のある変換内容を宣言します。これらは、型変換、検証など多数の要素を含みます。

新しく作成したPhoenixのアプリケーションは、デフォルトでは、PostgreSQLのストレージに対するEctoを使用します。