タイトルのとおりdocker pushはDocker 20から既定ですべてのタグをプッシュしなくなるという破壊的変更が行われた。
これまではdocker pushではすべてのタグをプッシュしていたが、変更後はlatestのみプッシュする。すべてのタグをプッシュしたい場合は--all-tags
(-a
)オプションを指定しなければならない。
自分はGCPのCloud Buildでdocker pushを使っていたが、これで1時間取られた。。
タイトルのとおりdocker pushはDocker 20から既定ですべてのタグをプッシュしなくなるという破壊的変更が行われた。
これまではdocker pushではすべてのタグをプッシュしていたが、変更後はlatestのみプッシュする。すべてのタグをプッシュしたい場合は--all-tags
(-a
)オプションを指定しなければならない。
自分はGCPのCloud Buildでdocker pushを使っていたが、これで1時間取られた。。
Windows10で英語キーボードを使う場合、バッククオート(`
)キーが半角/全角キーの代わりになり、IMEの切り替えに使われます。具体的にはAlt+`
とCtrl+`
がIME切替のショートカットになります。
※IME切替はIMEをオン/オフするという意味で使っています。
しかし、このIME切替ショートカットをユーザーが簡単に変更することはできません。コントロールパネルから簡単に変更できればよいのですが残念ながらできません。
Ctrl+`
を使いたい!私が困ったのが、この問題によりVSCodeでCtrl+`
を使えないということです。
同じ問題を抱えている方もおられるようです。
Windows上でVisual Studio Codeを使う際に英語キーボードのCtrl+backquote(`)が認識されない問題の対策 - Qiita
個人的にはIMEの切り替えにはAlt+`
しか使っておらず、Ctrl+`
は使っていません。Ctrl+`
というかなりアクセスしやすい位置にあるキーが死にキーになってしまっています。できればCtrl+`
を使えるようにしたい。
Windows10のIME切替ショートカットを変更するには、おそらくレジストリをいじる必要があると思いますが、できればそこまでの手間は掛けたくありません。
そこで見つけたのがMicrosoftが最近リリースしたKeyboard Managerです。PowerToysの機能のひとつになっておりレジストリを直接変更せずに簡単にキーをリマッピングできるという便利ツールです。
こちらを使って以下のように設定することで無事Ctrl+`
を使えるようになりました。
設定後はOS再起動が必要でした。またVSCode側では、workbench.action.terminal.toggleTerminal
にCtrl+F1
を割り当てています。
PowerToysを常駐させておけば、VSCode以外のアプリケーションも含めてCtrl+`
を使えるようになります。
PowerToysには他にもColor Pickerなど便利なツールが含まれています。いらない機能は機能毎に無効化することもできます。
PowerToys v0.25.0で動作確認済み。
いまさらながらASP.NET Core Razor Pages(以下Razor Pages)で小さなサイトを作ってみました。MSはRazor Pagesを推奨しているようですが、実際に使ってみてMVCから乗り換えるに値するものなのか判断できればいいなーと思っています。まだまだ分かっていない部分があるので間違っていたらご指摘頂ければと思います。
今回作成したRazor Pagesのプロジェクトと比較対象のMVCプロジェクトは以下のようなかんじです。.NET Coreバージョンの違いによる問題をPagesの問題と勘違いしている可能性があります。開発環境はVisual Studio 2019 16.4.2です。
プロジェクト | .NET Core Version | ページ数 |
---|---|---|
Razor Pages | 3.1 | ~20 |
MVC | 2.1 | 100+ |
MVCではページごとにViewModelクラスをいちいち作るのが面倒くさいです。ViewDataやViewBagもいまいちです。Pagesではcshtml.cs
に定義されるページ専用コントローラー兼ビューモデルであるPageModelクラスが自動で作成されます。これをそのままViewModelにすることができます。ビューに渡したいデータがあればPageModelクラスに新しいプロパティを追加してそれに値をセットすればビューから参照できます。もちろん型情報付きです。
つまりRazor Pagesはコントローラーをビューモデルと共用しているわけです。これは単一のビューに限定されたクラスだからできることだと思いますし、実際便利だと思いました。MVCではコントローラークラスは複数ページ共用なのでこれをやれないんですね。
Razor Pagesではページ毎に1ファイルというかんじになるので、フォルダ構造がそのままルーティング構造になります。Razor PagesではこのURLならこのファイルだなとすぐ分かります。
例えばAjaxアクションなどはページビューがないためRazor Pagesでは表現できないため、MVCで作ることになります。なのですべてのアクションをRazor Pagesに移行できるわけではないです。
Razor Pagesには独自のルーティングルールがあります。リンクもUrl.Action
ではなくUrl.Page
で作ります。すべてのアクションをRazor Pagesにするのであれば問題ありませんが、MVCと混在することを前提とした場合、ルーティングルールが2つあるというのはちょっと負担になります。
Razor Pagesでは1ページ毎に専用コントローラーになるので、MVCのように複数アクションでメソッドを共用したり、部分ビューを共用することがやりにくいです。
例えばCRUDのCreateとUpdateでフォームの部分ビューを作って共用したい場合、MVCでは各コントローラーのViewsフォルダ内に置けばよいですが、Razor PagesではSharedフォルダに置くことになります。Sharedフォルダが混雑しそうです。
またメソッド場合は、PageModelの継承クラスを定義したりすることになるのでしょうか。
デバッグ実行とデバッグなし実行を切り替えたり、ビルドを実行したりなどのタイミングで、ブラウザ更新をかけるとページが表示されない状態になります。MVCではそんなことありませんでした。
使用していると、変数名やクラス名を変更したりなどするタイミングでVSが応答なしになることがあります。復帰までに1分くらいかかります。1度この状態になると頻繁にこの現象が発生するのでVSを再起動しています。すると数時間は持ちます。アナライザが何やらしているような感じです。MVCではそんなことありませんでした。
*.cshtml
の変更だけでコンパイルが走るMVCでは*.cshtml
だけの変更であれば1秒未満で反映できていましたが、Razor Pagesでは*.cshtml
だけの変更でも2秒ほどかかります。PageModelもコンパイルしているのでしょうか。
ただ、*.cshtml.cs
やその他の*.cs
の変更によるコンパイル時間はMVCより早いように感じます。MVCはプロジェクト全体をコンパイルしている感じで、Razor Pagesは関連するページだけコンパイルしている感じです。間違っていたらすみません。
*.cshtml
の変更だけでコンパイルするのはやめてほしい。1ヶ月前にネット回線をV6プラス(MAP-E)に変更した話を書きましたが、2020/02/05現在、問題なく運用できています。 今回は、V6プラスでMTUを最適化した話を書きたいと思います。
MTUとは、IPパケットを送信する際の最大サイズです。このサイズより大きなデータを送信する場合はデータが分割されます。これをフラグメントといいます。
フラグメント(データ分割)が発生すると余計なコストがかかるため通信速度が落ちます。フラグメントが発生しないようにMTUを調節すればより効率的に通信できるわけですね。
MTUの一般的な値は1500ですが、最適な値はネット回線の種類などで変わります。なんで変わるかというと通信方式によってパケット内に追加のデータが必要になったりするからです。追加のデータが必要な場合は、ネットワークの下位にいるクライアントはその分を差っ引いたMTUにしなければフラグメント化してしまいます。なので。最適なMTUは環境によって異なるため実際に計測して確認することが重要になります。
今回使用した環境は以下になります。
192.168.1.1
)[Internet] - [ONU] - [Router] - [Client]
となっています。Windowsメニューでcmd
と打って管理者として実行
をクリックしてコマンドプロンプトを開きます。
コマンドプロンプトでping google.com -f -l 1500
を実行します。
以下の結果になると思います。
C:\WINDOWS\system32>ping google.com -f -l 1500 google.com [172.217.25.238]に ping を送信しています 1500 バイトのデータ: パケットの断片化が必要ですが、DF が設定されています。 パケットの断片化が必要ですが、DF が設定されています。 パケットの断片化が必要ですが、DF が設定されています。 パケットの断片化が必要ですが、DF が設定されています。 172.217.25.238 の ping 統計: パケット数: 送信 = 4、受信 = 0、損失 = 4 (100% の損失)、
-f
はデータ分割しない、-l
はパケットサイズを指定するオプションです。パケットサイズを1500にするとフラグメント化してしまう結果になっています。
あとはパケットサイズをフラグメント化しない値になるまで小さくしていきましょう。フラグメント化しない値で最も大きな値を探しましょう。
私の場合は1424
になりました。
C:\WINDOWS\system32>ping google.com -f -l 1425 google.com [172.217.161.206]に ping を送信しています 1425 バイトのデータ: パケットの断片化が必要ですが、DF が設定されています。 パケットの断片化が必要ですが、DF が設定されています。 パケットの断片化が必要ですが、DF が設定されています。 パケットの断片化が必要ですが、DF が設定されています。 172.217.161.206 の ping 統計: パケット数: 送信 = 4、受信 = 0、損失 = 4 (100% の損失)、 C:\WINDOWS\system32>ping google.com -f -l 1424 google.com [172.217.161.238]に ping を送信しています 1424 バイトのデータ: 172.217.161.238 からの応答: バイト数 =68 (1424 を送信) 時間 =8ms TTL=55 172.217.161.238 からの応答: バイト数 =68 (1424 を送信) 時間 =8ms TTL=55 172.217.161.238 からの応答: バイト数 =68 (1424 を送信) 時間 =8ms TTL=55 172.217.161.238 からの応答: バイト数 =68 (1424 を送信) 時間 =8ms TTL=55 172.217.161.238 の ping 統計: パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、 ラウンド トリップの概算時間 (ミリ秒): 最小 = 8ms、最大 = 8ms、平均 = 8ms
なぜ1424になるのか考えてみます。
---- Internet ---- +40 IPv6 Header + 8 encaplimit ---- Router ---- +20 IPv4 Header + 8 ICMP Header ---- Client ----
おそらく上記のように各種追加データが追加されるためではないかと思います。
1424+28+48=1500
というわけですね。
Clientが28バイト追加して、Routerがさらに48バイト追加すると。
というわけで、1424に28を足した値1452
がMTUの最適値になります。
では早速MTUを変更してみます。
まずは現在のMTUの設定状況を表示してみます。同じくコマンドプロンプトで以下を実行します。
C:\WINDOWS\system32>netsh interface ipv4 show interface Idx Met MTU 状態 名前 --- ---------- ---------- ------------ --------------------------- 27 5000 1500 connected vEthernet (Default Switch) 1 75 1500 connected Loopback Pseudo-Interface 1 18 1 1500 disconnected VPN - VPN Client 10 25 1500 connected vEthernet (bridge) 9 15 1500 connected vEthernet (DockerNAT)
私の環境ではいろんなネットワークがありますが、、設定変更する対象は27
、1
、10
、9
の4つになります。
以下のコマンドを実行します。
C:\WINDOWS\system32>netsh interface ipv4 set interface 27 mtu=1452 OK C:\WINDOWS\system32>netsh interface ipv4 set interface 1 mtu=1452 OK C:\WINDOWS\system32>netsh interface ipv4 set interface 10 mtu=1452 OK C:\WINDOWS\system32>netsh interface ipv4 set interface 9 mtu=1452 OK
最後に再度設定状況を表示して確認します。
C:\WINDOWS\system32>netsh interface ipv4 show interface Idx Met MTU 状態 名前 --- ---------- ---------- ------------ --------------------------- 27 5000 1452 connected vEthernet (Default Switch) 1 75 1452 connected Loopback Pseudo-Interface 1 18 1 1500 disconnected VPN - VPN Client 10 25 1452 connected vEthernet (bridge) 9 15 1452 connected vEthernet (DockerNAT)
これでMTUの設定を変更できました。
MTUの最適値を探してWindows10に設定してみました。 ただここまで書いておいて変更の効果は体感できていません。またMTUの最適値が本当にこの値でよいのかも確信がありません。もし間違っているよ~とか、最適値を確認する方法があるよ~とかあればぜひ教えて下さい。
ここ1年ほどネット回線が夜になると劇遅になるのでフレッツ光をPPpoEからIPoEに変えたいとずっと思っていたが、面倒くさいという思いがあって先延ばしにしていた。この度やっと重い腰を上げて乗り換えることにした。 が、当初思ったよりOpenWrtの設定がかんたんではなかったのでここに記録を残すことにした。まだまだPPpoEの契約者も少なく、OpenWrtを使っている人はさらに少ないだろうが、ネットにまとまった手順がなかったので記録せねばと3年ぶりに記事を書くことにした。みなさんお久しぶりです。口調が変わっていても気にしないで。3年も経てば色々忘れてる。
LAN
,WAN
,WAN6
があり、WAN
は旧ISPで接続中、WAN6
は停止中の状態なお今回解説する手順はJPNEが提供する「v6プラス(MAP-E)」を提供するISPであればどこでも同じになるはずである。
当初開通日に接続が勝手に切れると思っていたからそのつもりで仕事を調整していたのだが、結局何も起こらなかった。なので翌日の午後に時間をとって新しい設定をすることにした。
この時点で本当に開通しているのかどうかもわかっていなかった。もしかすると手違いが発生しているのかとか思ったりした。後から調べてわかったのだが、開通はNTT側の設定が切り替わるだけで旧ISPの接続が切れるわけではないのでこちらではいつ開通したのか設定してみないとわからないようだ。DHCPで発行されたIPv6アドレスがJPNEのものであれば開通済みということらしい。
まずはネイティブIPv6接続してみる。
基本的には下記の記事を参考にした。ありがとうございます。 blog.misosi.ru
WAN6
というインターフェースがあるので[Edit]をクリック。(WAN6がなければ作る)
DHCPv6 Client
eth1
wan
/etc/config/dhcp
を以下のように編集> vi /etc/config/dhcp : config dhcp 'lan' : option dhcpv6 'relay' option ra 'relay' option ndp 'relay' : config dhcp 'wan6' option dhcpv6 'relay' option ra 'relay' option ndp 'relay' option master '1' : > uci commit /etc/config/dhcp
自分の場合はlan
にoption master 1
がついていたので、その行を削除しなければならなかった。
WAN6
を接続WAN6
で[Connect]をクリックMAP-EとはIPv4パケットをIPv6パケットにカプセル化してJPNEに送り、JPNEがカプセル化を解いてインターネットに送る、受信も同じくIPv6にカプセル化されたものをJPNEから受信する、という仕組みのようだ。参照
つまりMAP-EとはクライアントとJPNEの間でトンネルを貼るということみたい。なんとなくわかった。
ちょっとここでMAP-Eのマッピングルールを計算してみる。急ぐ人は飛ばしてください。
計算方法は下記サイトを参考にした。ありがとうございます。(2409
は240b
の誤りと思われる)
ここまでで以下の値が手元にある。正しく設定するとこのIPv4アドレスで接続できるはずだ。
名前 | 説明 | 例 |
---|---|---|
IPv6Prefix | DHCPv6で発行されたIPv6プレフィックス。WAN6 のIPv6アドレスの欄に表示される。 |
240b:253:cccc:dddd:eeee:ffff:gggg:hhhh/64 |
IPv6Addr | DHCPv6で発行されたIPv6アドレス。 | 240b:253:cccc:dddd:iiii:jjjj:kkkk:llll |
CE | MAP-Eで計算したCEアドレス | 240b:253:cccc:dddd:mmmm:nnnn:oooo:pppp |
IPv4Addr | MAP-Eで計算したIPv4アドレス | xxx.xxx.xxx.xxx |
下記の計算ツールでMAP-Eの各パラメータを計算する。「IPv6 プレフィックスかアドレスを入力」にIPv6Prefix(WAN6
のIPv6アドレス)を入力して計算ボタンを押す。
http://ipv4.web.fc2.com/map-e.html
計算した結果は次項で使う。
opkg update opkg install map
余談だが以下のコマンドを実行するとIPv4アドレスなどを計算できる。値は各自置き換えること。
LEGACY=1 mapcalc * type=map-e,ipv6prefix=240b:252::,prefix6len=31,ipv4prefix=xxx.xxx.xxx.xxx,prefix4len=15,psidlen=8,offset=4,ealen=25
/lib/netifd/proto/map.sh
をviで開き#export LEGACY=1
のコメントを外すMAP-E用のインターフェースを作成する。
wan6_map
(何でも良い)MAP / LW4over6
MAP-E
2404:9200:225:100::64
(JPNEのBRアドレス)option ipaddr
の値option ip4prefixlen
の値option ip6prefix
の値option ip6prefixlen
の値option ealen
の値option psidlen
の値option offset
の値wan6
wan
WAN6
というインターフェースがあるので[Edit]をクリック。(WAN6がなければ作る)
disabled
(automatic
だとログにeth1: link down
とか出て通信が定期的に途切れる。意味はよくわかってないWAN6
のIPv6アドレスと同じ値か、mapcalcの計算結果のRULE_1_IPV6PD
の値に/56
を付与した文字列(例:240b:253:cccc:dddd::/56
)を設定。どちらでも問題ないと思うが自分は後者を設定した。/etc/config/network
を以下のように編集> vi /etc/config/network : config interface 'wan6_map' : option encaplimit 'ignore' : > uci commit /etc/config/network
※これで5時間ハマった。これがないとWAN6_MAP
のTXはカウントされてもRXはカウントされないという状態になる。おそらくパケットが壊れた状態になると思われる。下記の記事と同じ現象と思う。
自力でIPv4 over IPv6をした(Tunnel編) – 愚行録 the Next Generation
いよいよ接続です。
WAN6_MAP
の[Connect]をクリックWAN6_MAP
の状態のIPv4
の項にMAP-Eで計算したIPv4アドレスが表示されることを確認IPv6
の項にCEアドレスが表示されることを確認管理されたトンネルメカニズム(6RD)を使用してIPv4経由でIPv6を転送しているようです。
と表示されることを確認。*****.enabler.ne.jp
と表示されることを確認。Local address not yet configured!
と出る推測だが、Local address not yet configured!
は接続開始時にまだローカルアドレスが定まっていないために起こる一時的なエラーと思われる。接続後は発生しないようだ。
最後に自分の設定ファイルからwan6
とwan6_map
の設定値を貼っておく。
/etc/config/network
config interface 'wan6' option proto 'dhcpv6' option reqaddress 'try' option ifname 'eth1' option reqprefix 'no' option ip6prefix '240b:253:cccc:dddd::/56' config interface 'wan6_map' option proto 'map' option type 'map-e' option peeraddr '2404:9200:225:100::64' option ipaddr 'xxx.xxx.xxx.xxx' option ip4prefixlen '15' option ip6prefix 'aaaa:bbbb::' option ip6prefixlen '31' option ealen '25' option psidlen '8' option offset '4' option encaplimit 'ignore' list tunlink 'wan6'
下記サイトで夜9時半に90Mbps程。いままではこの時間は3Mbpsとかだったので劇的改善である。しかもレイテンシも15msとか上出来な値。昼間は100Mbps。旧ISPでは昼間は250Mbpsとかでてたので負けてるが、最大速度よりも一定速度が常に出るほうがありがたい。
MAP-Eはルーターへの負荷が高いとのことなので、完全に推測だがルーターの処理能力がボトルネックになっているのかもしれない。
しばらく使っているとポート不足により通信できない状態になった。
iptables -t nat -L -v
で見ると最初のポートブロックしか使われていない。
下記サイトの通り設定するとうまく分散できた。
OpenWrt map-e (JPNE v6plus) において、割当ポート240個をちゃんと使わせるための設定。 · GitHub
opkg update opkg install iptables-mod-ipopt
/etc/firewall.user
を以下のように編集iptables -t nat -A PREROUTING -m statistic --mode nth --every 15 --packet 0 -j MARK --set-mark 10 iptables -t nat -A PREROUTING -m statistic --mode nth --every 15 --packet 1 -j MARK --set-mark 11 iptables -t nat -A PREROUTING -m statistic --mode nth --every 15 --packet 2 -j MARK --set-mark 12 iptables -t nat -A PREROUTING -m statistic --mode nth --every 15 --packet 3 -j MARK --set-mark 13 iptables -t nat -A PREROUTING -m statistic --mode nth --every 15 --packet 4 -j MARK --set-mark 14 iptables -t nat -A PREROUTING -m statistic --mode nth --every 15 --packet 5 -j MARK --set-mark 15 iptables -t nat -A PREROUTING -m statistic --mode nth --every 15 --packet 6 -j MARK --set-mark 16 iptables -t nat -A PREROUTING -m statistic --mode nth --every 15 --packet 7 -j MARK --set-mark 17 iptables -t nat -A PREROUTING -m statistic --mode nth --every 15 --packet 8 -j MARK --set-mark 18 iptables -t nat -A PREROUTING -m statistic --mode nth --every 15 --packet 9 -j MARK --set-mark 19 iptables -t nat -A PREROUTING -m statistic --mode nth --every 15 --packet 10 -j MARK --set-mark 20 iptables -t nat -A PREROUTING -m statistic --mode nth --every 15 --packet 11 -j MARK --set-mark 21 iptables -t nat -A PREROUTING -m statistic --mode nth --every 15 --packet 12 -j MARK --set-mark 22 iptables -t nat -A PREROUTING -m statistic --mode nth --every 15 --packet 13 -j MARK --set-mark 23 iptables -t nat -A PREROUTING -m statistic --mode nth --every 15 --packet 14 -j MARK --set-mark 24 iptables -t nat -A OUTPUT -m statistic --mode nth --every 15 --packet 0 -j MARK --set-mark 10 iptables -t nat -A OUTPUT -m statistic --mode nth --every 15 --packet 1 -j MARK --set-mark 11 iptables -t nat -A OUTPUT -m statistic --mode nth --every 15 --packet 2 -j MARK --set-mark 12 iptables -t nat -A OUTPUT -m statistic --mode nth --every 15 --packet 3 -j MARK --set-mark 13 iptables -t nat -A OUTPUT -m statistic --mode nth --every 15 --packet 4 -j MARK --set-mark 14 iptables -t nat -A OUTPUT -m statistic --mode nth --every 15 --packet 5 -j MARK --set-mark 15 iptables -t nat -A OUTPUT -m statistic --mode nth --every 15 --packet 6 -j MARK --set-mark 16 iptables -t nat -A OUTPUT -m statistic --mode nth --every 15 --packet 7 -j MARK --set-mark 17 iptables -t nat -A OUTPUT -m statistic --mode nth --every 15 --packet 8 -j MARK --set-mark 18 iptables -t nat -A OUTPUT -m statistic --mode nth --every 15 --packet 9 -j MARK --set-mark 19 iptables -t nat -A OUTPUT -m statistic --mode nth --every 15 --packet 10 -j MARK --set-mark 20 iptables -t nat -A OUTPUT -m statistic --mode nth --every 15 --packet 11 -j MARK --set-mark 21 iptables -t nat -A OUTPUT -m statistic --mode nth --every 15 --packet 12 -j MARK --set-mark 22 iptables -t nat -A OUTPUT -m statistic --mode nth --every 15 --packet 13 -j MARK --set-mark 23 iptables -t nat -A OUTPUT -m statistic --mode nth --every 15 --packet 14 -j MARK --set-mark 24
/lib/netifd/proto/map.sh
を以下のように編集#$ diff -c /lib/netifd/proto/map.sh.orig /lib/netifd/proto/map.sh *** 135,140 **** --- 135,141 ---- json_add_string snat_ip $(eval "echo \$RULE_${k}_IPV4ADDR") json_close_object else + local mark=10 for portset in $(eval "echo \$RULE_${k}_PORTSETS"); do for proto in icmp tcp udp; do json_add_object "" *************** *** 142,152 **** --- 143,155 ---- json_add_string target SNAT json_add_string family inet json_add_string proto "$proto" + json_add_string mark "$mark" json_add_boolean connlimit_ports 1 json_add_string snat_ip $(eval "echo \$RULE_${k}_IPV4ADDR") json_add_string snat_port "$portset" json_close_object done + mark=`expr $mark + 1` done fi if [ "$type" = "map-t" ]; then
iptables -t nat -L -v
ですべてのポートブロックが使われていることを確認。
IPoEによる混雑の解消効果は素晴らしいし満足しているが、OpenWrtでのMAP-E設定はかなり敷居が高い。OpenWrtによるMAP-Eの動作はまだ自分の中で不安があるので、しばらく様子を見たいと思う。
eth1: link down
が頻発する問題しばらく運用していると、以下のようなログが出てリンクが切れることが頻発した。頻度としては通信しているとランダムに発生し、数時間発生しないときもあれば連続で発生するときもある。ただし再現性がないので確実に発生させる手順は不明。
eth1: link down ar71xx: pll_reg 0xb8050014: 0x110000
発生すると数十秒で復帰するが、正直通常使用できる状態ではない。ネットを探しても同じような問題はいくつかあるが解決しなかった。これは困った。
こりゃ素直にv6プラス対応ルーター買うかと思って実際にWSR-1166DHPL/N
を注文した。この問題で何日も費やすリスクを考えたら5000円出して金で解決できるなら安いもんだ。
注文した後、IPoEは使えないと思ってPPpoEだけで運用していたが、それでも発生することに気づいた!!これは。。。そういえば今回の作業にあたってOpenWrtを最新にバージョンアップしていたが、それが原因かもと思い、元のバージョンにダウングレードしてみることにした。1つ前の18.06.4
にしてみたがダメ。たしかもともとは18.06.1
だったと思いそれに戻すと見事に治った。いまのところ4日間元気に稼働中。
ということで新しいルーターは無駄になってしまった。。
6日目に再発しました。
どうやらハードに問題があるみたい。
回避するパッチは存在するようだが、手元に新しいルーターがある以上、これ以上コイツの問題に付き合うつもりはない。ということで新しいルーターに移行することにしました。
ここで新しいルーターの設定方法は説明しないが、設定の所要時間は3分だった。「v6プラスを使用する」を選んで設定保存するだけ。かんたんすぎる。。
改めて速度計測してみると、なんと昼間で300Mbps、夜9時頃でも260Mbps出る。レイテンシは15msと変わらず。やはりハードの性能がネックになっているのかもしれない。
新しいルーターはいまのところ3日間ほどネットも無線も問題なく稼働している。またなにかあれば報告する。
先日管理画面系のサイトをリニューアルするにあたり、SPAを検討しました。その過程で何を検討し、どう判断したのかを書いてみたいと思います。
まずは検討対象となるサイトについて説明したいと思います。 いわゆる管理画面サイトで、左側はサイドメニュー、右側はコンテンツエリアの2カラムレイアウト。サイドメニューの項目をクリックすると各ページのコンテンツが表示されます。 ヘッダー部分にはログイン情報があります。
コンテンツ・機能としては、以下のような物があります。
バックエンドはASP.NET MVC。タスク管理機能など動的な部分はjQueryで実装しています。 SEOは必要ありません。モバイルアプリもありません。モバイルではPC版のレイアウトで操作できればOKなのでレスポンシブでもありません。
SPA、MPAという言葉を多用するので、言葉の定義をします。
サイトをリニューアルするにあたり、以下の要件がありました。
ここ1,2年で、SPAの記事を目にすることが増えてきました。この時点ではSPAサイトを自分で作ったことはありませんでした。自分の中でSPAに対して抱いていた印象や知識は以下の様なことです。
この中で一番魅力を感じたのは2番目のデスクトップアプリのようにキビキビ動くという点です。通常のWebサイトではページ遷移すると通信が発生するので、コンマ何秒かの待ち時間が発生します。これがなくなるのは地味だけど、でも体感できる差です。大きな差別化要因になると感じました。
「デスクトップアプリのようにキビキビ動くこと」は要件にはないですが、もしそれが実現できればそれに越したことはありません。そこでSPAについて詳しく検討することにしました。
以下、それぞれ検討したことと、その結果になります。プラス1なら☆(+1)、プラス2なら☆☆(+2)、マイナス1なら★としてランク付けしていきます。合算して☆が多ければ費用対効果があります。
検討にあたっては実際にAngular2でSPAサイトを構築してみました。
SPAではサーバーは「データ」、フロントは「UI」と役割分担しますから、フロント側では必要な部分のみUI更新することができます。そうするとページヘッダーやナビゲーション部分はページ切り替え時には更新する必要がなくなりますからその分のレンダリングや通信コストが削減できます。これは正しいのでしょうか?
例えばログページから設定ページに移動した場合を考えてみます。
MPAの場合、
SPAの場合、
上記を考えてみると、MPAはページ全体を送っているのに対して、SPAでは設定値だけを送っています。たしかに通信量は削減できそうですね。しかし体感できる程の差かどうかは、ケースによるのではないでしょうか。
今回のサイトの場合、ページ全体のHTMLは30KB程です。設定値のJSONが1KBだったとして、その差は29KBになります。29KB削減の効果は疑問です。モバイル環境なら大きいでしょうが、モバイルは想定していません。でも削減できるのはいいことですね。効果は小さいかもしれませんがプラス材料です。星ひとつ。
SPAはデスクトップアプリのようにキビキビ動くのが魅力です!この最大の利点を得るためにSPAにするといっても過言ではありません。 では管理画面をSPAにするとどうなるでしょうか?
前項の例を見てください。
あれ?どっちも通信発生していますね。SPAってページ遷移がないから早いんじゃなかったの??
通信が発生するということはMPAと同じく通信待ちが発生するということです。デスクトップアプリのようにキビキビ動きません。
SPAではキャッシュするから2回目以降はAJAXも要らないということでしょうか?ん?設定値をキャッシュする?それじゃ設定値が最新のものじゃないかもしれなくなるってことだからダメだよね。
設定ページ以外ならどうだろう。ログも最新じゃないと困るし、他も全部最新がいい。でも例えばログのページ送り操作のケースを考えると、クライアントサイドでキャッシュしてくれてもいいような気がする。その場合は通信がなくなるのでキビキビ動きますね。そっか、コンテンツによってキャッシュすべきかどうか違うんだ。で、キャッシュできないものはゼロ通信にできないと。
結局、SPAにしたからといって一律にゼロ通信にはできない。これじゃあデスクトップアプリにはなれない。当初期待していた目論見が崩れました。考えてみれば当たりまえの話ですが、大きな勘違いをしていたようです。
とりあえず、キャッシュできる場面ではキビキビ動くということで星ひとつ。
SPAはJSファイルに各ページのテンプレート、UIロジック、スタイル情報なども含めるため、ファイルサイズが大きくなりやすい。
初回表示が遅いってやつですね。ファイルを分割するなど工夫が必要になるかもしれません。マイナス星ひとつ
これは実際に作ってみて気付いたことですが、SPAはブラウザのページキャッシュ機能が使えないんですね。
どういうことかというと、例えばログページから設定ページに移動した後、戻るした場合を考えてみます。
MPAの場合、
SPAの場合、
MPAでは最終的なHTMLがブラウザのページキャッシュとしてローカルに残っていますから、それを表示するだけです。しかしSPAの場合はこのページキャッシュ機能が使えないため、自前ですべて賄う必要があります。対策としてはログ結果を自前でキャッシュしておき、戻る・進むの場合はキャッシュを参照するようにすることだと思いますが、MPAではブラウザがすべて面倒をみてくれる点と比べると気が重くなります。
これは当初想定していなかったデメリットです。管理画面系サイトはページ切り替えが多く、戻る・進むは普通に使います。マイナス星みっつ。
他にも検討課題はあったと思いますが、この時点で今回のケースではSPAの採用を取りやめました。一番期待していたデスクトップアプリのようなUXが得られないと分かったからです。
おそらくSPAの使いどころというのは以下の点が判断条件になってくるのではないでしょうか。
SPAにしろ、デスクトップアプリにしろ、データがリモートにある以上、通信待ちからは逃れられません。データをローカルに置けるというのはUI速度という面では利点です。データをリモートで一元管理できるというのもまた別の利点です。どちらも、ということは簡単ではありませんね。
ということで、以上となります。いかがでしたでしょうか?少しでも参考になれば幸いです。
Azure Cloud ServiceのVMでページングファイルがCドライブ(永続ストレージ)に配置されている件でトラブった経緯と調査、解決のために行ったことについて記載します。
Azure Cloud Serviceで、ExtraSmallのVM2個で運用しています。osFamily、osVersionは未指定です。
OSはWindows Server 2012 R2 Datacenter。メモリは768MBです。
1年ほど運用してきましたが、最近処理が増えたのか、処理が途中で止まる現象が発生し出しました。
具体的には、
ここで思ったのは、「ExtraSmallはそろそろきついか。。」、「もしかしてメモリリークしてる??」でした。メモリリークについてはメモリ使用量が増え続けてないので原因候補から外しました。
「じゃあ、性能不足か。予算が、、」、しかしメモリ使用量は物理、仮想合わせても3GB程度、仮想メモリは4GB確保しているので、まだ余裕はあるはず、この状況で処理が止まるなんてことあるだろうか?う~ん。
ここでふと、処理負荷時にディスク使用率が100%に張り付いているのを見つけました。HDDをそんなに酷使するような処理は行っていないので、なにがそんなに負荷を与えるの?と思いました。そういえばAzureのVMには永続ストレージと一時ストレージがあって、永続ストレージはものすごく遅いんだっけ、もしかして永続ストレージを使っているから重い?、とさらに調査してみることに。
VMにリモートデスクトップでログインしてパフォーマンスモニターで処理負荷時の様子を眺めました。すると以下のことがわかりました。
処理が止まる原因はCドライブの過負荷のようです。しかもCドライブに負荷をかけているのはpagefile.sys。
「そうか、物理メモリが少ないから常にページングファイルでガリガリやってる状態で、処理が立て込むとついには固まる、と。」
状況がわかってきました。
一方で、VMには3つのドライブがあって、Cドライブ以外の負荷はまったくないような状況です。ここで疑問に思ったのはCドライブは永続ストレージ?それとも一時ストレージ?ということでした。もし永続ストレージなら改善の余地があるかもしれません。そこでネットを調べたところ、AzureのVMはDドライブが一時ストレージという記載がありますが、Cloud ServiceのVMにも当てはまるのか、情報が少なくはっきりしません。そこで実際に計測してみることにしました。
以下が実際のベンチマーク結果です。
Cドライブ
----------------------------------------------------------------------- CrystalDiskMark 5.1.2 x64 (C) 2007-2016 hiyohiyo Crystal Dew World : http://crystalmark.info/ ----------------------------------------------------------------------- * MB/s = 1,000,000 bytes/s [SATA/600 = 600,000,000 bytes/s] * KB = 1000 bytes, KiB = 1024 bytes Sequential Read (Q= 32,T= 1) : 43.511 MB/s Sequential Write (Q= 32,T= 1) : 56.066 MB/s Random Read 4KiB (Q= 32,T= 1) : 1.225 MB/s [ 299.1 IOPS] Random Write 4KiB (Q= 32,T= 1) : 1.082 MB/s [ 264.2 IOPS] Sequential Read (T= 1) : 74.436 MB/s Sequential Write (T= 1) : 68.354 MB/s Random Read 4KiB (Q= 1,T= 1) : 0.547 MB/s [ 133.5 IOPS] Random Write 4KiB (Q= 1,T= 1) : 0.811 MB/s [ 198.0 IOPS] Test : 500 MiB [C: 34.8% (6.9/20.0 GiB)] (x5) [Interval=5 sec] Date : 2016/07/28 8:07:01 OS : Windows Server 2012 R2 Datacenter (Full installation) [6.3 Build 9600] (x64)
Dドライブ
----------------------------------------------------------------------- CrystalDiskMark 5.1.2 x64 (C) 2007-2016 hiyohiyo Crystal Dew World : http://crystalmark.info/ ----------------------------------------------------------------------- * MB/s = 1,000,000 bytes/s [SATA/600 = 600,000,000 bytes/s] * KB = 1000 bytes, KiB = 1024 bytes Sequential Read (Q= 32,T= 1) : 1397.509 MB/s Sequential Write (Q= 32,T= 1) : 880.550 MB/s Random Read 4KiB (Q= 32,T= 1) : 68.634 MB/s [ 16756.3 IOPS] Random Write 4KiB (Q= 32,T= 1) : 92.339 MB/s [ 22543.7 IOPS] Sequential Read (T= 1) : 1697.640 MB/s Sequential Write (T= 1) : 1372.134 MB/s Random Read 4KiB (Q= 1,T= 1) : 27.629 MB/s [ 6745.4 IOPS] Random Write 4KiB (Q= 1,T= 1) : 28.783 MB/s [ 7027.1 IOPS] Test : 500 MiB [D: 34.0% (10.9/32.0 GiB)] (x5) [Interval=5 sec] Date : 2016/07/28 8:13:56 OS : Windows Server 2012 R2 Datacenter (Full installation) [6.3 Build 9600] (x64)
Eドライブ
----------------------------------------------------------------------- CrystalDiskMark 5.1.2 x64 (C) 2007-2016 hiyohiyo Crystal Dew World : http://crystalmark.info/ ----------------------------------------------------------------------- * MB/s = 1,000,000 bytes/s [SATA/600 = 600,000,000 bytes/s] * KB = 1000 bytes, KiB = 1024 bytes Sequential Read (Q= 32,T= 1) : 424.361 MB/s Sequential Write (Q= 32,T= 1) : 351.871 MB/s Random Read 4KiB (Q= 32,T= 1) : 78.930 MB/s [ 19270.0 IOPS] Random Write 4KiB (Q= 32,T= 1) : 71.282 MB/s [ 17402.8 IOPS] Sequential Read (T= 1) : 365.320 MB/s Sequential Write (T= 1) : 334.481 MB/s Random Read 4KiB (Q= 1,T= 1) : 13.171 MB/s [ 3215.6 IOPS] Random Write 4KiB (Q= 1,T= 1) : 18.136 MB/s [ 4427.7 IOPS] Test : 500 MiB [E: 41.4% (635.0/1534.9 MiB)] (x5) [Interval=5 sec] Date : 2016/07/28 8:23:47 OS : Windows Server 2012 R2 Datacenter (Full installation) [6.3 Build 9600] (x64)
この結果からDドライブが一時ストレージであることがわかりました。
「そもそもなぜページングファイルを永続ストレージに配置するのか。ページングファイルは揮発性の情報だから、永続化する必要はないはずなのに。。単なるミス?それとももともとこのような仕様?」
MSに問い合わせてみようと思いましたが、インシデント代がもったない。。不具合という確証もないし。。
そこでMSDNフォーラムに質問してみました。
Cloud ServiceのExtraSmall VMで、pagefile.sysがCドライブに配置されている件
試しに手動にてページングファイルの場所をDドライブにして様子を見てみると、メモリ使用量は相変わらずですが、ディスク負荷はほぼ解消しました。
OK。これで解決しそうです。
しかし、Cloud ServiceのVMはOSが自動更新されます。これによりページングファイルもCドライブに戻ってしまいます。OSが自動更新されてもページングファイルをDドライブにできるような方法はないものか。。
質問の回答ばかりに頼っていてもしょうがないので、自分で回避方法を探してみることにしました。
Cloud Servieにはスタートアップタスクという仕組みがあり、アプリケーション配置時にバッチスクリプトなどを実行することができます。既にNewRelicのインストールなどを行っていますし、ここでページングファイルの配置変更ができれば解決しそうです。
しかしページングファイルの設定変更にはOS再起動が必要です。できるのか。ネットで調べてみたところ、スタートアップタスクでOS再起動している人がいました。これはできるかも!やってみよう!
やってみた結果、できました。
以下がページングファイルの配置変更スクリプトをスタートアップタスクとして登録する手順です。
<ServiceDefinition ...> <WorkerRole ...> <Startup> <Task commandLine="changePagefileLoc.cmd" executionContext="elevated" taskType="simple"/> </Startup> </WorkerRole> </ServiceDefinition>
「出力ディレクトリにコピー」を「常にコピー」にします。 文字コードはASCII。
@echo off DATE /T >> "%TEMP%\StartupLog.txt" 2>&1 TIME /T >> "%TEMP%\StartupLog.txt" 2>&1 ECHO Starting up changePagefileLoc.cmd. >> "%TEMP%\StartupLog.txt" 2>&1 PowerShell -ExecutionPolicy Unrestricted .\changePagefileLoc.ps1 >> "%TEMP%\StartupLog.txt" 2>&1 EXIT /B 0
「出力ディレクトリにコピー」を「常にコピー」にします。 文字コードはUTF-8(BOM付き)。
Write-Output "===================" Write-Output "Change pagefile location start" $CurrentPageFile = Get-WmiObject -Query "select * from Win32_PageFileSetting" Write-Output "C drive page file: $CurrentPageFile" if ($CurrentPageFile -and $CurrentPageFile.Name.ToLower() -eq "c:\pagefile.sys") { $computer = Get-WmiObject Win32_computersystem -EnableAllPrivileges $computer.AutomaticManagedPagefile = $false $computer.Put() $CurrentPageFile.delete() Set-WmiInstance -Class Win32_PageFileSetting -Arguments @{name="d:\pagefile.sys"; InitialSize = 0; MaximumSize = 0} -EnableAllPrivileges | Out-Null $PageFile = Get-WmiObject Win32_PageFileSetting -Filter "SettingID='pagefile.sys @ d:'" $PageFile.InitialSize = 4096 $PageFile.MaximumSize = 4096 [Void]$PageFile.Put() $PageFile = Get-WmiObject Win32_PageFileSetting -Filter "SettingID='pagefile.sys @ d:'" Write-Output "D drive page file: $PageFile" Write-Output "The computer will restart for the changes to take effect." Restart-Computer } Write-Host "Change pagefile location end"
当面の回避策が見つかってよかったです。しかしなぜこのような仕様になっているのかは謎のままです。
ネットを探しても出てこない症状。可能性があるとすれば最近発生した不具合?、もし元々このような仕様だったとしたら、Cloud Serviceを使っている人はずっとこのような構成のOSを使わされていたということになります。
物理メモリが多いVMサイズではあまり問題になる状況はないかもしれませんが、ひとたびメモリ使用量が物理メモリを超えると、ページングによりCドライブが過負荷になり、しまいにはディスクアクセスエラーになり処理落ちするわけです。
ExtraSmallのように常にメモリ不足のような場合は致命的な問題です。まぁExtraSmallは開発・テスト用とされていますからね。素直に上のサイズ使えということですかね。
MSの人はこのことに気付いているのか、何か理由があってそうしているのか、聞いてみたいです。そういう窓口ってないんですかね。