koukiblog

たぶんweb系の話題

Go言語の関数とループ

A Tour of Goを進めてたのでその備忘


問題:
関数とループを使った簡単な練習として、 ニュートン法 を使った平方根の計算を実装してみましょう。

ニュートン法は、開始点 z を選び、以下の式を繰り返すことによって、 Sqrt(x) を近似します:

https://go-tour-jp.appspot.com/content/img/newton.png


最初は、その計算式を10回だけ繰り返し、 x を(1, 2, 3, ...)と様々な値に対する結果がどれだけ正解値に近づくかを確認してみてください。

次に、ループを回すときの直前に求めたzの値がこれ以上変化しなくなったとき (または、差がとても小さくなったとき)に停止するようにループを変更してみてください。 この変更により、ループ回数が多くなったか、少なくなったのか見てみてください。 math.Sqrt と比べてどれくらい近似できましたか?


回答:
gist.github.com

docker toolboxで作成したdocker0のアドレス帯の変更

デフォルトでは 172.17.0.0/16 が使用されているが、社内ネットワークの都合でこれを変更したかったのでその方法です。

docker toolboxを利用する場合、docker-machineを利用して、boot2dockerのVMが起動していると思います。

docker-machine ssh

でdocker daemonが起動しているサーバにログインして以下の作業を行います。

まずdockerを停止

docker stop

既存のbridgeを削除します。

ifconfig docker0

で、docker0インタフェースに172.17.0.0/16が設定されていることがわかります。
この設定を残したまま、dockerの起動時オプションに別にアドレス帯を指定してもエラーになってしまうので、まず削除します。

ip link del docker0 

で削除。

あとはdocker daemonをbipオプションを渡して起動する。

あまりよい方法ではないですが、
boot2docker/docker at master · boot2docker/boot2docker · GitHub

    /usr/local/bin/docker daemon -D -g "$DOCKER_DIR" -H unix:// $DOCKER_HOST $EXTRA_ARGS >> "$DOCKER_LOGFILE" 2>&1 &

    /usr/local/bin/docker daemon -D --bip=192.168.42.1/24 -g "$DOCKER_DIR" -H unix:// $DOCKER_HOST $EXTRA_ARGS >> "$DOCKER_LOGFILE" 2>&1 &

として、dockerを起動すると、 192.168.42.1/24 が適用されます。

ifconfig docker0

で結果が確認可能

参考:
Dockerのネットワークの基礎 | SOTA

mackerel-agentをchefでamazon-linuxにインストールするとエラーになった件

公式の手順にあるようにchefのcookbookを利用してインストールすると、サービスの起動時にエラーになる。

mackerel.io

エラーの内容は以下

Starting mackerel-agent:/etc/init.d/mackerel-agent: 36 :  7214 Trace/breakpoint trap   $BIN ${APIBASE:+--apibase=$APIBASE} ${APIKEY:+--apikey=$APIKEY} --pidfile=$PIDFILE --root=$ROOT $OTHER_OPTS >> $LOGFILE 2>&1

結論:
最新版(v1.2.1)を利用する

cookbook 'mackerel-agent', tag: 'v1.1.0'

ではなく

cookbook 'mackerel-agent', tag: 'v1.2.1'

以下調べた履歴

mackerel.io
で、Amazon Linux AMI 2016.03での不具合が報告されているものの、修正済みのはず。

試しにchefではなく公式の手順で手動でインストールしてみると問題なくインストールできる。
手順は下記の内容
mackerel.io

この手順で入るってことは、何か別のものをインストールしているのかも?ってことで公式の手順にある "https://mackerel.io/file/script/amznlinux/setup-yum.sh"の内容を確認してみると

# import GPG key
  gpgkey_path=`mktemp`
  curl -fsS -o $gpgkey_path https://mackerel.io/assets/files/GPG-KEY-mackerel
  rpm --import $gpgkey_path
  rm $gpgkey_path

  # add config for mackerel yum repos
  rpm -ivh http://yum.mackerel.io/amznlinux/latest/x86_64/mackerel-repo-1-0.noarch.rpm

となっていて、amazon linux用のレポジトリを用意している様子。
一方chefのrecipeは

if platform?('centos') or platform?('redhat') or platform?('amazon')
~
yum_repository "mackerel" do
    gpgkey gpgkey_url if yum_cookbook_ver >= Gem::Version.new('3.0.0')
    description "mackerel-agent monitoring"
    url "http://yum.mackerel.io/centos/$basearch"
    action :add
  end

となっていて、これが原因だった。

"http://yum.mackerel.io/centos/$basearch"を"http://yum.mackerel.io/amznlinux/$releasever/$basearch"に書き換えたところ問題なく動作した。

そしてここまでたどり着いたところで、最新のレポジトリでは対応済みなことに気づいた。。
Support Amazon Linux repo · mackerelio/cookbook-mackerel-agent@499d779 · GitHub

PhoenixでHTTP Headerを利用した認証を行う

PhoenixAPIを実装するときに、http headerを利用して簡易な認証を行う時の方法。
http headerで認証を行うplugを作成します。

/web/plugs/api_auth.ex

defmodule App.Plug.APIAuth do
  import Plug.Conn

  def init(default), do: default

  def call(conn, auth_header) do
    {key, value} = auth_header
    header = Enum.find(conn.req_headers, &elem(&1, 0) == key)

    if header && elem(header, 1) == value do
        conn
      else
        send400 conn
    end
  end

  defp send400(conn) do
    conn
    |> put_resp_content_type("text/plain")
    |> send_resp(400, "Bad Request")
    |> halt
  end
end

Phoenixの場合、http headerはconn.req_headersで取得できるのでそれを利用します。
{key,value}のtupleのリストになっています。
Plug.Conn – Plug v1.1.6

作成したPlugをRouterに設定すれば完了です。

web/router.ex

  pipeline :api do
    plug :accepts, ["json"]
    plug App.Plug.APIAuth, {"x-sample-key", "xxxxx"}
  end

環境毎に変更する場合は、configに追記して、Application.get_env で取得すればok

phoenix以外からphoenixのchannelを利用する

Rails + node.js(+socket.io) で作ったアプリの、node.jsの部分をphoenixに置き換えてみたときに必要だった。

phoenixのchannelのclientは
github.com
にあり、このファイルを利用すればよい。
es6で書かれているが、他のファイルに依存はしていないので、babelでコンパイルしたものを配置すればok。
phoenix.jsを読み込んでしまえば、phoenixチュートリアルにあるように

  var phoenix = require("phoenix");

  socket = new phoenix.Socket("/socket", {params: {token: window.userToken}});

のようにして利用できる。

別のwebアプリケーションからphoenixのchannel使いたいケースって結構ありそうだけど、現状はこれしか方法なさそう。
(とはいえ、socket.ioほど分厚い仕様があるわけではないので、client自作してしまうのあり)

ちなみに、他の言語のクライアントは現在以下の3つらしい。

iOS
github.com


Android
github.com

C#
github.com