20200310のNode.jsに関する記事は7件です。

初めてのGraphQL ~特徴・導入・簡単なクエリまで

最近Reactを学びはじめたこともあって同じFacebookが作ったGraphQLにも手を出してみました。
GraphQLの輪郭もわからない時は「NoSQLのクエリの弱さを独自の検索エンジンで全て解決してくれる魔法のクエリ言語」なんて思ってました。(浅はかなり)

GraphQLを勉強しはじめて2日目で書いた記事なのであやふやなところや間違ってる点など多々あると思います...

GraphQLとは

実際のところはクエリとレスポンスの構造に対応関係を持たせることができたり、スキーマ設定によりエディタにおける補完や型チェックなどが行えたり、REST APIと違い処理によってGETエンドポイントを分ける必要がなく冗長化を防ぐことができたりと、いわばAPIのフレームワークのような印象を受けました。

イメージ図を作ってみました↓
GraphQL流れ.png

インストール(導入)

今回はNodeベースのexpress + apollo + GraphQLでAPIサーバーをたてていきます。

// プロジェクトフォルダを作成
$ mkdir first_graphql
$ cd first_graphql

// プロジェクトのセットアップ
$ npm init

// 必要なモジュールをインストール
$ npm i --save express apollo-server-express graphql

// index.jsを作成
$ touch index.js

コードを書いていく

index.js

const express = require('express')
const { ApolloServer, gql } = require('apollo-server-express')
const app = express()

// GraphQL言語のschemaを使ったconstruct定義
// レスポンスするデータの型を設定しておく
const typeDefs = gql`
    type Query {
        firstQuery: String
    }
`

// schemaごとに取得ロジックを設定していく 
const resolvers = {
    Query: {
        firstQuery: () => "Hello,world!",
    },
}

const server = new ApolloServer({ typeDefs, resolvers })

server.applyMiddleware({ app })

app.listen({ port: 4000 }, () =>
    console.log(`Server ready at http://localhost:4000${server.graphqlPath}`)

動かしてみる

$ nodemon index.js
//$ node index.jsでも可

動かしたら
http://localhost:4000/graphql にアクセス!
スクリーンショット 2020-03-10 22.17.22.png
こんな画面が出たらうまく立ち上がっています。
これはapolloサーバーが提供しているものでGraphQLへのクエリをGUIでテストすることができます。

クエリを実行してみる

index.jsの↓の部分で設定したQueryを実行してみます。

// GrapohQL言語のschemaを使ったconstruct定義
// レスポンスするデータの型を設定しておく
const typeDefs = gql`
    type Query {
        firstQuery: String
    }
`
// schemaごとに取得ロジックを設定していく 
const resolvers = {
    Query: {
        firstQuery: () => "Hello,world!",
    },
}

GUIの左側のエディタに以下の通り書いて実行してみましょう。

{
  firstQuery
}

右側の実行結果画面にこのように表示されればデータの引き出し成功です。

{
  "data": {
    "firstQuery": "Hello,world!"
  }
}

最後に

少し勉強してみるとGraphQLは決して魔法の言語などではなく、型の定義やデータ取得ロジックを自分でしっかり書いていかなければならないということがわかりました。

しかしながらGETエンドポイントを1つに集約できること、フロント側からの直感的なクエリを実装できること、TypeScriptのようにコード管理を容易にしてくれることなどなど...便利なことに違いはありません!

まだまだ勉強しはじめたばかりなのでこれからどんどん知識を蓄えていきたいと思います!

それでは!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

IBM CloudでNode-REDを開始する手順【2020/03最新版】

はじめに

ここでは、IBM Cloud上でビジュアルプログラミング用のフローベース開発ツールであるNode-REDを使用・開始する手順を説明します。

なぜこんなことを今更書くのかというと、ずばりIBM CloudのUIが変わり私自身が混乱したためです。
以前は Qiita: IBM CloudでNode-REDの立ち上げ方IBM Developer: Node-RED を使用してリアルタイムのチャット・アプリケーションを 5 分で作成する に書かれているような手順、つまりカタログのサービスメニュからNode-RED Starterが探せ、かつ比較的簡単にアプリが開始できたため迷うこともなかったのですが、これが(個人的に)大きく変わったため同じく困る人がいるのではないかと想像し、最新版として記載することとしました。

なお、当記事の情報は2020年3月10日時点の情報です。
きっとまた変わることがあると思います。その時にはご容赦ください。

0. IBM Cloudにログイン

https://cloud.ibm.com よりIBM Cloudにログインします。

1. Node-RED Appを構成

1-1. 「カタログ」をクリック

まずは以前と同じくダッシュボード上部にあるく「カタログ」をクリックします。

image.png

1-2. 「ソフトウェア」メニューから「Node-RED App」を作成

ここで早速変更点です。
以前は「サービス」メニューからNode-Red Starterを選択していましたが、現在は「ソフトウェア」メニューから「Node-RED App」を選択する手順になっています。
Node-RED Appを見つけ、「作成」をクリックします。

image.png

1-3. アプリの作成

上部にある「アプリの作成」ボタンを押してアプリの作成を開始します。

image.png

アプリの詳細およびCloudantサービスに関する詳細を入力します。

  • アプリの詳細 - アプリ名: 任意のアプリケーション名を入力して下さい。
  • Cloudant - リージョン: 好みのリージョンを選択します。現在は「東京」も選択可能です。
  • Cloudant - 価格設定プラン: ある種一番重要です。無料のプランで始めたい場合は、「Lite」プランとなっていることを確認してください。

入力が完了したら、上部の「作成」ボタンを押します。

image.png

アプリが作成されると以下の画面に戻ります。

image.png

ここでまた変更点です。
以前ならこの時点で「アプリ URL にアクセス」というリンクが、アプリ名の右横に表示され即座にフローエディタにアクセスが可能でした。
しかし、現在のUIではそうなっておらず、ここからまたいくつかステップを踏む必要があります。

2. Continuous Delivery の構成

2-1. アプリのデプロイ

1-3の画面から続けます。
右側もしくはCloudantの下にContinuous Delivery の構成メニューがあるので、その中の「アプリのデプロイ」をクリックします。

image.png

2-2. DevOpsツールチェーンの構成

DevOpsツールチェーンを構成するための詳細入力画面が表示されるので、必要な値を入力していきます。
なお、当構成を完了させるには、事前に「Cloud Foundryの組織」および「スペース」を作成しておく必要があります。
適切に作成されていない場合、以下のが表示されるため、右サイドバーの「組織を作成します。」から対応します。

image.png

  • IBM Cloud API 鍵: 「New」ボタンをクリックするとCreate a new API key with full accessというダイアログが表示されます。
    チェックボックスのSave this key in a secrets store for reuseは、このキー(鍵)を他のツールチェーンやスターター・キット・ワークフローなどで再使用する場合に選択します。 これにより、IBM Key Protect シークレット・ストアと統合され、そこにキーが保存されます。
    内容を確認したら「OK」をクリックします。

image.png

  • インスタンスの数: 必要なインスタンス数をプルダウンから選択します。
  • インスタンス当たりのメモリー割り振り: 必要なメモリー量を選択します。
  • デプロイするリージョン: リージョンを選択します。この記事の時点では「ダラス」が自動選択されました。
  • 組織: Cloud Foundry組織情報に基づき、自動で入力されますので、適切なものを選択します。
  • スペース: Cloud Foundry組織情報に基づき、自動で入力されますので、適切なものを選択します。
  • ホスト: アプリ名と同じものが自動で入ります。アプリ名から変えることも可能です。
  • ドメイン: プルダウン形式でいくつかのドメインが選択可能です。
  • DevOpsツールチェーン名: アプリ名と同じものが自動で入ります。アプリ名から変えることも可能です。
  • ツールチェーンのリージョン: いくつかのリージョンから選択可能です。

入力が完了したら、上部の「作成」ボタンをクリックします。

image.png

ツールチェーンの作成が完了すると、以下の通りツールチェーンが表示されます。

image.png

2-3. Delivery Pipelineの確認

Delivery Pipelineの状況の横の「進行中」からBUILD/DEPLOYの進捗が確認可能です。
数分でDEPLOYまで完了するはずですので、正常に完了することを確認します。

image.png

DEPLYの枠内にあるジョブ部分の「ログおよび履歴の表示」をクリックすればDEPLOYに関する詳細なログを確認できます。

3. Node-REDフローエディタの開始

3-1. 「リソース・リスト」から「Cloud Foundry アプリ」をクリック

ここまでくると、やっとフローエディターが開始できます。
ハンバーガーメニューから「リソース・リスト」をクリックします。

image.png

リソース・リストでは、Cloud Foundry アプリセクションとAppsセクションに今回作成しているアプリが表示されます。
実はフローエディターへはどちらを選んでも辿り着けますが、ここではDEPLOYされたアプリの詳細が確認可能な、かつ従来と似た画面であるCloud Foundry アプリセクションのアプリをクリックします。

image.png

3-2. 「アプリ URL にアクセス」をクリック

やっと以前の画面が表示されました。
「アプリ URL にアクセス」をクリックして、フローエディタを開始しましょう。

image.png

ちなみに、3-1で選択しなかったAppsセクションの方は以下のようになっています。
最初はなかった「Apps URL にアクセス」が追加されています。

image.png

4. Node-REDフローエディタの設定

アプリの初回アクセスでは、従来通り設定メニューが表示されます。
ここでは多くを語りませんが、従来通りユーザーやそのパスワードを設定します。

image.png

5. フローエディタの起動

設定が完了すると、Node-RED on IBM Cloudの初期画面が表示されます。
「Go to your Node-RED flow editor」をクリックして、フローエディタでの開発を開始しましょう。

image.png

終わりに

当手順は以下リンク先の英語のTutorialを参考に実施しました。
いくつか簡素化しているところもあるので、興味のある方はリンク先を参照してください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Windows] Dockerを使用してホスト環境を汚さずにAngularの開発環境を構築する

TL;DR

  • Node.jsの開発環境をDockerをまとめたかった
  • ローカル環境にはDocker Desktopとvisual studio codeのみインストール
  • Angularでng newから書いている記事がなかったので書いた。これをベースに開発環境を育てていってほしい

環境

  • Windows10
  • Docker Desktop 2.2.0.3
  • docker-composeはDocker Desktopに同梱
  • visual studio code 1.42.1[Dockerの拡張機能を使用]

完成したリポジトリ

https://github.com/MegaBlackLabel/angular-docker-sample

ファイル

\---node-angular-sample
│  .gitignore
│  docker-compose.yml
│  docker-entrypoint.sh
│  Dockerfile
Dockerfile
FROM node:lts

COPY docker-entrypoint.sh ./
COPY ./frontend ./

RUN npm install -g @angular/cli

WORKDIR /frontend

EXPOSE 4200

ENTRYPOINT ["/docker-entrypoint.sh"]
docker-compose.yml
version: '3'

services:
  node:
    build: .
    environment:
        NG_CLI_ANALYTICS: "ci"
        NG_CLI_ANALYTICS: "false"
    ports:
        - "4200:4200"
    volumes:
        - "./frontend:/frontend"
        - nodemodules:/frontend/node_modules
    tty: true

volumes:
    nodemodules:
        driver: "local"
  • マウントしているfrontendについては初回起動時に作成する
  • NG_CLI_ANALYTICS、NG_CLI_ANALYTICSはnpm ci実行時に途中で確認メッセージが出て止まらないようにするために設定
docker-entrypoint.sh
#start SQL Server, start the script to create/setup the DB
#!/bin/bash

FILE="/frontend/package.json"
if [ -e $FILE ]; then
  npm ci
fi

/bin/bash
  • package.jsonがあるときはnpm ciを実行する
  • /bin/bashを実行してコンテナが停止しないようにする

マウントするフォルダの作成

docker-composeに記載しているホストのマウント先のフォルダを作成(無いとdocker-compose起動時にエラー発生)
mkdir frontend\node_modules

docker-composeビルド

コンテナのビルドを実施
docker-compose build

docker-compose起動

ビルドしたコンテナをバックグラウンドで起動
docker-compose up -d

Angularのプロジェクト作成

起動しているコンテナにアタッチしてコマンド実行
cd ..
ng new frontend --skipGit=true

※、これでfrontendフォルダにAngularプロジェクトが作成されます

Angular起動

外部から見えるようにhostを設定します
# attach shell
ng serve --host=0.0.0.0

docker-compose終了

コンテナを初期化して終了
docker-compose down -v

Angularプロジェクト作成後のフォルダ構成(.git内は省略)

\---node-angular-sample
│  .gitignore
│  docker-compose.yml
│  docker-entrypoint.sh
│  Dockerfile
│
└─frontend
    │  .editorconfig
    │  .gitignore
    │  angular.json
    │  browserslist
    │  karma.conf.js
    │  package-lock.json
    │  package.json
    │  README.md
    │  tsconfig.app.json
    │  tsconfig.json
    │  tsconfig.spec.json
    │  tslint.json
    │
    ├─e2e
    │  │  protractor.conf.js
    │  │  tsconfig.json
    │  │  
    │  └─src
    │          app.e2e-spec.ts
    │          app.po.ts
    │
    ├─node_modules
    └─src
        │  favicon.ico
        │  index.html
        │  main.ts
        │  polyfills.ts
        │  styles.scss
        │  test.ts
        │
        ├─app
        │      app.component.html
        │      app.component.scss
        │      app.component.spec.ts
        │      app.component.ts
        │      app.module.ts
        │
        ├─assets
        │      .gitkeep
        │
        └─environments
                environment.prod.ts
                environment.ts

git cloneして使う場合

初回時にマウント先のフォルダを作成
mkdir frontend\node_modules
docker-compose build

まとめ

この構成だとホストにNode.jsをインストールしないで初めからDockerの開発環境で進められる。
ただし、作成済みのプロジェクトをgit cloneして使う際にはnode_modulesを作成する必要があるので注意。

以上

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WSL(openSUSE)にNode.jsをインストールする

はじめに

せっかくの春休み中なので勉強を兼ねて新しいことに挑戦したいと思い、Electornを触ってみることにしました。
今回は前準備として、WSLにNode.jsとnpmをインストールしました。

2020/3/10:追記
WebStormとWSL使ってやろうとしてたんですが現状動かせそうにないです・・・。
素直にWindowsにNode.jsインストールしてやったほうが確実な気がします。

開発環境

  • Windows 10 Pro 1909
  • WSL(openSUSE-Leap-15-1)

Node.jsのインストール

WSLを起動し、リポジトリにあるnodejsのバージョンを調べます。

$ sudo zypper se nodejs
Loading repository data...
Reading installed packages...

S | Name                    | Summary                                          | Type
--+-------------------------+--------------------------------------------------+-----------
  | nodejs-common           | Common files for the NodeJS ecosystem            | package
  | nodejs-emojione         | A set of emojis designed for the web             | package
  | nodejs-emojione-awesome | Emojione templates                               | package
  | nodejs-emojione-demo    | EmojiOne Demos                                   | package
  | nodejs-emojione-meteor  | EmojiOne utility for Meteor                      | package
  | nodejs-emojione-python  | EmojiOne utility for Python                      | package
  | nodejs-emojione-swift   | EmojiOne utility for swift                       | package
  | nodejs-packaging        | Node.js Dependency generators for openSUSE       | package
  | nodejs-underscore       | A utility belt library for JavaScript            | package
  | nodejs10                | Evented I/O for V8 JavaScript                    | package
  | nodejs10                | Evented I/O for V8 JavaScript                    | srcpackage
  | nodejs10-devel          | Files needed for development of NodeJS platforms | package
  | nodejs10-docs           | Node.js API documentation                        | package
  | nodejs8                 | Evented I/O for V8 JavaScript                    | package
  | nodejs8                 | Evented I/O for V8 JavaScript                    | srcpackage
  | nodejs8-devel           | Files needed for development of NodeJS platforms | package
  | nodejs8-docs            | Node.js API documentation                        | package
$ sudo zypper info nodejs10
Loading repository data...
Reading installed packages...


Information for package nodejs10:
---------------------------------
Repository     : leap-15.1-update
Name           : nodejs10
Version        : 10.16.3-lp151.2.6.1
Arch           : x86_64
Vendor         : openSUSE
Installed Size : 23.6 MiB
Installed      : No
Status         : not installed
Source package : nodejs10-10.16.3-lp151.2.6.1.src
Summary        : Evented I/O for V8 JavaScript
Description    :
    Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js
    uses an event-driven, non-blocking I/O model. Node.js has a package ecosystem
    provided by npm.

v10.16.3が最新のようなので、今回はnodejs10をインストールします。
同時にnpm10もインストールします。

$ sudo zypper in nodejs10 npm10

インストールが終わったらバージョン確認をします。

$ node -v
v10.16.3
$ npm -v
6.9.0

無事インストールできていることが確認できました。

今回は以上になります。
次は実際にElectronを動かしてみるところまでやってみたいと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Node.js: CPU負荷で3秒かかっていた処理を「Worker Threads」で1秒に時短する

本稿では、Node.jsのWorker Threadsとその基本的な使い方について説明します。

本稿で知れること

  1. Worker Threadsの概要
    • Worker Threadsとは何か?
    • それが解決してくれる問題は何か?
  2. worker_threadsモジュールの基本的な使い方
    • スレッド起動時にデータを渡すにはどうしたらいいか?
    • 3秒かかる処理を、並列処理で1秒に短縮する方法。

Worker Threadsとは?

  • CPUがボトルネックになる処理を、別スレッドに負荷分散し、効率的に処理する仕組み。
  • マルチプロセスではなく、シングルプロセス+マルチスレッドのいわゆる「本物のスレッド」です

Worker Threadsが解決する問題

  • Node.jsはシングルプロセス、シングルスレッド。
  • シングルプロセス、シングルスレッドは、シンプルさという利点がある。
  • 一方で、CPUに高い負荷がかかる処理は、他の処理を止めてしまう欠点があった。
  • Worker Threadsは、複数のスレッドを使えるようにすることで、この欠点を解決する。

Worker Threadsが解決しない問題

  • I/Oがボトルネックになる処理。
    • これは、Node.jsの非同期I/OのほうがWorkerより効率的に処理できる。

worker_threadsモジュールとは?

  • JavaScriptを並列(parallel)で実行するスレッドが利用できるモジュール。
  • libuvを用いた本物のスレッド(イベントループやマルチプロセスはない)。
  • Web WorkerそっくりのAPI。つまりフロントエンドの知識が活きる。
  • Node.js 10.5.0から使える。
  • Node.js 11.7.0未満は、--experimental-workerフラグをつけてNodeを起動する必要があった。

child_processモジュール、clusterモジュールとの違い

  • worker_threadsはメモリを共有できる。
  • child_processとclusterはメモリが共有できない。

Pasted_Image_2020_03_12_12_36.png

  • child_process, clusterはワーカー間の通信時にデータを一旦JSONに変換するため、JSONライブラリの制約を受ける。
    • 再帰的なオブジェクトを転送できない。
    • MapSetはデータが消される。
  • worker_threadsはThe structured clone algorithmでデータを複製するため、再帰的なオブジェクトやMapSetも送ることが可能。

worker_threadsモジュール入門

worker_threadsモジュールの基本的な使い方を見ていきましょう。

Workerを起動するには?

まず、Workerを起動する方法を見ておきましょう。Workerの起動はシンプルに言って、Workerクラスをnewするだけです。第一引数は、ワーカーの処理を書いたファイル名です。

main.js
const {Worker} = require('worker_threads')
const worker = new Worker('./worker.js')
worker.js
console.log('Hello from worker')

このmain.jsをnodeで起動すれば、worke.jsがスレッドで実行されます。

console
$ node main.js
Hello from worker

Worker起動時にデータを渡すには?

次に、Worker起動時にmain.jsからデータを渡す方法を見てみましょう。データを渡すには、Workerクラスをnewするときに、第2引数にworkerDataに渡したいデータを入れます。

main.js
const {Worker} = require('worker_threads')
const worker = new Worker('./worker.js', {
  workerData: 'message from main.js!',
})

ワーカー側のコードでは、workerDataworker_threadsモジュールからインポートすることで、渡されたデータを参照できます。

worker.js
const {workerData} = require('worker_threads')
console.log('Hello from worker')
console.log(workerData)

この例では、'message from main.js!'がワーカーに伝わっているのがわかります。

console
$ node main.js
Hello from worker
message from main.js!

workerDataは複製される

Workerにデータを渡せることは渡せるのですが、共有はされないので注意してください。次の例では、配列をワーカーに渡し、ワーカーがその配列を変更するコードですが、main.jsにはワーカーが加えた変更が伝わってきません。つまり、workerDataで渡されるデータは、複製されるのです。

main.js
const {Worker} = require('worker_threads')
const workerData = [1, 2, 3]
const worker = new Worker('./worker.js', { workerData }) // オブジェクトを渡す

setTimeout(() => console.log('main.js: %O', workerData), 1000) // どうなる?
worker.js
const {workerData} = require('worker_threads')
console.log('worker.js %O', workerData)
workerData.push(4, 5, 6) // Worker側で変更を加える
console.log('worker.js %O', workerData)
実行結果
worker.js [ 1, 2, 3 ]
worker.js [ 1, 2, 3, 4, 5, 6 ]
main.js: [ 1, 2, 3 ]

複数のWorkerを起動するには?

Workerにデータを渡す方法が分かったので、今度は複数のWorkerを起動してみましょう。

複数のWorkerを起動するには、単純にWorkerインスタンスを複数作るだけです:

const {Worker} = require('worker_threads')
const worker1 = new Worker('./worker.js', {
  workerData: 'worker1',
})
const worker2 = new Worker('./worker.js', {
  workerData: 'worker2',
})
const {workerData} = require('worker_threads')
console.log(`I'm a ${workerData}`)
実行結果
$ node main.js
I'm a worker1
I'm a worker2

CPU高負荷な処理を分散してみよう

worker_threadsモジュールの基本的な使い方が分かったと思うので、CPU高負荷な処理をマルチスレッドで分散することを試してみましょう。

高負荷な関数を準備する

処理分散を試すために、CPUに高負荷がかかり、処理に時間がかかる関数を用意します。

このhighLoadTask関数は、単純に20億回ループするだけですが、実行するとCPU使用率が100%になるくらいの負荷が発生します。(CPUの性能によって実行時間が左右されるので、手元の環境で実行してみる際は、20億回の部分を調整して数秒で終わる程度の回数に直してください)

highLoadTask.js
function highLoadTask() {
  for (let i = 0; i < 2_000_000_000; i++) {
  }
}

module.exports = {highLoadTask}

どのくらい負荷と時間がかかるか確認してみよう

highLoadTask関数をシングルスレッドで3回実行するようにしたコードが次です:

main.js
const {highLoadTask} = require('./highLoadTask')

console.time('total')

console.time('task#1')
highLoadTask()
console.timeEnd('task#1')

console.time('task#2')
highLoadTask()
console.timeEnd('task#2')

console.time('task#3')
highLoadTask()
console.timeEnd('task#3')

console.timeEnd('total')

このスクリプトを実行すると、(僕のPCでは)合計で約3秒かかります:

実行結果
node main.js
task#1: 1.455s
task#2: 1.460s
task#3: 478.089ms
total: 3.399s

CPU負荷のほうは、Activity Monitorで「node」に検索を絞って、モニタリングすると、99%が使われていることがわかります。使用率が100%を超えていないので、当てられているCPUコア数は1個ということもわかります。(CPU使用率が上がりきらない場合は、highLoadTask関数のループ数を増やしてください)

Screenshot_2020_03_10_10_28.png

CPU高負荷処理は非同期処理でも解決しない

ちなみに、次のようにPromiseを使って各タスクを非同期処理にしても、かかる時間は変わりませんので、この関数はシングルスレッドでは限界があるということが確認できます:

main.js
const {highLoadTask} = require('./highLoadTask')

function asyncHighLoadTask(taskName) {
  return new Promise(resolve => {
    console.time(taskName)
    highLoadTask()
    console.timeEnd(taskName)
    resolve()
  })
}

(async function () {
  console.time('total')
  await Promise.all([
    asyncHighLoadTask('task#1'),
    asyncHighLoadTask('task#2'),
    asyncHighLoadTask('task#3'),
  ])
  console.timeEnd('total')
})()

Workerを使って3秒かかる処理を1秒にする

では実際にWorkerを使って、処理を分散するコードを書いてみます。

まず、Worker側の実装です:

worker.js
const {workerData} = require('worker_threads')
const {highLoadTask} = require('./highLoadTask')
console.time(workerData)
highLoadTask()
console.timeEnd(workerData)

次に、メイン側の実装です。

main.js
const {Worker} = require('worker_threads')

console.time('total')
const worker1 = new Worker('./worker.js', {
  workerData: 'worker1',
})
const worker2 = new Worker('./worker.js', {
  workerData: 'worker2',
})
const worker3 = new Worker('./worker.js', {
  workerData: 'worker3',
})

Promise.all([
  new Promise(r => worker1.on('exit', r)),
  new Promise(r => worker2.on('exit', r)),
  new Promise(r => worker3.on('exit', r)),
]).then(() => console.timeEnd('total'))

main.jsでは、ワーカーを3つ起動して、3並列で処理させるようにしました。

最後のPromise.allの部分は、ワーカーの終了を待って合計所要時間を計測するためのコードですので、ここでは気にしないでください。

実行してみましょう:

実行結果
$ node main.js
worker1: 1.526s
worker3: 1.529s
worker2: 1.529s
total: 1.579s

実行結果を見てのとおり、各タスクの処理は1.5秒程度で変化はありませんが、並列実行したため3秒かかっていた合計所要時間が1.5秒に短縮されました。

気になるCPU使用率は、298%になっているので、コアが3つがきびきび働いているのがわかります。

Screenshot_2020_03_10_10_37.png

おわり

本稿では、Node.jsのWorker Threadsの概要と、worker_threadsモジュールの基本的な使い方を解説しました。

CPUがボトルネックとなる処理をマルチスレッドで分散すると、マルチコア環境で眠っているCPUを効率的に働かせられたり、その結果処理時間を短縮できることが分かったかと思います。

今後投稿するかもしれないこと

本稿では基本的なことがらにしか触れませんでしたが、下記のような疑問も気になるところなので、追って投稿できたらと思います。


最後までお読みくださりありがとうございました。Twitterでは、Qiitaに書かない技術ネタなどもツイートしているので、よかったらフォローお願いします:relieved:Twitter@suin

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Node.jsで簡単にサーバーを立てる

Node.jsでサーバーを立てるモジュールについて書きます。

前提条件

  • npmがインストールされていること
  • package.jsonがあること

インストール

$ npm install -D http-server

使い方

設定

npm run serverコマンドでhttp-serverを動かすように定義します。

package.json
{
  "scripts": {
    "server": "http-server -o"
  }
}

実行

npmコマンドを実行します。

$ npm run server

出力結果

Starting up http-server, serving ./
Available on:
http://127.0.0.1:8080

出てきたパスを叩けば現在のディレクトリのファイルを見ることができます。

参考文献

この記事は以下の情報を参考にして執筆しました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ubuntuで使う言語のインストール方法とか環境構築とか

最近はバックエンド言語毎にVMで環境用意して勉強したりしてて、その環境構築方法の管理を最近はGistでしてるのですが、何となくQittaに。※※但し、Gistは英語で書いてるので。

environment

  • host OS: Windows
  • VM: Virtual Box with Vagrant
    • Ubuntu 18.0

CUIまたはGUIの仮想環境をUbuntuを使って構築するのはこっち。

Ruby on Rails

Install latest version

terminal
# install in one time
sudo apt install autoconf bison build-essential libssl-dev libreadline-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev

# install rbenv
# rbenv is tool to manage a few of ruby versions and enable to change ruby ver. project by project.
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
source ~/.bashrc
git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build

# Install ruby
rbenv install --list
rbenv install 2.〇.〇
rbenv global 2.〇.〇

# Instal yarn
# Rails6 needs webpacker, and Webpacker needs yarn to install
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt update
sudo apt install yarn

# Install Rails
gem install rails --no-document

# install webpacker
# inner App
rails webpacker:install

Install RubyonRails by "apt install"

terminal
sudo apt install -y ruby ruby-dev build-essential
sudo apt install yarn

sudo gem install rails
  • "-y" means "All Yes"
  • build-essential contain information about package to build Debian pack.
    • If do not build Debian, build~ is not needed
    • Reference

Nodejs

rails6 uses webpacker, which needs nodejs

terminal
# first, install nodejs and npm
sudo apt install -y nodejs npm

# install n-package
sudo npm install n -g

# by n-package, install node
sudo n stable

# uninstal old nodejs and npm, and re-login
sudo apt purge -y nodejs npm
exec $SHELL -l

# confirm
node -v

Rust

when discord changed golang to Rust, I just tried this and coded a little.

terminal
sudo apt install build-essential

# install rust
curl https://sh.rustup.rs -sSf | sh

# add the pass
source $HOME/.cargo/env

Java

terminal
sudo apt update
sudo apt install git
sudo apt install openjdk-11-jdk

# confirmation
java --version

PHP

Python

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む