mod-wsgi を python3.5.0 + pyenv + Apache2 で、AmazonLinux 上に構築

mod-wsgi は、python と1:1で紐付いているため、apacheに1つまでしか追加できない。

pyenv を入れる

公式に書いてあるとおり。
yyuu/pyenv · GitHub

$ git clone https://github.com/yyuu/pyenv.git ~/.pyenv
・・・

python3 を入れる

このときに、オプションを付ける必要があります。
global にしても、しなくてもよいです。

$ CFLAGS="-fPIC"  pyenv install 3.5.0
$ pyenv global 3.5.0

apache2 を入れる

$ sudo aptitude install httpd
$ sudo aptitude install httpd-devel

mod_wsgi を入れる

以下の方法でインストールしてしまうと、system の python がつかわれる。

$ sudo aptitude install libapache2-mod-wsgi-py3 

*1

mod_wsgi.tar.gz をダウンロード

公式からダウンロード

install

python のパスを指定します。

$ tar zxvf mod_wsgi.tar.gz
$ cd mod_wsgi
$ ./configure --with-python=/home/username/.pyenv/versions/3.5.0/bin/python
$ make
$ sudo make install

apache2 設定

<VirtualHost *:80>

  ServerName   hoge.test
  ServerAdmin  server-mail@hoge.test
  DocumentRoot /hoge/public

  WSGIScriptReloading On
  WSGIDaemonProcess  my_name python-path=/home/username/.pyenv/versions/3.5.0/lib/python3.5/site-packages python-home=/home/username/.pyenv/versions/3.5.0  user=apache group=apache processes=2 threads=25
  WSGIProcessGroup   my_name
  WSGIScriptAlias    /  /hoge/app.wsgi

  <Directory "/hoge/">
    Order deny,allow
  </Directory>
</VirtualHost>

追加で、
LoadModule による wsgi のロードと、の設定が必要。
WSGISocketPrefix /var/run/wsgi

トラブルシューティング

Fatal Python error: Py_Initialize: Unable to get the locale encoding
ImportError: No module named 'encoding'

python-home、 python-path が間違っている可能性があります。

python-home は、python コンパイルオプションの、prefix と同じにします。
確認方法は以下。

$ python
>>> import sysconfig
>>> sysconfig.get_config_vars('CONFIG_ARGS')

python-path は、site-packages までのパスを設定します。

/home/username にアクセス出来ていない可能性があります。
chmod 755 /home/username

pyenv のインストール先を変更するのでも良いと思います。

(13)Permission denied: mod_wsgi (pid=23797): Unable to connect to WSGI daemon process '***' on '/etc/httpd/logs/wsgi.12880.0.1.sock' after multiple attempts., referer: http://dummy.test

socket ファイルにアクセス出来ていない可能性があります

WSGISocketPrefix の設定を変更する

*1:ただし、pyenv で管理しているの system python は、python (version2) で、 python3 を使う場合は、3を付けます。

Unity から C++ 側でallocした配列にアクセスする

C++で new し、C#側で一旦コピー、さらにC++で削除

hoge.h
#pragma once

#define DLL_UNITY extern "C" __declspec(dllexport)

typedef unsigned char byte ;

DLL_UNITY void loadData (byte** data, int* dataSize);
DLL_UNITY void freeData (byte** data);
hoge.cpp
#include "hoge.h"

void loadData(byte** data, int* dataSize) {

	int s = 10;
	byte* d = new byte[size];

	// ...

	*data = d;
	*dataSize = s;
}

void freeData(byte** data) {
	delete[] *data;
	*data = 0;
}
MyData.cs
using UnityEngine;
using System;
using System.Runtime.InteropServices;

public class MyData {

    [DllImport("libhoge")]
    public static extern void loadData (ref IntPtr data, ref int dataSize);

    public static void loadData (ref byte[] data) {

        IntPtr buff = IntPtr.Zero;
        int buffSize = 0;

        loadData(ref buff, ref buffSize);

        byte[] result = new byte[buffSize];
        // コピーしてから使う
        Marshal.Copy(buff, result, 0, buffSize);

        freeData(ref buff);
    }

    [DllImport("libhoge")]
    public static extern void freeData(ref IntPtr data);
}

ViewPager 利用時、 FragmentManager 内に Adapterで返しているより少ない数しか入っていない

FragmentPagerAdapter で 返すデータ数が、実際に3つあっても、
タブで1番目に切り替えを行うまで、FragmentManager の中には、2つしかFragmentが入っていないような動きになっていた。

List<Fragment> datas = getSupportFragmentManager().getFragments();
// 2つだけ

setOffscreenPageLimit で、最後のIndexを設定すると解決する。

final ViewPager viewpager = (ViewPager) findViewById (R.id.main_view_pager);
viewpager.setAdapter(adapter);
viewpager.setOffscreenPageLimit (datas.size() - 1);

knife solo cook 実行時、ERROR: undefined method `cheffish' for nil:NilClass

ubuntu でknife-solo を実行した時に以下のエラーが出た。

ERROR: undefined method `cheffish' for nil:NilClass

chef のバージョンが関係しているようだったので、

$ knife solo prepare sample-host -v
$ 12.4.1

新しいものをインストールした。ところ、問題がなくなった。
前の12.3.0でも良いという記述も見つけた。

$ knife solo prepare sample-host --prerelease

AWS EC2 スポットインスタンス 制限緩和のリクエスト

ケースの作成

左メニューの制限ボタンを押し、
制限緩和のリクエスト を更に押します。

CCには、自分のメールアドレスを忘れない。


制限タイプは、スポットインスタンスの項目が無いですが、「EC2インスタンス」を選び、
新しい制限値「200」

申請理由の説明に、
「テレビ放送があり、アクセスに耐えられないため。
スポットインスタンスの増加をお願いします。」

連絡方法「Web」

的なことを書いたところ、いつの間にかスポットインスタンスの制限が200に上がっていました。
他いくつかのオンデマンドインスタンスの制限も、200になっていました。

nginx Rails Mysql の構成で、アクセス負荷に耐えるためとりあえずやっておくこと

Too many open files

nginx (/etc/nginx/nginx.conf)

# CPU と同じ数
worker_processes  8;

# worker_connections の 4倍程度
# failed (24: Too many open files)  に対処できる。
worker_rlimit_nofile  40960;

events {
  # とりあえずこの値
  worker_connections 10240;
}
open file が増えているかを確認
# これでpid を確認し、
$ ps ax | grep nginx | grep worker
# 数字に、pid を入れる。
$ cat /proc/5618/limits

Resource temporarily unavailable

net.core.somaxconn (/etc/sysctl.conf)

こちらも処理するキューに貯められる最大値。backlog と小さいほうが優先される。

# デフォルトは 1024。とりあえずこの値にする。
# failed (11: Resource temporarily unavailable) に対処できる。
net.core.somaxconn = 65535

再読み込み

sysctl -p

MySQLでtoo many connections

Rails (unicorn.rb)

worker が1増えると、db への connection が1増えるため、max_connection の値には注意する。
DBのpool は、DBの接続数にあまり意味が無い。

DB の connection 数を確認する

worker にアクセスがなければ、unicorn が起動していても connection が増えない場合もあるので注意する。

show status like 'Threads_connected';
DB の max_connection 数を確認する

この値を超えてしまった場合は、DBへ接続できないということになる。ただし、単純にDBのmax_connection を増やしてしまうと、DB 側のメモリ消費が増えてしまう。

show variables like 'max_connections';
# メモリを最大限消費する数にする。多すぎると、swapが発生し、遅すぎて処理ができなくなる。実際にworker へアクセスされた時にメモリ消費が増えるため、起動した時の値だけで判断してはいけない。
# failed (110: Connection timed out) に対処するための一つの要素。
worker_processes 10

# backlog に、キューに積み上げられる最大数を設定する。
# failed (11: Resource temporarily unavailable) に対処できる。
listen "/var/sample.sock", backlog: 8192