遠距離でのSCP転送速度: CentOS7のNWパラメーターをチューニングしてみる（大きな改善なし）

#はじめに
遠距離になると、TCPはUDPに比べて劇的に転送パフォーマンスが悪化します。これは、TCPがUDPと違って受信応答をするプロトコルだからです。つまり、ある一定量送ったら、ちゃんと届いたよ、という応答をすることで、信頼性を上げるプロトコルだからです。
※いちおう、IBMだと、Aspera（http://www-01.ibm.com/software/jp/info/aspera/index2.html ）というUDPベースのファイル転送製品があります。

いちおうTCPも毎回毎回パケットの応答が返ってくるまで、次の送信ができないと困るので、一定量は応答がなくてもまとまって送れる仕様になっています。この一定量というのがWindow Sizeです。でもですね、、、、仮にWindow Sizeが64KBだとすると、帯域100Mbps(=12.5MB/sec)であっても、5msecぐらいでWindow Size分のデータはOSとしては送信しきってしまう訳です。SoftLayerのLooking Glass（http://lg.softlayer.com/ )を見ると、東京-シンガポール間は75-80msecぐらいなので、ほとんど受信待ちになってしまっています。というので、遠距離でのTCP転送はもうちょっとチューニングの余地がありそうです。iperfを使ってもよかったのですが、実データに即した計測をしたかったので、今回は単純にscpで送付してみました。

先に結論を書いておきますが、実はパラメーターを変更しても結果は若干ましになったかもっていう程度であり、劇的に改善はしませんでした。最近のKernelは結構転送を自動チューニングするらしく、もしかしたら手動で変更してもあまり影響を与えないのかも。。。平均20MB/sec=160Mbpsだし、遠距離でこの速度ならそんなに悪くない気はしますけどね。。。コメント求む！！！

注１)仮想サーバーでは、Jumbo FrameをONにしてMTUサイズを9000にすることはできません。今度、物理サーバーで計ってみたい。。。

#環境情報
クラウド環境:SoftLayer
回線：SoftLayerのPrivate NW。
サーバーロケーション: 東京とシンガポール（Looking glassによると75msec)。pingの結果も74.3ms。
サーバー種類: 仮想サーバー（CentOS7, vCPU=2, Memory=2GB, vNIC=1Gbps）

```test:ping
[root@perftesttok02 ~]# ping -c 5 10.116.21.164
PING 10.116.21.164 (10.116.21.164) 56(84) bytes of data.
64 bytes from 10.116.21.164: icmp_seq=1 ttl=56 time=74.3 ms
64 bytes from 10.116.21.164: icmp_seq=2 ttl=56 time=74.3 ms
64 bytes from 10.116.21.164: icmp_seq=3 ttl=56 time=74.3 ms
64 bytes from 10.116.21.164: icmp_seq=4 ttl=56 time=74.3 ms
64 bytes from 10.116.21.164: icmp_seq=5 ttl=56 time=74.3 ms

--- 10.116.21.164 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4005ms
rtt min/avg/max/mdev = 74.333/74.352/74.381/0.299 ms

[root@perftesttok02 ~]# uname -a
Linux perftesttok02 3.10.0-327.4.5.el7.x86_64 #1 SMP Mon Jan 25 22:07:14 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

[root@perftesttok02 ~]# cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)

```



#デフォルトの転送速度

5Gデータを3回転送。

```
[root@perftesttok02 ~]# dd if=/dev/zero of=5GB.data bs=1M count=5120
[root@perftesttok02 ~]# du -sm 5GB.data
5126    5GB.data

[root@perftesttok02 ~]# time scp -r 5GB.data root@10.116.21.164:/root/
5GB.data                                                                       100% 5120MB  15.7MB/s   05:27

real    5m28.554s
user    0m34.303s
sys     0m11.851s

[root@perftesttok02 ~]# time scp -r 5GB.data root@10.116.21.164:/root/
5GB.data                                                                       100% 5120MB  17.5MB/s   04:52

real    4m52.294s
user    0m33.899s
sys     0m11.821s

[root@perftesttok02 ~]# time scp -r 5GB.data root@10.116.21.164:/root/
5GB.data                                                                       100% 5120MB  16.0MB/s   05:21

real    5m22.219s
user    0m34.266s
sys     0m11.828s

```



#チューニング実施

http://www.cyberciti.biz/faq/linux-tcp-tuning/
を参考に、両サーバーでチューニング実施。

```
actual values(minimum size, initial size, and maximum size)
# cat /proc/sys/net/ipv4/tcp_mem
42411   56548   84822

The default and maximum amount for the receive socket memory
# cat /proc/sys/net/core/rmem_default
212992
# cat /proc/sys/net/core/rmem_max
212992

The default and maximum amount for the send socket memory:
# cat /proc/sys/net/core/wmem_default
212992
# cat /proc/sys/net/core/wmem_max
212992

The maximum amount of option memory buffers:
# cat /proc/sys/net/core/optmem_max
20480

TCP Window Scaling
# cat /proc/sys/net/ipv4/tcp_window_scaling
1

最大バッファーサイズとして12MBを割り当て
# echo 'net.core.rmem_max=12582912' >> /etc/sysctl.conf
# echo 'net.core.wmem_max=12582912' >> /etc/sysctl.conf
# echo 'net.ipv4.tcp_rmem= 10240 87380 12582912' >> /etc/sysctl.conf
# echo 'net.ipv4.tcp_wmem= 10240 87380 12582912' >> /etc/sysctl.conf

Turn on window scaling
# echo 'net.ipv4.tcp_window_scaling = 1' >> /etc/sysctl.conf

Enable timestamps as defined in RFC1323:
# echo 'net.ipv4.tcp_timestamps = 1' >> /etc/sysctl.conf

Enable select acknowledgments:
# echo 'net.ipv4.tcp_sack = 1' >> /etc/sysctl.conf

TCP will not cache metrics on closing connections:
# echo 'net.ipv4.tcp_no_metrics_save = 1' >> /etc/sysctl.conf

Set maximum number of packets, queued on the INPUT side, when the interface receives packets faster than kernel can process them
# echo 'net.core.netdev_max_backlog = 5000' >> /etc/sysctl.conf

設定の反映
# sysctl -p
```

#チューニング後の転送速度

5Gデータを3回転送。

```
[root@perftesttok02 ~]# time scp -r 5GB.data root@10.116.21.164:/root/
5GB.data                                                                       100% 5120MB  18.2MB/s   04:41

real    4m42.667s
user    0m34.178s
sys     0m12.974s

5GB.data                                                                       100% 5120MB  21.8MB/s   03:55

real    3m56.087s
user    0m33.805s
sys     0m14.351s


[root@perftesttok02 ~]# time scp -r 5GB.data root@10.116.21.164:/root/
5GB.data                                                                       100% 5120MB  19.5MB/s   04:23

real    4m24.794s
user    0m33.962s
sys     0m14.169s

```