nodejsのイベントキューの動作確認

概要 Node.jsのイベントループの仕組みについてNode.jsでのイベントループの仕組みとタイマーについてという記事で学びました。しかし、こちらに掲載されている例だけではイベントキューの仕組みがピンとこなかったので自分なりに実験してみました。 イベントキューの動作を見る Node.jsでのイベントループの仕組みとタイマーについてでは以下のコードが掲載されています。 setTimeout(() => console.log(1)); setImmediate(() => console.log(2)); process.nextTick(() => console.log(3)); Promise.resolve().then(() => console.log(4)); (() => console.log(5))(); 出力は以下のようになります。 5 3 4 1 2 こうなる理由についてはhiroppyさんのブログの解説にまかせるとして、それぞれの命令がそれぞれのフェーズのキューに積まれる部分を理解したいなと思いました。 少し最初のコードを改造して以下のようにします。 setTimeout(() => console.log('1-1')); setImmediate(() => console.log('1-2')); process.nextTick(() => console.log('1-3')); Promise.resolve().then(() => console.log('1-4')); (() => console.log('1-5'))(); setTimeout(() => console.log('2-1')); setImmediate(() => console.log('2-2')); process.nextTick(() => console.log('2-3')); Promise.resolve().then(() => console.log('2-4')); (() => console.log('2-5'))(); 実行結果は以下のようになります。 1-5 2-5 1-3 2-3 1-4 2-4 1-1 2-1 1-2 2-2 この動作から各命令は各フェーズのキューに積まれて積まれた準に実行されていることがわかります。操作の順番は5->3->4->1->2の順番をキープしつつ。キューの積まれた順番(1or2)は1->2をキープしています。setTimeoutについてはあくまでタイマーがスタートする順番が1->2なので引数を変えたりすると標準出力のタイミングがずれます。 もう少しわかり易い例を思いつきましたらupdateしていきます。

November 16, 2021 · 1 min · Me

KubernetesのCPU設定とコンテナ上のプロセスの関係

概要 KubernetesやDockerではポッドやコンテナの使用CPU数を簡単に変更することができます。簡単が故に設定さえしてしまえばそのシステムはそのリソースを使用して稼働しているものと誤解しがちです。この文章ではKubernetesと簡単なプログラムを使ってリソース割り当てとスレッドの関係について紐解いていきたいと思います。 環境 docker desktopのkubernetes機能を使います $ kubectl version Client Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.5", GitCommit:"aea7bbadd2fc0cd689de94a54e5b7b758869d691", GitTreeState:"clean", BuildDate:"2021-09-15T21:10:45Z", GoVersion:"go1.16.8", Compiler:"gc", Platform:"darwin/amd64"} Server Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.5", GitCommit:"aea7bbadd2fc0cd689de94a54e5b7b758869d691", GitTreeState:"clean", BuildDate:"2021-09-15T21:04:16Z", GoVersion:"go1.16.8", Compiler:"gc", Platform:"linux/amd64"} kube上のリソース表示にmetrics-serverとk9sをつかっています。 詳細 KubernetesやDockerでは、立ち上げるコンテナにCPUを割り当てることができます。Kubernetesの場合、稼働しているポッドにいくらCPUを積んでも性能が上がらないなんてことはなかったでしょうか。もしかするとそのCPU、無駄かもしれません。 「そのプロセス、本当にマルチスレッドですか?」の問いに答えることが重要です。特に意識せず開発されたシステムであれば通常はシングルスレッドでしょう。その場合には最大でも1000mi cpu(1 cpu)以下が適切な設定値となります。それ以上の設定値は意味がありません。 Kubernetesの場合、request.resources.cpuなどに設定を入れることができます。これで常にポッドがそのcpu数で動作していると思われがちですが、正確には「コンテナが並列に実行できるスレッド数(そのスレッド数で実行しているとはいってない)」というべきでしょうか。 以下の図を見てみてください。左側にメモリ、右側にCPUを表しています。プロセスやスレッドは実行するとメモリ上に展開されます。ここでコンテナに2cpuを割り当てたとします。これは一度に2スレッド並列に処理する能力がこのコンテナに与えたことを意味します。メモリ上で1プロセスに2スレッドが展開されているため、無駄なくcpuリソースを使用できていると言えます。 スレッドを意識していないプロセスを考えてみます。その場合には以下のように1プロセスに1スレッドがメモリ上に展開されます。簡単にフルスクラッチで書いた世の中の大体のプログラムはこのような形になるでしょう。ここで4000mi cpuをこのコンテナに割り当ててみます。3000m cpuは使われずに無駄になってしまいました。 ここから少し実験してみます。まずは1000m cpuをコンテナに割り当て適当に無限ループのプロセスを稼働させてみます。 このようにCPUが限界の1000m cpu付近まで使用されていることがわかります。 ではこのコンテナに2000m cpu割り当てて同じことをしてみます。 やはりcpuが1000m以上は利用されず、resuestに対するパーセンテージも50%を上回ることはありません。 先述の通りコンテナ上で動作しているプロセスがシングルスレッドで動作するものだからです。 同じプロセスをもう一つ走らせてみると簡単に1000mi cpuを超えることができます。 これは図にすると以下のような状態です ではもう一例、次は1プロセス2スレッドで1000mi cpu超えを試してみます。以下のようなjavascriptを利用します。 File: master.js const { spawn, Thread, Worker } = require("threads"); (async () => { const auth1 = await spawn(new Worker("....

November 6, 2021 · 1 min · Me

Raspbianのiptables問題を解消する

概要 ラズパイでk3sクラスタを構築しそこでシステムを稼働させているのですが、ある日内部の処理がかなり低下していることに気づきました。raspbianに最初から入っているiptablesに無駄なエントリが徐々に増えていくバグがあり、iptablesをアンインストールすることで解消しました。 環境 raspberry pi3 b+ と pi4が混在したクラスタを構成しています。 $ cat /etc/os-release PRETTY_NAME="Raspbian GNU/Linux 10 (buster)" NAME="Raspbian GNU/Linux" VERSION_ID="10" VERSION="10 (buster)" VERSION_CODENAME=buster ID=raspbian ID_LIKE=debian HOME_URL="http://www.raspbian.org/" SUPPORT_URL="http://www.raspbian.org/RaspbianForums" BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs" 詳細 kubernetesで稼働しているプロセス溜まっており、詳しく見てみると通常数百ms程度で動作していた処理が数秒かかっているようでした。 不要なログは伏せています 遅い処理時間 単純なAPIリクエストからレスポンスまでの時間を測っているだけですので数秒かかるのは遅すぎます。 Nodeの負荷もかなり高かったためプロセスを確認すると以下のとおりksoftirqdとiptablesが怪しそうです。 重いnodeのプロセス そこでGitHubを漁っていたらHigh load due to ksoftirqd, growing iptables rulesというissueを見つけました。 こちらのコメントの通りルールをリストしてwcかけてみるとやはり大きいようです、3MBもある $ sudo iptables -L | wc # Warning: iptables-legacy tables present, use iptables-legacy to see them 18606 393165 3159290 またこちらで言及されているiptablesのバージョンにも近いようです。これはraspbianインストール時に最初から入っているiptablesです。...

October 17, 2021 · 1 min · Me

Screwdriver Singlehost Workaround of ExternalIP

Overview Screwdriver.cd is a one of a CI/CD tool which woks on Kubernetes. You can set builds with easy yaml definition with this tool. Screwdriver.cd has a Helm chart, but this needs workaround to make it works with single host. I’d like to introduce how to deploy it with single host mode and with Helm chart. Registering OAuth apps Screwdriver.cd works with GitHub, so please register it as an OAuth app from here....

June 23, 2019 · 3 min · Me

Manage k3s With systemd

Introduction This post shows a way to install k3s manually and add rc.local script for automatic launch. I found that k3s install script is more useful because it supports systemd, so I introduce it. Prerequisites 2 or more Raspberry pi installed Raspbian lite Please log in master/node, and add some setings to enable cgroup to /boot/cmdline.txt. Settings to add is cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory. Below is a example of my cluster....

May 18, 2019 · 2 min · Me