karszawa / sign-of-horns

ISUCON 7 Qual Repository :metal:
0 stars 1 forks source link

Unix Domain Socket #8

Open karszawa opened 6 years ago

karszawa commented 6 years ago

なにをやるか

nginxとアプリケーションの間の通信をTCP/IP通信からUnix Domain Socketに置き換える

なぜやるか

Unix Domain Socketは同一ホスト内での通信を高速に行うことができる。 Webサービスの場合は、Webサーバーとアプリケーションの間の通信を高速化するために利用できる。 (nginxの場合はTCP/IP通信を用いてWebサーバー/アプリケーション間の通信を行っている場合がある)

どうやるか

/etc/nginx/nginx.conf

http {
  upstream app {
    server unix:/tmp/nginx.sock;
  }
}

Application

ハンドラ登録後、unixソケットを介してリッスンする

func main() {
    mux := http.NewServeMux()

    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("<h1>It works!</h1>\n"))
    })

    listener, err := net.Listen("unix", "/tmp/nginx.sock")
    if err != nil {
        log.Fatalf("error: %v", err)
    }
    defer func() {
        if err := listener.Close(); err != nil {
            log.Printf("error: %v", err)
        }
    }()

    shutdown(listener)
    if err := http.Serve(listener, mux); err != nil {
        log.Fatalf("error: %v", err)
    }
}
// 割り込み終了処理
func shutdown(listener net.Listener) {
    c := make(chan os.Signal, 2)
    signal.Notify(c, os.Interrupt, syscall.SIGTERM)
    go func() {
        s := <-c
        if err := listener.Close(); err != nil {
            log.Printf("error: %v", err)
        }
        os.Exit(1)
    }()
}

注意点

あとはnginx.confのいっちばん上に

user isucon;  

と記述するという手もある(ここでisuconはunix domain socketを生成するユーザー名)

gojiについては実行時引数の--bindに/var/run/webapp/webapp.sockを設定してあげればunix domain socketを用いることができる。