月別アーカイブ: 3月 2013

ネットワークチューニング

OSのネットワークカーネルチューニングについて色々なサイトを参考にまとめてみました。
自分自身でもよく使うものなので備忘録として残そうと思います。

多くのネットワークチューニングで最も通信速度に影響するのは、ネットワークのバッファサイズです。別名ウィンドウサイズとも呼ばれています。

このバッファサイズには受信と送信の2種類があります。一般的には、送信、受信ともに同じサイズで設定しまいがちなのですが回線は上下で帯域が違うものです。やはりシンメトリーな回線ではないケースが多いためそれを考慮して設定する事が大切です。

サーバがWEBサーバだけならリクエストは受信ですから、一般的に大きなパケットが来ることがありません。しかしWEBコンテンツに動画のような大きなファイルをアップロードする仕組みなら大きなパケットが来ることでしょう。このように回線だけではなく、コンテンツがどのようなものか理解してその性格を理解してチューニングすることが大切です。

おそい回線なら、バッファが大きいほうが処理速度が早く感じます。しかし、高速CPU、高速回線の場合はむしろほどほどにしておくほうが効率が良いです。バッファ・サイズを大きくすることで転送失敗のリカバリーに即時性がなくなるからです。
下記に指針としての式を用意しましたが、あくまでも一つの基準としてこれをベースに設定をいくつかためしにパフォーマンスを見てみましょう。

Buffer size = Bandwidth (bits/s) * RTT (seconds)

受信パケットサイズ)
net.core.rmem_default :デフォルトバッファ値
net.core.rmem_max :最大バッファ値

送信パケットサイズ)
net.core.wmem_default :デフォルトバッファ値
net.core.wmem_max :最大バッファ値

OSのデフォルトと最大値のバッファの使い分けの具体的なアルゴリズムはわからないが、TCP の送受信バッファのデフォルトサイズと最大サイズは
あるタイミングでデータの送受信の状況により相互にオーバーライドされるようです。

その他)
net.ipv4.tcp_window_scaling :ウィンドウバッファが64KBを超える場合、この設定値が1になっている必要があります。
net.ipv4.tcp_sack :ばらばらに届くパケットを整列して、足りないものだけを受信するように促すため受信効率があがる設定です。
net.ipv4.tcp_timestamps :再転送のタイムアウトの算出方法よりも正確な方法で RTT を算出するオプションです

net.ipv4.tcp_mem :最初の値は、メモリー使用量の最小しきい値を表します。次の値は、メモリー圧縮モードを開始してバッファー使用量を圧縮する際のしきい値を表します。最後の値は、メモリー使用量の最大しきい値を表します。最大しきい値に達すると、メモリー使用量を減らすためにパケットが破棄されます。BDP 値が大きい場合はこの値も大きくします (ただし、この値はメモリー・ページのサイズであって、メモリーの容量ではないことに注意してください)。

net.ipv4.tcp_wmem :
自動調整に必要な 1 ソケットあたりのメモリー使用量を定義するオプションです。最初の値は、ソケットの送信用バッファーに割り当てられている最小バイト数を表します。次の値は、システムに過大な負荷がかかっていない状態で、バッファーのサイズをどこまで大きくできるかのデフォルト値を表します (wmem_default によって上書きされます)。最後の値は、送信用バッファー・スペースの最大値を表します (wmem_max によって上書きされます)。

net.ipv4.icmp_destunreach_rate :ICMP 不達パケット (Destination Unreachable packet) を送る最大レート。 これは特定のルートまたは行き先にパケットを送信するレートを制限する。
net.ipv4.icmp_echo_ignore_all:この値が非ゼロの場合は、 Linux はすべての ICMP_ECHO 要求を無視する。
net.ipv4.tcp_max_tw_buckets :システムが同時に保持する time-wait ソケットの最大数。この数を越えると、time-wait ソケットは直ちに破棄され、警告が表示されます。この制限は単純な DoS 攻撃を防ぐためにあります。わざと制限を小さくしてはいけません。ネットワークの状況によって必要な場合は、 (できればメモリを追加してから) デフォルトより増やすのはかまいません。

cmp_echo_ignore_broadcasts :この値が非ゼロの場合は、 Linux はブロードキャストアドレスに送られたすべての ICMP_ECHO 要求を無視する。

net.ipv4.icmp_ignore_bogus_error_responses:これを設定すると、 ネットワーク上のホストが、 ブロードキャストアドレス向けとみなしたフレームに対して不正に反応したために発した ICMP error を無視します。
net.ipv4.icmp_echoreply_rate:ICMP_ECHOREQUEST パケットに応答する ICMP_ECHOREPLY パケットの最大送信レート。
net.ipv4.icmp_timeexceed_rate:ICMP_TIME_EXCEEDED パケットの最大送信レート。 これらのパケットはパケットがあまりに多くの hop を通過した場合に、 ループを防ぐために送られる。

net.ipv4.tcp_fin_timeout :ソケットを強制的にクローズする前に、最後のFINパケットを待つ時間(n秒)を指定する。DoS攻撃対策のために必要。defaultは60秒。

クライアント側)

net.ipv4.tcp_timestamps: 再転送のタイムアウトの算出方法よりも正確な方法で RTT を算出するオプションです (RFC 1323 を参照)。このオプションはシステムの性能向上のために有効にします。デフォルトは1です
実際には無効(0)が良いみたい。
nmapなどでuptime(システムの連続稼働時間)を探られるのを防ぐ。uptimeが分かると、いつからカーネルを更新してないかがバレる
NAT環境下に複数ホストがいてそいつらがクライアントのときに、WAN側のサーバに接続が切られるときnet.ipv4.tcp_timestamps = 0 にすると解消されるらしい。

サーバ側)
net.ipv4.tcp_keepalive_time:コネクションのタイムアウト時間の設定。例えば、サーバへの接続数が多いときに、タイムアウト時間を短くすると、より多くの接続をさばけるようになる。

net.ipv4.tcp_tw_recycle:短時間に数多くのクライアントが接続する場合、TCP/IPのソケット不足になりWebブラウザに「Internal Server Error」が表示される場合があります。上記情報を追加することで、ソケットを高速にリサイクルできるようになります。

ただし、サーバ側で net.ipv4.tcp_tw_recycle が有効で、クライアント側でTCPのタイムスタンプオプションが有効(Linuxの場合net.ipv4.tcp_timestamps = 1)だと、NAT/LBを超えたときにSYNを落としてしまい、接続障害になる。
ユーザー向けに使っているとSB携帯などで障害が発生してしまうようなので、使わないほうがいいかも。

net.ipv4.conf.all.rp_filter:送信元IPの偽装防止
net.ipv4.conf.default.rp_filter:送信元IPの偽装防止

OSのチューニング

LinuxのOSチューニングは、サーバを運営する人によって欠かせないものです。

サーバプログラムは様々なものがありますが、これらのプログラムはOSの核であるkernelからリソースを供給してもらい動作するからなのです。
よくある失敗はサーバの設定だけメモリ割り当てを増やしてしまい、OSのカーネル共有メモリの割り当てを行なっていない事です。

メモリはOSから供給されるわけですから、当然kernelがメモリをサーバプログラムへ渡す際に許容範囲というものが生じています。
故にkernel側でサーバプログラムに十分なメモリを提供するためのチューニングが必要となります。

このサーバプログラムに提供するメモリを共有メモリと言っています。
実際にはカーネルパラメータshmmax、shmallというのが共有メモリを調整するパラメータになります。

  • SHMALL システム全体の共有メモリ・ページの最大数
  • SHMMAX 共有メモリ・セグメントのバイト単位の大きさの上限
  • SHMMIN 共有メモリ・セグメントのバイト単位の大きさの下限

気を付けないといけないのは、SHMALLの値です。よくあるのはSHMALLとSHMAXの値を同じにしてしまう事ですが、実際は上記に書かれてある通り
SHMALLはページサイズを指定するのであり、バイト数ではありません。

カーネルのインクルードファイルlinux.hからすると以下の算定式で設定することがわかっています。
(kernel 2.6.32(CentOS6.3)から抜粋)
#define SHMALL (SHMMAX/PAGE_SIZE*(SHMMNI/16)) /* max shm system wide (pages) */
#define SHMMNI 4096 /* max num of segs system wide */

SHMALLの算定式は以下の通リです。
SHMALL= SHMMAX/4096 * (4096/16)
*SHMMAXはカーネルがアプリケーションなどに割り当てる共有メモリサイズの最大値を設定するのでユーザ毎に代入し計算してください。

Linux TIPS&実験室

ひさびさにリナックスサポートサイトをリニューアルしました。会社経営をしていることもあり中々時間をさけなくなっていましたが、また復活させて頑張ってサポート記事を書いていきたいと思います。

今回はサイト自体を、今はやりのレスポンシブ表示に対応させてみました。各種デバイスに合わせて最適な画面表示を行うようになっていますのでスマートフォンやタブレットでも見やすく表示させる事が可能です。

どうぞ今後ともよろしく御願いします。

Lesson24 実習3


named.conf

//
// named.conf
//
// Provided by Red Hat bind package to configure the ISC BIND named(8) DNS
// server as a caching only nameserver (as a localhost DNS resolver only).
//
// See /usr/share/doc/bind*/sample/ for example named configuration files.
//

options {

listen-on port 53 {
any;
};

directory "/var/named";
dump-file "/var/named/data/cache_dump.db";

statistics-file "/var/named/data/named_stats.txt";
memstatistics-file "/var/named/data/named_mem_stats.txt";
recursion yes;

dnssec-enable yes;
dnssec-validation yes;

dnssec-lookaside auto;

forwarders {
192.168.5.1;
};
/* Path to ISC DLV key */
bindkeys-file "/etc/named.iscdlv.key";

};

logging {
channel default_debug {
file "data/named.run";
severity dynamic;
};

};

zone "." IN { type hint; file "named.ca";
};

zone "example.org" { type master; file "example.org.zone";

};

zone "5.168.192.in-addr.arpa" IN {
type master;
file "example.org.rev";
};

include "/etc/named.rfc1912.zones";


example.org.zone


$ORIGIN example.org.
$TTL 1D

@ SOA dns.example.org. root.example.org. (
2012100502 ;serial

10800 ;refresh
3600 ;retry
604800 ;expire
86400 ) ; minimum(negative cache)

IN NS dns.example.org.

IN A 192.168.5.75

IN MX 5 mx.example.org.
dns IN A 192.168.5.75
www IN A 192.168.5.75
mx IN A 192.168.5.75


example.org.rev


$ORIGIN 5.168.192.in-addr.arpa.
$TTL 1D

@ IN SOA dns.example.org. root.example.org. (
2012101302 ; serial
3600 ; refresh 1Hour
900 ; retry 15min
604800 ; expiry 1w
3600 ; minimum 24Hour

);

IN NS dns.example.org.
IN A 192.168.5.75

75 IN PTR www.example.org.

Lesson33 実習5


post.php

<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8" />
<title>メール送信</title>
</head>

<body>

<?php

require_once "Mail.php";
//日本語文字コードをUTF-8で処理
mb_language("japanese");
mb_internal_encoding("utf-8");

//confirm.phpから受け取った送信内容を変数へセット
$button = $_POST['SendMail'];
if ($button != ""){
$mail_address = $_POST['Address'];
$mail_subject = $_POST['Subject'];
$mail_body = $_POST['MailBody'];

//SMTPサーバへ接続するためのアカウント情報
$params = array(
"host" => "example.org", //SMTPサーバ名
"port" => 587, //送信ポート25 or 587が一般的

"auth" => "PLAIN", //認証の方式、他に暗号化など色々ある
"username" => "ichinohe", //送信者名
"password" => "xxxxxxxx" //パスワード

);

//SMTPサーバへ接続
$mailObject = Mail::factory("smtp", $params);
$recipients = "ichinohe@netmars.mobi";
//FROMヘッダをISO-2022JPコードへ変換。ヘッダ情報にかんしては本文のコードとは別に考えISO-2022JPへ

//コード変換しMIMEエンコードするのが常識。そうしないと日本語が文字化けになる。
$fromstr = mb_encode_mimeheader(mb_convert_encoding($_POST['Sendar'],
"ISO-2022-JP","auto"))." < $mail_address > ";
//メッセージ本文へ表示されるヘッダ情報

$header = array(
"To" => "ichinohe@netmars.mobi",
"From" => $fromstr,

"Subject" => $mail_subject
);
//メッセージを送信
$ret=$mailObject -> send($recipients, $header, $mail_body);

//送信のエラー処理
if(PEAR::isError($ret)) {
die("送信失敗:".$ret->getMessage());
echo('もう失敗');
}

else{
echo('送信しました');
}
}

?>

<a href="index.php">TOP</a>

</body>
</html>