woshidan's loose leaf

ぼんやり勉強しています。

型が指定できないフォーマットのデータに入っている値の型を信用しない。フォールバック処理をデフォルトで動くからで止めずに確認する

こないだ、JavaScriptのコードからJavaのコードへ値を引き渡すとき、JSONの文字列にして渡すことがありまして。

そのときに受けたレビューで、Javaが期待している型が String だけど、JavaScriptからは Array だって Int だって入れられるのでは、という指摘があってなるほどーと思ったのでメモ。

TL;DR

  • 違う型に変換するときは、パースが通る/期待していた通りの型に変換されていることまでは意識がいっていた
  • 異なる言語から、型が指定できないフォーマットで値を受け取るときは、相手がこちらが期待していない型で入力していた場合の振る舞いについて考慮が必要
    • defaultで変換してくれるクラスがあったりすると、上記の仕様のことを忘れやすい

状況説明

どう言う感じかと言うと、

var url = 'woshidan://example?data=' + JSON.stringify({ data: [1, 2, 3]}); // この
$.get(url);

と書いたら、

String requestUri; // = "{ \"data\" : [1, 2, 3]}";
JSONObject requestJSON = new JSONObject(requestUri); 

みたいな感じになる場合、JavaScript書いた人は ArrayJavaへ送ったと思っていそうですよね。

でも、Java側で getString() してしまうと、

"[1, 2, 3]"

というString型の値が取れてしまう。

ここで、想定外の型(Array )が来てもなんでもStringに直すようにするのか、それともそこでこのキーは String 型しか入らないんですが、 Array 型入れてるのはなんでですかね、みたいにメッセージ出すか、みたいなことが考えられるといいですね。

Webサーバのkeepaliveとは

久々に書いておいて、めっちゃざっくりした感じででかく出たタイトルだな、と思ったんですが、まぁここloose leafですしね。

この記事では、「keepalive」という言葉が、webサーバの設定でどう言う意味を指すか、みたいなところを確認します。

TL;DR

  • TCP/IPだと1度のリクエストとレスポンスごとにTCPコネクション貼り直す
  • 勿体無いので一回貼ったコネクションは使いまわそう -> keepalive
  • 具体的に言うと、一つのページの中で画像とかの素材を読み込んで… みたいなので細かくリクエストが発生する場合とか効きそう、という想定があるらしい
  • コネクション張っている = リクエストを待ち受ける以外何もしていないスレッドやプロセスがある、ということなのでコネクションをずっと維持していればいいと言うものでもない
  • 1回通信を実行した(=1回分レスポンスを返してから)、どの程度サーバが待ち受けているか、であって、1回分のレスポンスにかけてよい最大時間ではない

今回するkeepaliveってどの辺の話

キープアライブ (keepalive) とは、コンピュータネットワークにおいて、2つの装置間の接続が有効であることを確認し、また、接続が切断されるのを防止するために、装置間で定期的に送信される通信のことである。

キープアライブ - Wikipedia

たとえば、TCPでデータを転送する前にはコネクションを確立する必要があります。

コネクションの確立にあたって、サーバ・クライアントがそれぞれこちらの記事のように状態を遷移させていますが、他方に遷移に伴う通知を行う前に終了した場合など、サーバとクライアントの状態が中途半端なことになってしまうこともあり得ます。

そこで、あらかじめ決められた周期で信号を送信し合うことにして、通信ができる状態か確認するようにしましょうや、という機能が「keepalive」というそうです。

HTTPのヘッダを利用して行う場合と、TCPのパケットに乗っけて行うことがありますが、TCPの方は拡張機能でデフォルトでは無効にされており*1、「keepalive」あるいは「keepalive 設定」といったら、どうもHTTPキープアライブを指すことが多いようです。

で、タグにnginxって入れてるんですが、このHTTP keepaliveはWebサーバのレスポンスに「Connection: Keep-alive」ヘッダを入れてくれって話なので、Webサーバであるnginxとかapacheとかそのレイヤーの設定の話なんでしょうかね。

nginxで利用できるkeepaliveとは

HTTPで喋るWebサーバの話なんで、「HTTP通信をするとき、TCP/IPだと本当は一回ずつコネクションを貼らなければいけないが、キープアライブが有効ならコネクションを張ったままにして、一つのTCPコネクションで複数回「コマンド」と「応答」がやり取りできるようにする」くらいの意味になります。

nginxの場合、

あたりがkeepaliveに関連するディレクティブです。

keepalive_timeout はサーバが一つのクライアントからの接続を何秒くらいオープンにしたままにしておくか、と言う値で、

keepalive_timeout 75s;

のように指定すると、HTTPのレスポンスヘッダに

Connection: keep-alive

と追加されます。長すぎると、もう不要になったコネクションが滞留して、最悪しばらく新しいコネクションが作成できなくなったり、コネクションプールにメモリが食われたりします。0だとkeep alive無効です。

keepalive_requests は keepalive_timeout > 0 の時に有効で、持続的な接続上で許可されるリクエストの数を設定します。

たとえば、nginx でKeepAliveを設定してみる | レンタルサーバー・自宅サーバー設定・構築のヒントからの引用となりますが、

keepalive_requests 100;
keepalive_timeout 75;

の場合は、クライアントから要求がきたら、一度張ったコネクションをそのままに同じクライアントからの再要求を75秒待ちますが、そのコネクションが有効な間に、同じクライアントからの要求が100件を超えたら、待つのを止めます。

一般的な設定で、1ページの必要なリンク先(画像やCSSなど)が、概ね100個を超えないということと、遅くとも75秒以内には、再要求がくるだろう・・・という前提条件のもとの設定 だそうです。

コネクションを張ったままにしているというのは、言い方を変えるとリクエストを待ち受けている(=他のことをしていない)スレッド or プロセスが用意されているということなので、長い or 多ければいいというものではなさそう。

また、わかりにくいのですが、1回通信を実行した(=1回分レスポンスを返してから)、どの程度サーバが待ち受けているか、であって、1回分のレスポンスにかけてよい最大時間ではないみたいです。

現場からは以上です。

参考

$ANDROID_HOMEってどこさ

環境変数 JAVA_HOMEとANDROID_HOMEと、時々、PATH

Android SDKのパスのことで、ここだ。

f:id:woshidan:20170307024420p:plain

なお、$NDK_ROOTなどを聞かれた場合は、$ANDROID_HOME/ndk-bundleであることが多い。

sdk$ ls
add-ons     docs        lldb        platform-tools  sources     tools
build-tools extras      ndk-bundle <-    platforms   system-images
cmake       licenses    patcher     skins       temp

Xcode Command Line Toolsのインストール

Apple IDでサインインして下記URLへ。

Sign in with your Apple ID - Apple Developer

利用するバージョンのCommand Line Toolsを探してDL(いくつかツール種別のチェックを外した方が探しやすい).

f:id:woshidan:20170228005131p:plain

あとはDLしたインストーラをぽちぽちすればOK.

Homebrewでgitのバージョンを上げた後、実行されるバージョンを変える

本当は、

brew uninstall git
brew update
brew install git

すればいいんだけど、慌てて後者だけやって、Homebrewの管理するディレクトリが二つできて、名前順で古い方が優先されてどうしようかな、ということに(なぜだ)。

もう少し状況をまとめると

  • 新しい方のパス /usr/local/Cellar/git/2.12.0
  • 古い方のパス /usr/local/Cellar/git/1.9.0
  • 古い方のパスはHomebrewでインストールしたコマンド用のパス /usr/local/bin/git にリンクされてる

こういう感じ。

結局

// 古い方をてきとうなディレクトリへ退避
mv /usr/local/Cellar/git/1.9.0 ./temp/git
// 新しい方ので呼び出されてくれないだろうかと期待してgit --version
$ git --version
bash: /usr/local/bin/git: No such file or directory
// なるほどリンクされた先のパスのファイルはさっき消したのでそれはそうですね
// いまは一つしかgitいないし、新しい方のgitが使われるだろうから brew linkすればいいのかな
$ brew link git
Linking /usr/local/Cellar/git/2.12.0... 419 symlinks created
$ git --version
git version 2.12.0
// 古い方はいらないので消す
$ rm -rf ~/temp/git

なまら面白かったので単純に日記が書きたかった…

使い道がよくわからなかったのでScaleDrawableで遊んでみた

楽しい。

f:id:woshidan:20170210001205g:plain

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int i = new Random(System.currentTimeMillis()).nextInt(8000);
                ScaleDrawable sd = (ScaleDrawable)imageView.getDrawable();
                sd.setLevel(i);
            }
        });
<ImageView
  android:id="@+id/imageView"
  android:src="@drawable/scaletest"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content" />
<?xml version="1.0" encoding="utf-8"?>
<scale
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/icon"
    android:scaleGravity="center"
    android:scaleHeight="80%"
    android:scaleWidth="80%"/>

Rubyのgemをインストール際に要求されるnative extensionとは何者か

stackoverflow.com

gemのnative extenstionは、それの事前インストールを必要とする別のライブラリ(gem)とリンクさせてもよいRubyが動く環境(rbenvなどの管理下ではなくPCなど)に入っている、主にCやC++などで書かれるライブラリ。

それの事前インストールを必要とする別のライブラリ(gem)とリンクさせてもよい

とは、たとえば、ImageMagicのnative extensionとして入れた画像処理系のライブラリをRMagickのnative extensionとして利用してもよい。

ただ、用語としては単に「(そのgemは)あなたのマシンにコンパイルされている必要があるいくらかのコードを含んでいる」ということを意味しているだけ。

あなたのマシンのRubyが、requireキーワードで、コンパイル & リンクされた結果のexeファイルを呼び出せるように(自信がない)。

下記のあたりを読んでみるとよさそうなので、また今度読みます。

library mkmf (Ruby 2.4.0)