TECH PLAY

株式会社ラクス

株式会社ラクス の技術ブログ

941

noriharu3 です。 業務で AWS の Lambda を使う機会があったので、簡単にまとめてみました。 Lambdaとは? Lambdaの嬉しいところ インフラの管理が不要 使った分だけの支払い Lambdaの場合 どういうことができるのか?苦手なのか? Lambdaが適さないケース Lambda関数開発 環境構築 ローカルPCでLambda関数を作成する ローカルPCでLambda関数を実行する AWSにデプロイする API Gateway+Lambdaにリクエストを送ってみる まとめ Lambdaとは? AWS のドキュメント *1 には、次のように記載されています。 AWS Lambda は、サーバーのプロビジョニングや管理の必要なしにコードを実行できるコンピューティングサービスです。 簡単に言うと、「サーバーを構築しなくとも、コードを実行できるよ」ということです。 図 *2 でいうと、こちらがわかりやすいと思います。 Lambdaの嬉しいところ では、Lambdaの嬉しいところ、メリットについて書いていきたいと思います。 インフラの管理が不要 インフラの管理といっても色々あると思います。 とりあえずセキュリティについて、次のことは AWS *3 が責任をもって対応すると言ってくれています。 AWS Lambda については、 AWS が基盤となるインフラスト ラク チャ、基盤サービス、 オペレーティングシステム 、アプリケーションプラットフォームを管理します。 なので、セキュリティについて開発者は主に次だけしっかりやればいいことになります。 IAMの権限 コードのセキュリティ( 脆弱性 ) 機密データの保管とアクセス管理 古いですが、セキュリティ以外では次のことを担保すると述べていますね。 *4 – キャパシティ – スケール – デプロイ – 耐障害性 – モニタリング – ロギング – セキュリティパッチの適用 なるほど。サーバーやOSの構築だけでなく、スケール管理、モニタリングなどもLambdaの標準サービスとして付帯している。 インフラのメンテナンス時間や定期的なダウンタイムもない。 たしかにこれは運用している人 からし たら嬉しい。 使った分だけの支払い 実際に、LambdaとEC2の月額費用を比較してみましょう。 毎日0時に Python コード(Lambdaで実行した場合の平均時間1分)を実行するものとします。 ※ 計算しやすくするため、1ヶ月は30日とする Lambdaの場合 ちなみに、Lambda では、指定してメモリ量に比例した CPU パワーとその他のリソースが割り当てられます。 メモリはLambdaで指定できる上限の10240MB(10GB)で計算します。 Lambda に512 MB のメモリを割り当て、30回実行し、毎回の実行時間が 60 秒間だった場合、 1 か月のコンピューティング料金 合計コンピューティング (秒) = 30 × 60 秒 = 1,800 秒 合計コンピューティング (GB-秒) = 1,800 × 10,240 MB ÷ 1024 = 18,000 GB-秒 合計コンピューティング – 無料利用枠 = 1 か月の請求コンピューティング GB-秒 18,000 GB-秒 - 400,000 GB-秒の無料利用枠 < 0 1 か月のリクエスト料金 30 件のリクエスト – 1,000,000 件の利用無料枠のリクエスト < 0 合計月額料金 合計料金 = コンピューティング料金 + リクエスト料金 = 0 USD + 0 USD = 0 USD/月 この段階で、EC2の負け確定ですねw 負け戦ですが、EC2の料金はこちら *5 を参照ください。 どういうことができるのか?苦手なのか? できることがたくさんあると思いますが、公式の資料 *6 には下記が記載されていました。 API サーバーの代わり アラート通知 etc Lambdaが適さないケース Lambdaにもいくつか制約があるので注意です。気になったものは下記になります。 大量のリソースが必要となる処理 Lambdaで指定できるメモリの上限 *7 は10240MB(10G) 900秒以上時間がかかる処理 Lambdaで指定できる タイムアウト の上限は900秒 *8 (15分)。900秒以上かかると、Lambdaはエラーを返します。 ペイロード *9 が6MB以上のリク エス トbodyまたはレスポンスbody リク エス トbodyまたはレスポンスbodyの ペイロード が6MB以上あった場合、Lambdaはエラーを返します。 OS、ネットワーク、ストレージレベルで制御したい 好みのOSを選定したい Lambdaは、 Amazon Linux 2 *10 がベースになっています。 Lambda関数開発 続いて、実際にLambdaで実行するコード(以下、Lambda関数)を作成し、動かしてみようと思います。 環境構築 ローカルPCでLambda関数を作成する ローカルPCでLambda関数を実行する AWS にデプロイする API Gateway +Lambdaにリク エス トを送ってみる 環境構築 公式 *11 を参考に、Docker と AWS SAM CLI をインストールします。 Windows , Mac , Linux で手順が異なるようなので、詳細は公式のドキュメントを見てください。以下、 Mac での手順です。 $ brew install docker $ brew tap aws/tap $ brew install aws-sam-cli また sam コマンドのリファレンスはこちら *12 。 ローカルPCでLambda関数を作成する sam init コマンドで、アプリケーションのプロジェクトを作成します。 このLambda関数は、 {"message":"hello world"} というレスポンスを返します。 $ sam init Which template source would you like to use? 1 - AWS Quick Start Templates 2 - Custom Template Location Choice: 1 What package type would you like to use? 1 - Zip (artifact is a zip uploaded to S3) 2 - Image (artifact is an image uploaded to an ECR image repository) Package type: 1 Which runtime would you like to use? 1 - nodejs12.x 2 - python3.8 3 - ruby2.7 4 - go1.x 5 - java11 6 - dotnetcore3.1 7 - nodejs10.x 8 - python3.7 9 - python3.6 10 - python2.7 11 - ruby2.5 12 - java8.al2 13 - java8 14 - dotnetcore2.1 Runtime: 1 Project name [sam-app]: Cloning app templates from https://github.com/aws/aws-sam-cli-app-templates AWS quick start application templates: 1 - Hello World Example 2 - Step Functions Sample App (Stock Trader) 3 - Quick Start: From Scratch 4 - Quick Start: Scheduled Events 5 - Quick Start: S3 6 - Quick Start: SNS 7 - Quick Start: SQS 8 - Quick Start: Web Backend Template selection: 1 ----------------------- Generating application: ----------------------- Name: sam-app Runtime: nodejs12.x Dependency Manager: npm Application Template: hello-world Output Directory: . Next steps can be found in the README file at ./sam-app/README.md sam build コマンドでビルドし、実行できる状態にします。 $ sam build Building codeuri: hello-world/ runtime: nodejs12.x metadata: {} functions: ['HelloWorldFunction'] Running NodejsNpmBuilder:NpmPack Running NodejsNpmBuilder:CopyNpmrc Running NodejsNpmBuilder:CopySource Running NodejsNpmBuilder:NpmInstall Running NodejsNpmBuilder:CleanUpNpmrc Build Succeeded Built Artifacts : .aws-sam/build Built Template : .aws-sam/build/template.yaml Commands you can use next ========================= [*] Invoke Function: sam local invoke [*] Deploy: sam deploy --guided ローカルPCでLambda関数を実行する sam local start-api コマンドで、 API Gateway を模したHTTPサーバーを作成し、擬似的な API Gateway を経由した動作確認を行うことができます。 $ sam local start-api Mounting HelloWorldFunction at http://127.0.0.1:3000/hello [GET] You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template 2021-03-05 17:50:58 * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit) Invoking app.lambdaHandler (nodejs12.x) 別ターミナルで http://127.0.0.1:3000/hello にアクセスします。 お、レスポンスが返ってきましたね。 $ curl http://127.0.0.1:3000/hello {"message":"hello world"} AWS にデプロイする sam deploy -g コマンドで、 AWS にデプロイします。 -g オプションを付けると、デプロイ設定を対話的にすすめることができます。 $ sam deploy -g Configuring SAM deploy ====================== Looking for samconfig.toml : Not found Setting default arguments for 'sam deploy' ========================================= Stack Name [sam-app]: AWS Region [us-east-1]: ap-northeast-1 #Shows you resources changes to be deployed and require a 'Y' to initiate deploy Confirm changes before deploy [y/N]: y #SAM needs permission to be able to create roles to connect to the resources in your template Allow SAM CLI IAM role creation [Y/n]: y HelloWorldFunction may not have authorization defined, Is this okay? [y/N]: y Save arguments to samconfig.toml [Y/n]: y Looking for resources needed for deployment: Found! (以下長いので、省略) API Gateway +Lambdaにリク エス トを送ってみる デプロイは完了しているので、後はリク エス トを送るだけです。 $ curl https://**********.execute-api.ap-northeast-1.amazonaws.com/Prod/hello {"message":"hello world"} まとめ EC2と比較して、Lambdaを使うと大幅なコスト削減ができるかもしれないので、魅力ですね。 また、インフラの管理を AWS に任せることで、運用業務にかかるコストの削減も見込めます。 ただ、Lambdaにはいくつか制約があり、適さないサービスや処理があるので、選定する際は注意です。 また SAM CLI を使えば、 AWS アカウント持っていなくても、さくっとローカルで Lambda 関数を動かすことができるので、興味のあるかたは是非やってみてください。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com *1 : https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/welcome.html *2 : https://www.bit-drive.ne.jp/managed-cloud/column/images/column14/img_01.jpg *3 : https://d1.awsstatic.com/serverless-jp/Security%20Overview%20of%20AWS%20Lambda_JP.pdf *4 : https://d1.awsstatic.com/webinars/jp/pdf/services/20150701_AWS-BlackBelt-runcodeinthecloud.pdf *5 : https://aws.amazon.com/jp/ec2/pricing/on-demand/ *6 : https://d1.awsstatic.com/webinars/jp/pdf/services/20150701_AWS-BlackBelt-runcodeinthecloud.pdf *7 : https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-console.html *8 : https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-console.html *9 : https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/gettingstarted-limits.html *10 : https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-runtimes.html *11 : https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html *12 : https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-sam-cli-command-reference.html
技術広報の syoneshin です。 今回は当社の開発組織メンバー達に 『おすすめのITエンジニア向けイベント』 と おすすめの理由を聞きました。 質問:皆さんの「おすすめのエンジニア向けイベント」 を教えてください。 【目次】 『PHPerKaigi』 『AWS Summit 』 『JJUG CCC』 『Web × PHP TechCafe』 『PostgreSQLアンカンファレンス』 『なるセミ』 『PHP Conference Japan』 『デブサミ・デブサミ関西・デブスト』 『Builders Box』 『プロダクトマネージャーカンファレンス』 『自動化大好きエンジニアLT会』 ITエンジニア向けイベント情報が検索できるサイト 6選 まとめ まず当社開発メンバーが選んだ「おすすめのITエンジニア向けイベント」は 『PHPerKaigi』 phperkaigi.jp 以下はおすすめ理由やポイント イベント自体はカジュアルな雰囲気で、参加者間での交流も盛んな印象です。 開催日3/27 に「 PHP でも アーキテクチャ テストしたい!」の発表テーマで登壇します! 開催日3/28に LT登壇します!是非、ご参加下さい! 次いで、当社開発メンバーが選んだ「おすすめのITエンジニア向けイベント」は 『 AWS Summit 』 partners.awscloud.com 以下はおすすめ理由やポイント AWS の最新情報、導入事例などが知れて勉強になりおすすめです。 基礎的な セミ ナー時間もあるので初心者にもおすすめです! 次いで、当社開発メンバーが選んだ「おすすめのITエンジニア向けイベント」は 『 JJUG CCC』 www.java-users.jp 以下はおすすめ理由やポイント 直近の Java の動向や流行りを知れるため、おすすめです。 Java 関連の技術や事例に関するセッションが豊富。 JJUG CCC 2020 Fallには当社メンバー2名が登壇しました! 次いで「おすすめのITエンジニア向けイベント」は 当社主催のイベント 『Web × PHP TechCafe』 rakus.connpass.com 以下はおすすめ理由やポイント レベルは高すぎず、会話ベースの進行のため、オンライン参加がしやすく、ラジオのように聞きながら情報をピックアップできる点がおススメです。 ゆるく雑談形式で最新のトピックを知ることができるので良いです。 外部から一緒に語り合ってくれる方も、聞き専門の方も増えているイベントです!是非、ご参加下さい! 次いで「おすすめのITエンジニア向けイベント」は 『 PostgreSQL アンカンファレンス』 pgunconf.connpass.com 以下はおすすめ理由やポイント PostgreSQL の新機能や内部的な仕組み、お試し系の検証結果などを知ることができて勉強になります。 毎年メジャーバージョンアップの時期に実施されるので、情報収集がてら参加するのは良いと思います。 次いで「おすすめのITエンジニア向けイベント」は 『なる セミ 』 nrs-seminar.connpass.com 以下は気になった理由やポイント 設計系ではよくお世話になっているイベントの一つです。 毎回テーマは違いますが、参考になるイベントが多いです! 次いで「おすすめのITエンジニア向けイベント」は 『 PHP Conference Japan』 phpcon.connpass.com 以下は気になった理由やポイント 2020開催のイベントには当社メンバー2名もLT登壇! 毎年、人も活気もすごいイベントです! 次いで「おすすめのITエンジニア向けイベント」は 『 デブサミ ・ デブサミ 関西・デブスト』 event.shoeisha.jp 以下はおすすめの理由やポイント デブサミ 関西は関西では数少ない大きなイベント。著名人も多く登壇されており、直接お話を伺え、刺激を受けやすいと思います。 デブストは同年代のエンジニアがやっていることを知れる、いい機会でした。 今期の デブサミ 関西とデブストにはそれぞれ当社メンバーも登壇しました! 次いで「おすすめのITエンジニア向けイベント」は 『Builders Box』 buildersbox-online.com 以下はおすすめの理由やポイント Sansan社が主催しており、著名な方のセッションが聞ける貴重なイベント。 国内の Saas 企業とコラボしたイベントなどもあり、内容はどれも面白くおすすめ。 次いで「おすすめのITエンジニア向けイベント」は 『プロダクトマネージャーカンファレンス』 2020.pmconf.jp 以下はおすすめの理由やポイント PdM意外の方でも、どうプロダクトへ貢献すべきかを理解する良い機会になります。 前回イベントで、PdMの最新情報をキャッチアップできました。 次いで「おすすめのITエンジニア向けイベント」は 当社主催のイベント 『自動化大好きエンジニアLT会』 rakus.connpass.com 以下は気になった理由やポイント テストやインフラ構成管理など、様々な分野における自動化が取り上げられていました。 LT登壇者が多く、豊富な自動化の事例が学べるイベントです! その他、以下のITエンジニア向けイベントを、当社エンジニア達が推薦しておりました。 『Spring Fest』 jsug.doorkeeper.jp 『 VSCode Meetup』 vscode.connpass.com 『Vue Fes Japan』 vuejs-jp.org 『CloudNative Days』 cloudnativedays.jp 『 スクラム フェス大阪』 www.scrumosaka.org 『 ソフトウェアテスト 自動化カンファレンス』 testautomationresearch.connpass.com 『 CSS Nite 』 cssnite.jp などなど 全50件近くの「おすすめのITエンジニア向けイベント」が 当社内で共有されました。 ITエンジニア向けイベント情報が検索できるサイト 6選 ここでは、ITエンジニア向けイベントの情報が探せるサイトをご紹介します。 TECHPLAY techplay.jp connpass connpass.com DoorKeeper www.doorkeeper.jp Street academy www.street-academy.com Peatix https://peatix.com/ peatix.com OpenCU www.opencu.com まとめ 以上、いかがだったでしょうか。 昨年からITエンジニア向けイベントもオンライン開催が主流になり 皆さんも、イベントを「はしご」する機会が増えたのではないかと思います。 当社も情報発信と交流を通じた見識を広める機会として、週1~2回ほど多様なテーマでイベントを主催しております。 もし、当社イベントに少しでもご興味をお持ちいただけましたら 、是非ご参加下さい。 主催イベント一覧 rakus.connpass.com 本記事でご紹介した おすすめのITエンジニア向けイベント が皆さまの情報探索の一助となれば幸いです。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
はじめに 技術広報のyayawowoです。 いつも ラク スのエンジニアブログのご購読、そしてエンジニアイベントへのご参加、ありがとうございます。 今回は、『 開発戦略・マネジメント・設計 』をテーマに実施した、2021年最初の ラク スMeetup 2Daysの様子をお届けします! 本記事では、2/17(水)にお届けした 『PdM・インフラ戦略』 について紹介させていただきます。 ※2/16(火)【Meetup】PM・ リファクタリング 戦略は こちら はじめに イベントテーマ概要 発表の紹介 ロバストネス分析を用いた設計と工数見積もり JavaCCとSpring Expression Languageを用いたユーザ定義項目 開発を止めるという選択 インフラ業務のモデリングについて考えてみた おわりに イベントテーマ概要 Day2では人気の楽楽シリーズを担当しているエンジニア陣を中心に、大規模な SaaS 開発におけるエピソードや、多数のサービスを展開中の ラク スが構想しているインフラ戦略を紹介しました。 今回は以下サービスに携わるエンジニア3名と、 ラク ス全体のインフラ基盤を支えるエンジニア1名の計4名が登壇させていただきました。 楽楽勤怠 楽楽精算 楽楽明細 発表の紹介 それではここから各発表内容と資料を共有させていただきます! ロバストネス分析 を用いた設計と 工数 見積もり まずは楽楽精算のサブリーダである坂田が、設計工程で取り入れている ロバストネス分析 を用いた設計と 工数 見積もりについて、紹介させていただきました。 目新しい手法ではありませんが、システム構成を三つの要素で抽象化し、それらの関係性を非常に簡単な図で表現することができる優れた手法です。 またこれを行うことにより改修範囲の要 素数 が 定量 的に洗い出せることから、楽楽精算開発チームでは、これらの分析結果を応用した 下流 工程の 工数 見積もりも行っています。 今回はこれらの取り組みとその効果に関して紹介しました。 speakerdeck.com JavaCC とSpring Expression Languageを用いたユーザ定義項目 次に、楽楽勤怠チームの山口の発表です。 楽楽勤怠にてカスタム項目というユーザが楽楽勤怠に標準で持っているプロパティの値を利用して、独自に計算式を定義できる機能を開発しています。 この機能を開発する際は計算式をどうやって評価し、計算式からどうやって計算結果を算出するのかが肝となりました。 この肝となった部分についてフロントエンドとバックエンドの役割分担や実現方法を紹介しました。 speakerdeck.com 開発を止めるという選択 ラク スでは、開発チームに プロダクトマネジメント の人員を各商材配置し、意思決定から価値の提供までのスピードをあげる取り組みを行っています。 しかし、一言に「 プロダクトマネジメント 」といってもその取り組みに唯一解はなく広範囲に渡るため、試行錯誤しながら日々取り組んでいるのもまた現実です。 プロダクトマネジメント の大きな目的である、「求めている顧客に早く価値を届ける」という目的と、自分の過去の経験が邪魔をしたことで、失敗した 経験談 を超上流(サービス仕様)決定に携わっている松浦が紹介しました。 speakerdeck.com インフラ業務の モデリング について考えてみた 最後は、 ラク ス全体のインフラ基盤の責任者である竹田より、インフラ業務の モデリング についてです。 大規模な SaaS 開発の裏側では Saas サービスのサービス・機能特徴に合わせた独自技術がどんどん導入されています。 今回は アプリ開発 職よりはるかに少ないメンバーで組織運営を行う組織の中で、 増え続けるサービス、技術の深い理解 サービス・事業要件に応えるインフラ基盤 「安定・安心・安全(3A)」 を効率よく実現させ、コスト部門として設備管理にかかる費用の低減を続けるにはこれから何をしていくべきかを考察し、ご紹介しました。 speakerdeck.com おわりに 2021年最初の ラク スMeetupはどうでしたか? 今回の4名の発表が、皆さまにとって新しい気づきや成長につながる機会となっていますと幸いです! 今後も ラク スMeetupでは日々のエンジニアの取り組みを発信してまいりますので、次回もぜひご参加いただけますと幸いです。 また、前日に開催した 【Meetup】PM・リファクタリング戦略 も別記事にまとめておりますので、是非ご確認ください! そして直近ですが、 PdM がテーマのイベントを3/18(木)に開催予定です! プロダクト設計、開発、デザインの PdM にご興味のある方は、ぜひconnpassをご確認いただければと思います。 ご参加お待ちしております! rakus.connpass.com
はじめに 技術広報のyayawowoです。 いつも ラク スのエンジニアブログのご購読、そしてエンジニアイベントへのご参加、ありがとうございます。 今回は、『 開発戦略・マネジメント・設計 』をテーマに実施した、2021年最初の ラク スMeetup 2Daysの様子をお届けします! 本記事では、2/16(火)にお届けした 『PM・ リファクタリング 戦略』 について紹介させていただきます。 ※2/17(水)【Meetup】PdM・インフラ戦略は こちら はじめに イベントテーマ概要 発表の紹介 14年目のサービスと今後も歩むためのリファクタリング戦略 仮想基盤サーバのリプレイスに伴うインフラ設計 入社4ヶ月の新入りPdMの取り組み 変化の時代に活かす「みんなのプロジェクトマネジメント」 おわりに イベントテーマ概要 Day1では開発、インフラ、 プロダクトマネジメント 、プロジェクトマネジメントの4つの立場のエンジニアから、今年度 ラク スがチャレンジしてきました取り組みを紹介しました。 今回は以下サービスに携わるエンジニア4名が登壇させていただきました。 配配メール クルメル 楽楽販売 発表の紹介 それではここから各発表内容と資料を共有させていただきます! 14年目のサービスと今後も歩むための リファクタリング 戦略 現在14年目になる配配メールでも長年続くサービスならではの過去からの負債がありました。 また、過去の ソースコード を参考にすることも少なくないので負債は日々増えるばかり… いつか リファクタリング したいと思いながらも肥大化してしまった負債に手が出せないジレンマがありました。 しかし、このままではダメだと一念発起し問題に向き合う事を決め、リリースサイクルに影響を与えず円滑に リファクタリング を進める為に実施した工夫について、配配メール開発担当の西原が紹介しました。 speakerdeck.com 仮想基盤サーバのリプレイスに伴うインフラ設計 次に、「配配メール」「クルメル」のインフラ開発担当である小西の発表です。 ひと言で「設計」といっても様々な事を検討し、形にする必要があります。 基本設計・詳細設計・移行設計・運用設計などの各フェーズでの設計を行い、問題なく実行できるようにする必要があります。 今回は、仮想基盤サーバのリプレイスを通じて実際に行った設計の一部をご紹介し、今後のサービス運用と継続的な改善に繋がるインフラチームとしての設計方針を発表しました。 入社4ヶ月の新入りPdMの取り組み 楽楽販売(旧名:働くDB)はローンチから10年以上、たくさんのユーザ様に利用されているシステムです。 これまで営業 / CS / 企画 / 開発とお互いの領域を研ぎましていたフェーズから、今後のさらなる成長を目指し、各部門を超え組織横断でプロダクト強化を行うための活動について、入社直後の永橋がPdMとしてどう取り組んだかをご紹介しました。 
入社4ヶ月 新入りPdMの取り組み from Tsuyoshi Nagahashi www.slideshare.net 変化の時代に活かす「みんなのプロジェクトマネジメント」 最後に、配配メール開発チームのエンジニア リングマ ネージャである大塚の発表です。 「プロジェクトマネジメント」はプロダクト開発の役割であると同時にエンジニアのスキルセットでもあります。 プロジェクトをゴールに導くこのスキルセットは不確実な変化の時代にエンジニアが取るべき行動のヒントを与えてくれます。 今回はこれまでの SaaS プロダクト開発の現場で実践してきた事例を「プロジェクトマネジメント」の視点でご紹介し、チームのリーダーやマネージャーを目指す人はもちろん、変化の時代を生き抜く全てのエンジニアにおすすめしたい「みんなのプロジェクトマネジメント」についてお話ししました。 speakerdeck.com おわりに 今年度 ラク スがチャレンジしてきました取り組みは、いかがでしたでしょうか? ラク スの取り組みが、皆さまにとって新しい気づきや成長につながる機会となっていますと幸いです! 今後も ラク スMeetupでは日々のエンジニアの取り組みを発信してまいりますので、次回もぜひご参加いただけますと幸いです。 また、翌日に開催した 【Meetup】PdM・インフラ戦略 も別記事にまとめておりますので、是非ご確認ください! そして直近ですが、 PdM がテーマのイベントを3/18(木)に開催予定です! プロダクト設計、開発、デザインの PdM にご興味のある方は、ぜひconnpassをご確認いただければと思います。 ご参加お待ちしております! rakus.connpass.com
株式会社 ラクス のrakusMoritaです。 2021年2月22日にオンラインで開催された Laravel Meetup Tokyo Vol.13 に参加したので、内容のポイントをまとめてみました。 どの話も興味深く、そして実践しやすい内容だったので共有させていただきます。 laravel-meetup-tokyo.connpass.com Laravelと継続的デプロイ スピードと質を求められている状況下での基本構成 注意点等 継続的なデリバリのために組織として取り組むこと DDD入門とLaravel DDDの理解でよくある間違い 結局DDDって何? DDDのメリット どうやって実践するの? よく聞く軽量DDDとはどう違うの? 実装するには Laravel8で使えるJavaScriptパッケージ「Inertia.js」が便利 TDD視点から見るRequestクラスの依存性 まとめ Laravelと継続的デプロイ スピードと質を求められている状況下での基本構成 クラウド ・コスト削減 ・スケーラビリティが容易 コンテナ ・作業時間短縮 ・DevOpsとの相性良い 注意点等 ログの構造化は必須 AWS のCloudWatch等で、ログは構造化( JSON 化)しておくとのこと。 視認性が格段にアップして開発や デバッグ ・調査の時短になる。 vendor内をコンテナ化していると、ビルドに時間がかかったりする場合がある 安定性は向上するので、どちらを取るかは組織内で要相談。 デプロイを自動化していたとしても、突然デプロイが失敗することもある デプロイが短時間でできると思っていても、デプロイ当日にパニックになることもあるので、余裕を持ったスケジュール組むこと。 そして、定期的なデプロイをして、突然の「動かない」を極力なくす。 継続的なデリバリのために組織として取り組むこと 運用できる人を増やす 一部の人しか触れないではなく、なるべく多くの人が携わる。 関係者を巻き込みながら、少しずつやれることを増やしていく 体制面でも継続可能な状況を作ることが理想。 ログの構造化は確かに必須ですね。個人的に即効性があって良いと思いました。 DDD入門とLaravel 最近よく耳にする「 ドメイン 駆動設計」、通称「DDD(domain-driven design)」ですが、具体的にわかりにくいと思いませんか? 今回具体的にどういうことなのかを掘り下げた内容が聞けて勉強になりました。 DDDの理解でよくある間違い 「 アーキテクチャ で、層に分かれて実装すれば良い」  これ、間違いです 「 DDDでデータベース肥大化対策どうやるの?」  実は関係ありません 「 MVC ではDDDはできないのでは?」  これも全く関係ありません 「DDDで実装したけど、全然楽になりません」  長期的に見ると楽になるはず・・・ 結局DDDって何? 開発スタイルのひとつ 「実現したいこと」 や 「解決したい問題」 、それを 「 ドメイン 」 という。 その「やりたいこと」を起点として開発していくのがDDD。 実装言語や フレームワーク 、ストレージや アーキテクチャ などは含まれない 一般的な非機能要件は含まれない。 機能要件が含まれる。 DDDは、どういう アーキテクチャ で、どういう言語、 フレームワーク 、データベース・・・などの技術的な要素とは一切関係なく、 何を作るのか? それを考えて実現していくことだったのですね。 一般的な「 ドメイン 」と違うのが理解し難くしている原因の一つかもしれません。 DDDのメリット 何をしたいかをまず考えるため、先を見越した設計ができる 開発チームで共通の認識が生まれ、認識のずれからくるやり直しや確認が減る 突然の仕様変更に困ったことはありませんか?システムや機能の根幹を揺るがしかねない事態になる可能性だって往々にしてあります。 そういう事態を未然に防ぎやすいのがDDDの特徴です。 「何を実現したいか」が関係者で共有ができているため、設計段階から将来の変更を見越したものが作りやすいというわけです。 膨大な改修コストや、目的からずれた不要な機能開発とはこれでおさらばです。 どうやって実践するの? カスタマーサービス チームに加わったり企画会議に参加して、開発以外の概念理解や知識をつける ユーザー層や実現したいこと、チーム構成は変わっていくため、継続的にコミュニケーションや分析を行う チーム全員で ドメイン (会社が提供したい価値)モデルを導き出し、全員で同じ認識と同じ言語で共通理解をする 言葉の認識を合わせていくことが大切とのこと。 例えば「ユーザー」という言葉でも、エンジニアは「DBのユーザーテーブルのことだな」と思っていても、実際は「会員」を指しているのかもしれないし、「有料会員」のことを指すのかもしれない。 まずはその共通認識を行うことが第一歩。 文脈でもその意味は変わってくるので、そのバックグラウンドに基づく知識が共有できていれば、迷いやすれ違いが少なくなるとのこと。 よく聞く軽量DDDとはどう違うの? 軽量DDDとは、DDDで得られた知識を反映しやすい実装パターン、構造だけを採用したもので、DDDとは別物です。 こちらの意味だけが先行して、DDDの本質を見失う人も多そうな印象ですね。 実装するには Laravel等を用いて開発するときは、DDDの知識を落とし込みやすいパターンを無理に最初から実現しなくても良い 処理の共 通化 を行わず、まずは分析と知識に基づいて、クラスにする 同じような箇所はコピペでも良い。あとから共 通化 させるほうが収束しやすいし、 リファクタリング もしやすい。 まずは本当に共 通化 すべきもののみ共 通化 すること。 余談ですが、「設計をちゃんと考えるようになってからコピペが増えた」なんて話もちらほら聞きます。 DDDは詳しく知らなかったので、聞きながら実践イメージもわき、非常に興味深かったです。 Laravel8で使える JavaScript パッケージ「Inertia.js」が便利 Laravel8で使える、ビューとのデータのやり取りが容易になる JavaScript パッケージ「Inertia.js」でお手軽にモダンなSPAが構築できるというお話もありました。 軽く紹介があったので、調べて簡単にまとめてみました。 Inertia.jsとはLaravel8の標準認証ライブラリ「Jetstream」で使われている、フロントエンドとバックエンドのデータ連携技術 Vueファイルとのデータ連携がテンプレートエンジンと同じように扱えるため、SPA化も容易 Vue.jsなどでSPAを実現するには、 Ajax の制御やVue側でルーティングを行う必要があり、開発コストがかさみやすいですが、それが不要になります。 Laravelのルーティングの記述で、 Ajax 通信・ルーティングも一緒にコン トロール できるので楽にSPAを実現できるのが魅力的ですね。 TDD視点から見るRequestクラスの依存性 Requestクラスにはユーザー認証や情報の保持、バリデーションなど、色々な情報がありすぎて、 ユニットテスト が書きづらい バリデーションと認証が共存しているなど、テストクラスの文脈がぶれることがあるので、何をしているテストかわからない。何をテストすればいいかわかりにくいという内容で、そこから転じて 「なんでもやってるクラスはテストがつらい。」 この心の叫び、エンジニアあるあるではないでしょうか? 設計や実装時にはそう思われないクラスづくりが大切だと改めて考えさせられました。 まとめ 色々気づきや発見のある有意義な時間でした。 個人的にはDDDの概念が理解できたことが大きな収穫でした。 ドメイン 駆動はいわば「本質を見失わない開発」ということだったのですね。 また参加してみたいと思います。
はじめに こんにちは。itoken1013です! 度々お送りしています超入門シリーズ、今回ご紹介するのは Bootstrapの使い方 です! Bootstrapを利用することで、簡単にページデザインを仕上げることができます。 HTML/ CSS は分かるけどBootstrapには触れたことのない方、今まで体系的には理解せずにBootstrapを利用していた方にオススメの内容です。 それでは解説していきたいと思います! はじめに Bootstrapとは まず、フロントエンドとは? では、Bootstrapとは? Bootstrapを使うことによるメリット レスポンシブWebデザインに対応している 導入のしやすさ、汎用性 コンポーネントが多数用意されている Bootstrapのセットアップ グリッドシステム よく使うコンポーネント フォーム ボタン テーブル 画像 おわりに   Bootstrapとは まず、フロントエンドとは? Bootstrapはフロントエンドの開発で使うための フレームワーク ですが、まずはフロントエンドが何かを説明します。 (厳密な定義からは逸脱しますが)今回のご説明の範囲では、フロントエンドとは HTML、 CSS 、 JavaScript を使って開発するブラウザ上のUI(ユーザ・インタフェース)部分 と解釈いただければと思います。 ユーザが見ることができ、操作を行うことでシステムに命令を与えるための領域、とも言うことができます。 フロントエンドの開発で必要な技術要素は多岐に渡りますが、より詳細な情報については当社のエンジニアが書いた以下の記事を読むとご理解いただけるかと思います。 tech-blog.rakus.co.jp では、Bootstrapとは? それではBootstrapのご説明ですが、Bootstrapは フロントエンドの開発で利用する CSS フレームワーク に位置付けられます。 CSS は フレームワーク を利用せずとも自前のコーディングで装飾を施すことができますが、Bootstrapをはじめとした フレームワーク を導入することで効率的に CSS を仕上げることが可能です。 特にBootstrapは後述の通り、HTMLの各要素へ規定のクラス名を指定するだけでデザインを実現できるなど、 フレームワーク を利用しない場合と比べて圧倒的に早くデザインを仕上げることができてしまいます。 また フレームワーク であるため、一定のルールをもってコーディングできる点はチーム開発において有効であると考えることができます。 Bootstrapはもともと Twitter 社が開発し、2021年2月時点ではバージョン5.0.0が最新版となっています。 いまや世に CSS フレームワーク は数多く存在しますが、Bootstrapはその先駆けとなる フレームワーク でした。 getbootstrap.jp Bootstrapを使うことによるメリット 上記でBootstrapを使うメリットに触れましたが、より詳細に特徴3点を説明していきます。 レスポンシブWebデザインに対応している 多くの方がBootstrapを使う最大のメリットとして挙げるのが、レスポンシブWebデザインに対応している点です。 レスポンシブWebデザインとはPC、 タブレット 、 スマホ 等のデ バイス で異なる画面サイズにおいて、最適なレイアウトデザインへ切り替える手法です。 Bootstrapでは関単にレスポンシブWebデザインに対応したスタイル指定を行うことができ、デ バイス ごとに異なるHTMLを用意する手間を省くことができます。 導入のしやすさ、汎用性 Bootstrapの導入手順は後述しますが、とても簡単です。 また構築するプロダクトの規模や種類を問わずに利用できる汎用性があります。 このように手軽にデザインを反映できる点は大きなメリットと言えるでしょう。 コンポーネント が多数用意されている Bootstrapではデザイン性に優れた各 コンポーネント (ボタンやフォームなど)が提供されています。 さらにこれらの コンポーネント を利用するための手順は、各HTML要素に指定されたclassを追記するだけで実現できます。 非デザイナーのエンジニアでも、簡単な手順で一定レベルのデザインを実現できます。 以降では、定番となる コンポーネント を紹介したいと思います。 Bootstrapのセットアップ それではここから簡単な使い方を紹介していきます。 まずはBootstrapを使える状態とするため、セットアップを行いましょう。 ※今回は CDN (コンテンツ・デリバリー・ネットワーク)を使わず、Bootstrapをダウンロードして利用できる状態にしていきます。 まずは公式ページにアクセスし、Bootstrapをダウンロードしてください。 getbootstrap.jp 上記ページの「Compiled CSS and JS」配下のダウンロードボタンをクリックすると、Bootstrapのコード一式のダウンロードが開始されます。 ダウンロード完了後、Zipファイルを解凍すると css フォルダとjsフォルダが表示されるはずです。 今回はこの2フォルダを任意のフォルダ配下にコピーし、同列にindex.htmlを作成します。 <!DOCTYPE html> < html lang = "ja" > < head > < meta charset = "UTF-8" > < meta name = "viewport" content = "width=device-width, initial-scale=1.0" > < title > Rakus </ title > < link href = "css/bootstrap.min.css" rel = "stylesheet" > </ head > < body > < h1 > Hello, Rakus! </ h1 > < script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js" ></ script > < script src = "js/bootstrap.min.js" ></ script > </ body > </ html > 上記index.htmlではダウンロードしてきた「bootstrap.min. css 」および「bootstrap.min.js」を読み込んでいる点をご確認ください。 またBootstrapでは jQuery を読み込む必要があり、「bootstrap.min.js」よりも前に「 jquery .min.js」を指定しています。 ファイルの作成が完了しましたら、ブラウザで確認してみましょう。 開発者コンソールも開き( Windows であればF12、 Mac であればCommand +Option + I )、特にエラーが表示されていなければセットアップ完了です。 グリッドシステム では実際にコーディングをしながら、Bootstrapの使い方を説明してまいります。 まずはBootstrapを使う上で重要な グリッドシステム からです。 グリッドシステムは先述したレスポンシブWebデザインを実現するために必要な仕組みであり、横幅を 12分割 してHTML要素を配置していきます。 HTML要素にはグリッド(格子)の数を指定していくことで、横幅を指定することができます。 コーディングを行うにあたっては、以下の4つの基本ルールに従う必要があります。 ① divタグを配置し、class=”container” または ”container-fluid”を指定する ② 1の中にdivタグを配置し、class=”row”を指定する ③ 2の中に要素を配置し(複数) 、class=”col-{prefix}-{columns}”を指定する ④ 3で配置した複数要素の{columns}を合計12とする 上記のルールに従ってindex.htmlを修正してみましょう。 今回は1行を4分割して要素を表示してみます。 <!DOCTYPE html> < html lang = "ja" > < head > < meta charset = "UTF-8" > < meta name = "viewport" content = "width=device-width, initial-scale=1.0" > < title > Rakus </ title > < link href = "css/bootstrap.min.css" rel = "stylesheet" > </ head > < body > < header > ヘッダーです </ header > < div class = "container-fluid" > < div class = "row" > < div class = "col-md-2 border border-dark" > 2 </ div > < div class = "col-md-2 border border-dark" > 2 </ div > < div class = "col-md-2 border border-dark" > 2 </ div > < div class = "col-md-6 border border-dark" > 6 </ div > </ div > </ div > < footer > フッターです </ footer > < script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js" ></ script > < script src = "js/bootstrap.min.js" ></ script > </ body > </ html > 上記をブラウザで表示すると、指定したグリッドの個数分、行が分割されていることが確認できます。 ちなみにルール③における class=”col-{prefix}-{columns}” の prefix ですが、上記では「md」としています。 ここでコードを少し書き換え、「col-md-〇」の隣に「col- sm -〇」を追記してみます。 <!DOCTYPE html> < html lang = "ja" > < head > < meta charset = "UTF-8" > < meta name = "viewport" content = "width=device-width, initial-scale=1.0" > < title > Rakus </ title > < link href = "css/bootstrap.min.css" rel = "stylesheet" > </ head > < body > < header > ヘッダーです </ header > < div class = "container-fluid" > < div class = "row" > < div class = "col-md-2 col-sm-6 border border-dark" > 2 </ div > < div class = "col-md-2 col-sm-2 border border-dark" > 2 </ div > < div class = "col-md-2 col-sm-2 border border-dark" > 2 </ div > < div class = "col-md-6 col-sm-2 border border-dark" > 6 </ div > </ div > </ div > < script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js" ></ script > < script src = "js/bootstrap.min.js" ></ script > </ body > </ html > 次に画面を表示し、画面サイズを小さくしてみましょう。 分割された4要素の比率が変わるタイミングがあるはずです。 このようにBootstrapでは 画面サイズごとにprefixを指定でき 、レスポンシブWebデザインを実現しています。 この画面サイズの境界を ブレークポイント と呼び、最新のv5.0.0では ブレークポイント を区切りに以下6種類のprefixを利用できます。 デ バイス 画面サイズ prefix スマホ 576px以下 xs (eXtra Small) タブレット 576px以上 ~ 768px未満 sm (SMall) PC(小) 768px以上 ~ 992px未満 md (MidDle) PC(中) 992px以上 ~ 1200px未満 lg (LarGe) PC(大) 1200px以上 ~ 1400px未満 xl (eXtra Large) PC(特大) 1400px以上 xxl (eXtra eXtra Large) 以上がグリッドシステムの基本となります。 Bootstrapを利用していく上でこのグリッドシステムへの理解は重要となりますので、ぜひ以下の公式ページもご確認ください。 getbootstrap.jp よく使う コンポーネント 上記「Bootstrapを使うことによるメリット」欄にて、Bootstrapには高いデザイン性の コンポーネント が用意されている点に触れました。 Bootstrapでは各HTML要素のclassに決められたクラス名を指定することで、 CSS を実装せずに簡単にデザインを適用することができます。 以降ではこれらの コンポーネント でもよく利用するであろうものについて、サンプルを紹介していきます。 フォーム まずはフォームです。とても簡単です。 formタグ内に以下2つのclassを指定していくことで、簡単にデザイン済のフォームを作成できます。 .form-group:formタグ内に用意するdivタグで指定し、フォーム要素のグルーピングを行います。 .form-control:inputタグなどの各フォーム要素に指定します。 サンプル画面、コードはこちらです。(コードはBody要素のみを記述します) < body > < div class = "container-fluid" > < form > < div class = "form-group" > < label > Email </ label > < input type = "email" class = "form-control" placeholder = "Email" > </ div > < div class = "form-group" > < label > Password </ label > < input type = "password" class = "form-control" placeholder = "Password" > </ div > < button type = "submit" class = "btn btn-primary" > Button </ button > </ form > </ div > < script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js" ></ script > < script src = "js/bootstrap.min.js" ></ script > </ body > ボタン 次はボタンです。ボタンは用途に応じ、"btn btn-XXXX"という形式でクラス名を指定します。 公式ページで紹介されているクラスを載せたコードを示します。 getbootstrap.jp < body > < div class = "container-fluid" > < form > < div class = "form-group" > < label > Email </ label > < input type = "email" class = "form-control" placeholder = "Email" > </ div > < div class = "form-group" > < label > Password </ label > < input type = "password" class = "form-control" placeholder = "Password" > </ div > < button type = "button" class = "btn btn-primary" > Primary </ button > < button type = "button" class = "btn btn-secondary" > Secondary </ button > < button type = "button" class = "btn btn-success" > Success </ button > < button type = "button" class = "btn btn-danger" > Danger </ button > < button type = "button" class = "btn btn-warning" > Warning </ button > < button type = "button" class = "btn btn-info" > Info </ button > < button type = "button" class = "btn btn-light" > Light </ button > < button type = "button" class = "btn btn-dark" > Dark </ button > < button type = "button" class = "btn btn-link" > Link </ button > </ form > </ div > < script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js" ></ script > < script src = "js/bootstrap.min.js" ></ script > </ body > ボタンについては上記用途別のクラス指定の他、背景色の透過やサイズ変更を実施できます。 詳細は上記公式ページのリファレンスをご確認ください。 テーブル テーブルへの指定方法もとても簡単です。 対象となるtableタグのclassに対して"table"を指定の上、デザインに応じて追加のクラス名を指定するだけです。 よく使われるクラス名を示します。 .table-bordered:テーブルセルに枠線をつける .table-striped:テーブル内の1行ずつ交互に色を変える .table-hover:カーソルの乗っている行をハイライト表示する .table-responsive:レスポンシブテーブルとし、水平方向にスクロールさせる 以下では個人的によく使う".table-striped"を指定したテーブルをサンプルに示します。 < body > < table class = "table table-striped" > < thead > < tr > < th scope = "col" > # </ th > < th scope = "col" > イベント名 </ th > < th scope = "col" > 開催日 </ th > </ tr > </ thead > < tbody > < tr > < th scope = "row" > 1 </ th > < td > UI/UXデザイナーLT会 - vol.2 </ td > < td > 3/3 </ td > </ tr > < tr > < th scope = "row" > 2 </ th > < td > フロントエンドTechCafe </ td > < td > 3/10 </ td > </ tr > < tr > < th scope = "row" > 3 </ th > < td > エディタ好きは語りたいLT会 </ td > < td > 3/17 </ td > </ tr > < tr > < th scope = "row" > 4 </ th > < td > PdM Tips LT会 </ td > < td > 3/18 </ td > </ tr > < tr > < th scope = "row" > 5 </ th > < td > おすすめの技術書LT会 </ td > < td > 3/24 </ td > </ tr > </ tbody > </ table > < script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js" ></ script > < script src = "js/bootstrap.min.js" ></ script > </ body > 画像 最後は画像です。画像の加工ももちろん CSS を編集して対応できますが、Bootstrapで指定のクラス名を付与することでとても簡単に実現できます。 対象となるimgタグに対して指定するクラス名のうち、よく使われるものを示します。 .img-responsive:画面サイズに応じてレスポンシブに画像サイズを変更する .img-thumbnail:画像の枠線に丸みを持たせ、サムネイル状に表示する .img-circle:画像をサークル形に加工して表示する .rounded float-left(right):画像の表示位置を左(右)に指定する。 サンプルは"img-thumbnail"です。サムネイルの枠線が判別しやすいよう、背景色も変更しております。 <!DOCTYPE html> < html lang = "ja" > < head > < meta charset = "UTF-8" > < meta name = "viewport" content = "width=device-width, initial-scale=1.0" > < title > Rakus </ title > < link href = "css/bootstrap.min.css" rel = "stylesheet" > </ head > < body > < div class = "text-center" style = "background-color: black;" > < img src = "image/img-sample.png" class = "img-thumbnail rounded" > </ div > < script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js" ></ script > < script src = "js/bootstrap.min.js" ></ script > </ body > </ html > おわりに 今回は超入門的なBootstrapの使い方を紹介しましたが、ご理解いただけましたでしょうか? Bootstrapは歴史の長い CSS フレームワーク ながら、今なお進化しております。 基本を理解すれば今後のバージョンアップにも追随していけるかと思いますので、ぜひこのブログをスタートラインとし、Bootstrapの便利機能の数々に触れていっていただけますと幸いです! ではでは!   エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 https://rakus.hubspotpagebuilder.com/visit_engineer/ rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
株式会社ラクス でエンジニア リングマ ネージャをしている 間澤 です。 私達の組織では、ここ数年で管理職間やリーダー間でマネジメントやリーダーシップについてちょっとした勉強会をしています。 エンジニアは日頃そのテーマの学習の機会に触れるきっかけが少ないのかな、と感じていたのが始めたきっかけです。 開発をしていると技術のインプットだけでも大変ですよね。 そこで、私達が勉強会で本を読み合わせたうえで、議論や意見交換してみて良かったなと思う10冊をご紹介します。 先に言ってしまいますと殆どが技術本ではないです。エンジニアではない方にも有益だと思います。 単に本を読んだだけではあまり効果がないので、それを実際にやってみると人生がより良く変わっていきます。 仕事の中で、 「それ、本に書いてあったことができてるね。」 を言い合えることがポイントです。 1. 組織論:失敗の本質 2. リーダーシップ:マキアヴェッリ語録 3.問題解決:問題解決 4.論理思考力:ロジカル・プレゼンテーション 5.行動様式(自己啓発):人を動かす 6.心理学:嫌われる勇気 7.組織経営ポリシー:プロフェッショナルマネージャー 8.マネジメント:マネジメント(ドラッカー) 9.経営組織論:組織行動のマネジメント 10.プロダクトマネジメント:Inspired 1. 組織論:失敗の本質 一昔も二昔も前から著名なビジネス本です。 主に第二章を中心に旧日本型組織の陥りやすい弱点を理解します。 「目的が曖昧」であることが失敗を招きます。 「よかれ」や「雰囲気」で進めていくと簡単にあまり良くない状況に陥ります。 論理に基づいてタスクを進めているかが重要になります。 キーワード 戦略上の失敗:曖昧さ あいまいな戦略目的、短期思考、主観的で 帰納 的な戦略策定、アンバランスな技術体系 組織上の失敗:柔軟さの欠如 人的ネットワーク偏重、属人的な組織、学習の軽視、プロセスや動機を重視した評価 2. リーダーシップ: マキアヴェッリ 語録 勘違いされている方もいるかもしれませんが、強権な暴君の話ではありません。 過去の君主たちの実績が書かれた、必要な統率力の考え方とは何か、が書かれています。 戦える組織を作る。 軍隊(エンジニア)と法律(ルール)を整える。 良い法律とよい軍隊を持っていれば国は安定する。 このふたつこそが、国を保つための根幹である。 キーワード 必要な資質 変化への対応力、よからぬ者になりうる技、悪評から逃れるすべ、ケチであること、慈悲深さと冷酷さ、外見上は資質があるふりをする、気前の良さ 戦える組織をつくる 自分の軍を持つ、決断はひとりでする、有能な側近あるところに有能な君主あり、有能な側近に常に助言を求める、常に 武装 する 3.問題解決:問題解決 正しく問題を解決するプロセスを学びます。この本はすべてが重要なのですべてきちんと吸収したいです。 問題解決プロセス 現状把握(where)→課題抽出/特定(why)→あるべき姿(what)→対策立案(how)→モニタリング(KPI設定) 現状把握は非常に重要でここが誤っていたり、浅いと後続の各項目が矛盾したり、唐突だったりグダグダになります。 開発でいうと要求分析にあたるようなものなので全体の半分近くの力をここに注ぐのが望ましいです。 特に数値情報は説得力があり最後のKPIにも描きやすいです。 4.論理思考力:ロジカル・プレゼンテーション 前述の『問題解決』と同じ著者の方です。 ビジネスパーソン が価値の高い仕事を遂行していく上で必須となる能力が書かれています。 論理思考力:話をつなぐスキル 仮説検証力:疑問に答えるステップ 会議設計力:議論をまとめるスキル 資料作成力:紙に落とすステップ 5.行動様式( 自己啓発 ):人を動かす 言わずもがなの古典の名著。 目次に示された行動に対して自己診断の◯×をつけて、みんなで評価し合うと楽しいです。 もし、できていない項目があれば、それができている人を見つけて真似するだけで良くなっていきます。 6.心理学:嫌われる勇気 タイトルがキャッチーですが、嫌われるわけではないです。 正しく「共同体へ貢献」する考え方とは何かを理解できる本です。 他人を変えるための心理学ではなく、自分が変わるための心理学です。 自分を認めてあげると気持ちが楽になります。 キーワード 解決策は課題の分離 対人関係のゴールは「共同体感覚」 叱っても褒めてもいけない 「勇気づけ」と「感謝」 自己受容/他者信頼/他者貢献 7.組織経営ポリシー:プロフェッショナルマネージャー 高い視点の持ち方、視点をどこに置くべきか(経営の秘訣)、マネジメントとリーダーシップの違いなどが書かれています。 あなたのリーダーシップはどのようにして獲得できるか?高められるか?知りたい方は答えが書いてあります。 本を読む時は、初めから終わりへと読む ビジネスの経営はそれとは逆だ 終わりから始めて、そこへ到達するためにできる限りのことをする  - 自分は何をやりたいのかをしっかり見定め、それをやり始めよ。 すみません、10冊といいながらこのテーマについてはもう1冊紹介させてください。 HIGH OUTPUT MANAGEMENT マネージャーのアウトプットとは、     「自分の組織のアウトプット+自分の影響力が及ぶ隣接組織のアウトプット」 マネージャーは「テコ作用」を活用すべき。 マネージャーというテコをチームに入れることで、チームのパワーを何倍にもする点をなる。 マネージャーはテコを探し、作る。 8.マネジメント:マネジメント( ドラッカー ) こちらも誰もが知る名著。ただし、読むのは少し難しいです。 別冊にはなりますが、『実践する ドラッカー 【思考編】』と『実践する ドラッカー 【行動編】』だけでも 良質なピックアップがされていて読みやすいです。 主な論点は、貢献、強み、集中、時間管理、意思決定、目標管理、計画、です。 一番のおすすめは「強み」です。 『なすべきは自らが持っていないものではなく、  自らが持っているものを使って成果を上げることである。』 強みとは、個々人が持っている資質を磨いたものである。 自分を最高に生かす方法は、できること、強み、に集中することである。 そして、強みを生かす3ステップ  1.明らかになった強みに集中する事  2.その強みをさらに伸ばす事  3.無知の元凶ともいうべき知的な傲慢(もうこれで十分という気持ち)を正す事 9.経営組織論:組織行動のマネジメント こちらの本は重厚です。何回かに分けて、みんなで読んでいきました。 経営組織論に初めて触れる方は、なぜ経営理念があるのか、既にある人事制度や目標管理は論理に基づいている、組織文化を大事にする理由、などがわかります。 例えば、復数の管理職でこの本を読んだ際に、管理職の特性により以下の組織特性がありました。 グループシンク 安全志向重視が強い。→それが過度にならないようにどうするか注意が必要。 楽観的すぎる。→特定の人頼りになっていて管理も任せすぎた。 組織は、一時的に信頼が損なわれても説明でき、納得すれば関係を継続できる特徴があるので、早めの気づきからの説明と修正が重要になります。 また、 コンフリクト についても一概に悪いものと思い込んでいる点がありました。 ですが、調和的で平穏で協力的な集団は停滞しがちで変化や改革の必要性に対して無関心かつ鈍感になりやすいというものになります。 対策は、集団のリーダーに対して、集団を活性化し、 自己批判 的、創造的にするのに必要な最小限のコンフリクトを常に維持するよう促すのが大事と書かれていました。 10. プロダクトマネジメント :Inspired 最後に、急にエンジニアリングに戻ります。 製品やサービスに必要な役割と責務が書かれています。 プロダクトマネージャーの役割 製品の市場性を評価することと、開発すべき製品を定義することである。正しいもの(製品)は何かを定義する。(What) ユーザーエクス ペリエ ンスデザイナーの役割 製品が対象とするユーザー像(ペルソナ)を深く理解した上で、ユーザーのニーズに合うように要求仕様とデザインの調和を図ろうとする。 プロジェクトマネジメントの役割 製品が定義されれば、製品開発チームがプロジェクトを引き継ぎ、製品の開発に取りかかる。プロジェクトのスケジュールや工程・進捗の管理。正しくもの(製品)を作る。(How) エンジニアリングの役割 製品開発やソフトウェア開発(者)ともいうが、彼らは実際に製品を開発する人たちである。 サイト(システム)運用の役割 ウェブサイトを運用するチームは、ウェブ上のサービスを常時稼働させる任務を負っている。 プロダクト マーケティング の役割 製品を世界中に知らしめること、製品を対外的に発表すること、販売チャネルで製品を売り込むためのツールを提供すること、主要な マーケティング 活動を指揮することである。 以上、どの書籍も大変身になるものばかりでした。大事なのは読むだけではなく「やってみること」だと思います。 最後に、宣伝を失礼します。 株式会社ラクス では、このように人やプロセスを大事にして、正しく製品やサービスを作っております。 ご興味がありましたら是非お声がけください。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
こんにちは、株式会社 ラク スで楽楽勤怠の開発を行なっている goldminer です。 「楽楽勤怠」は昨年にリリースしたばかりの クラウド 型の勤怠管理システムです。 ラク スのサービスは BtoB のサービスが多く、勤怠管理システムも基本的にはバックオフィス業務をサポートするためのシステムです。 バックオフィス業務であれば(サービスの停止を伴う)メンテナンス時間を営業時間外となることが多い深夜時間帯にすれば影響が出にくいのですが、勤怠管理システムには打刻機能があり、これは次のような性質を持っています。 打刻には(いつ打刻したのかという)客観性が必要だが、打刻できずに従業員の自己申告に基づいて後から入力したものは客観性が低い 従業員の勤務時間帯は多様であり、深夜時間帯に行われる打刻も一定数ある このことから、楽楽勤怠では無停止リリースの重要性が高いです。直近のバージョンアップでたまたま無停止リリースを実施できる条件を満たしているものがありましたので、実際に無停止リリースのための開発を行ってみました。 今回の目的 無停止リリースの手順 無停止リリースに向けたアプリケーションの開発 DB変更パッチの作成 COLUMN の追加に関する注意点 TABLE の追加に関する注意点 アプリケーションの実装 COLUMN の追加に関する注意点 TABLE の追加に関する注意点 テスト 次回バージョンアップでの課題 DB変更パッチの作成 アプリケーションの実装 まとめ 今後の予定 今回の目的 無停止リリースについては弊社のかみせんプロジェクトでも検証しています。 同じ ラク ス エンジニアブログに 記事 があるので参考になさってください。 上記の記事では次の3つの要件があげられています。 セッション管理 アプリケーション構成 DB運用 この内、「セッション管理」「アプリケーション構成」は前に担当していたサービスでも対応済だったこともあり ナチュラ ルに対応しています。 つまり、DB変更がないリリースについてはすでに無停止リリースを達成しています。 今回は「DB運用」の検証で且つ 完全無停止 を目的としており、リリース中の更新リク エス トを制限しません。 「DB変更リリースを完全無停止で行う」ために何が必要であり、開発にどのような影響がでるのかを検証してみました。 無停止リリースの手順 DB変更リリースをサービスを停止して行う場合の手順は次のとおりです。 APサーバー1と2を停止する APサーバー1と2のアプリケーションを更新する DB変更パッチを適用する APサーバー1と2を再開する 無停止リリースの手順は次のとおりです。 DB変更パッチを適用する APサーバー1への振り分けを停止する APサーバー1のアプリケーションを更新する APサーバー1への振り分けを再開する APサーバー2への振り分けを停止する APサーバー2のアプリケーションを更新する APサーバー2への振り分けを再開する 手順の 2 から 7 まではDB変更がない場合の無停止リリースとまったく同じ手順です。 この手順の場合、アプリケーションとDBの組み合わせには次の3つがあります。 古いバージョンのアプリケーションと古いバージョンのDB 古いバージョンのアプリケーションと新しいバージョンのDB 新しいバージョンのアプリケーションと新しいバージョンのDB 1番目と3番目は当たり前のことですので、2番目の「古いバージョンのアプリケーションと新しいバージョンのDBで正常に動作する」ことが特徴的な要件です *1 。 無停止リリースに向けたアプリケーションの開発 DB変更パッチの作成 先に結論を言ってしまうと、DB変更パッチが以下だけの場合に限り完全無停止で行うことができます。 COLUMN の追加( ALTER TABLE ADD COLUMN ) TABLE の作成( CREATE TABLE ) 単純にデータ種別が増えて追加する場合に限る、既存の TABLE を分割するような場合は不可 大抵のORマッパーは追加された TABLE と COLUMN は無視しますので、特に何もしなくても 「古いバージョンのアプリケーションと新しいバージョンのDBで正常に動作する」を達成することができます。 それ以外の UPDATE や INSERT ~ SELECT などは、レコード数が多いと負荷が高くなったり容量が急に増えたりする可能性がありますので、運用しながらの実行はするべきではないと考えます。 COLUMN の追加に関する注意点 追加した COLUMN に初期値は設定せず、null のままにします OK 例 ALTER TABLE table_a ADD COLUMN col1 boolean ; NG 例 ALTER TABLE table_a ADD COLUMN col1 boolean ; UPDATE table_a SET col1 = true ; ALTER TABLE table_a ALTER COLUMN col1 SET NOT NULL ; NG 例は UPDATE を実行している点がよろしくありません。 UPDATE ではなく DEFAULT を使って初期値を設定するのも同様です。 今回は検証していませんが、全体設定のようなデータを保持する UPDATE ONLY な TABLE であれば レコード数が少なく、影響が把握しやすいので UPDATE も可能と考えています。 追加した COLUMN の INDEX は作成しません UPDATE と同じく、レコード数が多いと負荷が高くなったり容量が急に増えたりする可能性がありますので、運用しながらの作成はするべきではないと考えます。 やはりレコード数が少なければ作成しても問題ないですが、レコード数が少ないのであればそもそも INDEX を作る必要性が低いので、作成するという選択肢はないと考えています。 TABLE の追加に関する注意点 今回の検証では特に注意する点はありませんでした。 初期レコードを INSERT するかどうかについては次のように考えています。 基本は INSERT しない サンプルレコードや UPDATE ONLY な TABLE のレコードであれば、レコード数が少なく影響が把握しやすいので INSERT も可能 今回の検証では INSERT していません。 INDEX の作成はレコードがない、または数が少ないので問題はないと考えています。 プライマリーキーやユニークキー制約により自動的に作成される INDEX も同様です。 アプリケーションの実装 COLUMN の追加に関する注意点 上述したように追加した直後の COLUMN は null になっています。 これに対応する必要があります。 次のような実装でDBから取得した値が null だった場合に初期値に置換します。 Entity entity = /* DBから取得する処理 */ ; if (entity.col1 == null ) { entity.col1 = true ; } この置換処理は 、DataAccessObject(DAO) または Repository のどちらかで実行することになるでしょう。 そうすることで、それ以外の箇所では値が null である可能性を除外して実装することができます。 追加した COLUMN を抽出時の条件に使用する場合は 、null である可能性を考慮します。 Entity findByCol1() { // ↓「col1 IS NULL」を条件に付与している. String sql = "SELECT * FROM table_a WHERE col1 = true OR col1 IS NULL" ; } 追加した COLUMN でソートする場合、NULLS FIRST / NULLS LAST を指定する必要があります。 今回は検証した中にこのケースがなかったため実際にはやっていません。 TABLE の追加に関する注意点 今回の検証では初期レコードを INSERT しておらず、TABLE の中身が空なのは正常な状態のため特に注意する点はありませんでした。 テスト 無停止リリースに固有のものとして次のテストを行いました。 Apache JMeter を使って常時アクセスがある状況を作り、その中でDB変更パッチを実行するテスト 以下の観点で確認 DB変更パッチが正常終了するか Apache JMeter によるアクセスがすべて正常応答するか(エラー応答がないか、 応答時間 が正常な範囲内かどうか) 「古いバージョンのアプリケーションと新しいバージョンのDB」の組み合わせで機能テスト テスト結果はいずれも問題ありませんでした。 1 のテストは ミドルウェア やインフラ構成に大きな変更がない限りは、初回のみの実施でよく、毎バージョンアップで実施する必要はないと考えています。 次回バージョンアップでの課題 ここまでの内容で無停止リリースを実施することができます。 しかし、いくつかの課題を先送りにしており、次回以降のバージョンアップで対応する必要があります。 この対応はサービスを停止して行います。 DB変更パッチの作成 追加した COLUMN は null になっていますので、改めて初期値に更新します *2 。 緊急性は高くありませんが、今後の開発でノイズにならないために早めに対応しておくべきだと考えています。 UPDATE table_a SET col1 = true WHERE col1 IS NULL ; ALTER TABLE table_a ALTER COLUMN col1 SET NOT NULL ; INDEX の作成を見送っていた場合は INDEX も作成します。 アプリケーションの実装 null である可能性を考慮した実装がありますが、null がありえなくなりますので 本来あるべき実装にします。 Entity entity = /* DBから取得する処理 */ ; // 後処理は必要なし. Entity findByCol1() { String sql = "SELECT * FROM table_a WHERE col1 = true" ; } まとめ 今回の検証結果を踏まえての結論は次の通りです。 「DB変更リリースを完全無停止で行う」こと自体は条件が整えば可能 しかし、 工数 や 心理的 負担の増加を考えるとペイしない 次のような作業が必要になり、 工数 が増加します。 ★無停止リリースの手順を作成する 追加した COLUMN が null だった場合を考慮した実装を行う ★常時アクセスがある状況でのリリースのテストを行う 「古いバージョンのアプリケーションと新しいバージョンのDB」の組み合わせで機能テストを行う 追加した COLUMN の null を初期値に更新するDB変更パッチを作成する@次回バージョンアップ 追加した COLUMN が null だった場合を考慮した実装を本来あるべき実装に変更する@次回バージョンアップ 上記で★を付けたものは初回のみの実施でよく、毎バージョンアップで実施する必要はないと考えているものです。 ★が付いていないものが毎バージョンアップで 工数 が増加する原因になるもので、 工数 としてはざっくり1、2人日程度です。 工数 は飛び抜けて大きなものではありませんが、次回バージョンアップでの対応が発生することによる 心理的 負担の増加が嫌だなと、感じました。 効果の方はと言いますと、そもそもDB変更パッチが COLUMN と TABLE の追加のみの場合に限られるという問題があります。 さらに今後の予定に書いているように分散システム化することで打刻の無停止が達成できると、効果は「リリース担当エンジニアが深夜作業をしなくてよい」だけになってしまいます。 ビジネスサイドでの無停止リリースの要求が強くなるか開発の負担を減らすことができないと再チャレンジは難しいという所感です。 今後の予定 ビジネスサイドから無停止リリースの要求が出てきた際に応えられるようにと考えて実施した今回の検証ですが、毎バージョンアップで頑張ってDB変更パッチの作成と実装を行わなければならないのは継続性に難があると感じました。 今後の計画に無停止リリースは織り込まず、突発的に無停止リリースの必要が生じた場合に今回の知見を活かせればよいと考えています。 可用性の向上の観点ではシステム全体の完全無停止にはこだわらず、一度仕組みを作ってしまえば以降は再利用するだけでよくなる次のような方針で進めるべきだと考えています。 分散システムにして重要な機能は常時稼働できるようにする 勤怠管理システムでは打刻機能が該当 更新リク エス トのみ制限して参照リク エス トは行えるようにする 停止はするが停止時間が極力短くなるようにする *1 : DB変更パッチの適用とアプリケーションの更新の順序を入れ替えれば「新しいバージョンのアプリケーションと古いバージョンのDB」の組み合わせになります。 詳細は割愛しますが、この組み合わせで正常に動作させることは難易度が高く現実的ではありません。 例外的にDB変更が「 DROP COULMN」のみの場合は容易に達成できますが、「 DROP COULMN」に緊急性がある場合は少なく無停止リリースで行うメリットはないと思われます。 *2 : 新しいバージョンのアプリケーションで INSERT, UPDATE したレコードでは null ではありません。
今回は API について解説します。エンジニア/ プログラマ の方はよく聞く単語だと思いますが、 私自身、他の人にうまく説明できるかと考えた時にあまり自信がなかったのでまとめてみることにしました。 APIとは APIを使うメリット 開発コストの削減 開発の効率化 セキュリティの向上 APIの種類 実践 作ったもの 使用するAPI ぐるなびAPI LINE Messaging API 構成 作成手順 ぐるなびAPI登録 LINEBOT登録 Node.jsなどの環境構築 実装 おわりに API とは API は「 Application Programming Interface 」の略で、ざっくりいうとあるプログラムから別のソフトウェアを操作するための仕組みのことです。 企業などがアプリケーションの一部の機能を外部に向けて公開することで、第 三者 は開発したアプリで機能を利用することができます。 API を使うメリット 開発コストの削減 基本的にWeb API は API 自体の仕様が変更になる以外に、バグ修正等の運用コストも必要ありません。また、Web API は無料で公開されているものが多いので、開発時間の削減も可能です。 開発の効率化 アプリケーション開発で、ある機能を実装したいとなった時、一部の機能は他社が API として公開している場合があります。 例として、駅情報が必要になった時には既に駅情報を取得できる API が存在していますので、1から機能を実装する必要はありません。 1から作成する場合は、路線データ、地図データ、料金データ、アップデートなどを考慮する必要がありますが、 API を利用することでこれらの考慮が不要となり、効率よく開発を進めることができます。 セキュリティの向上 ログイン機能実装時には、 Facebook や Twitter 、 Google の API を活用することで該当アカウントを利用したログインができます。 大手企業の高いセキュリティ機能を利用することでセキュリティ面の担保ができます。 API の種類 ごく一部ですが、例として以下のようなものがあります。 ・ Twitter :アカウントと利用者や、ツイート、ダイレクトメッセージといった Twitter データの利用ができる ・ Amazon :商品情報、在庫情報、注文情報などを呼び出すことができる ・ Google :画像の分析やテキストの読み取り、手書き文字の読み取り、人や建造物の特定など、画像認識に関するさまざまな機能が使える ・LINE: BOT を作成して、応答メッセージの送受信を行ったりすることができる ・Slack:チャンネルや DM からのメッセージなど、イベントを送信したり、Slack チャンネルとユーザーグループを作成、変更したりできる 実践 作ったもの API を使って飲食店検索 BOT を作成しました。 仕様としては、位置情報を送った際に日本酒のある近くの居酒屋を検索しています。 使用する API ぐるなび API ぐるなび に掲載されている飲食店の基本情報を取得することができますので、飲食店を検索するようなアプリ作成時に使用するといいです。 LINE Messaging API Messaging API を使うことで BOT を作成することができます。ユーザーの反応によって何かしらの処理を行うことができますので、例えばオウム返しなどといったユーザーの送ったメッセージと同じメッセージを返す BOT が簡単に作れたりします。 構成 作成手順 ぐるなび API 登録 まず、アクセスキーを発行するために以下のサイトでアカウントを作成します。 ぐるなび Web Service - トップページ どのような API があるかは以下のサイトで確認できます。 ぐるなび Web Service - トップページ 次に受け取るデータの確認を行うのですが、 ぐるなび API はテストツールが用意されているため簡単にどのようなデータが返ってくるか確認することができます。 方法は、以下のサイトで使用する API 名とパラメータを指定して「クエリを送信ボタン」を押下するだけです。 ぐるなび Web Service - トップページ 今回はヒット件数を制限するhit_per_pageと、フリーワード検索を行うfreewordを指定しています。 画像の下部に JSON 形式でデータが返ってきていることが分かりますね。こちらからどのようなデータが返ってきているか確認します。 アプリに組み込むときは、URLをコピペすればとりあえずは動きます。あとは、必要に応じて検索パラメータを変更するように実装すればOKです。 LINEBOT登録 以下からLINE Developersにログインします。それからプロバイダーを作成して、Messaging API を選択してのチャネルを作成します。 ※LINE Developersへの登録にはLINE個人アカウントが必要になります。 LINE Developers Node.jsなどの環境構築 こちらについて今回は割愛させていただきます。 実装 今回実装したコードは以下となります。 'use strict'; const fetch = require('node-fetch'); const express = require('express'); const line = require('@line/bot-sdk'); var request = require('request'); const PORT = process.env.PORT || 3000; const config = { channelSecret: 'チャネルシークレット', channelAccessToken: 'チャネルアクセストークン' }; const app = express(); app.set('port', (process.env.PORT || 3000)); app.get('/', (req, res) => res.send('Hello LINE BOT!(GET)')); //ブラウザ確認用(無くても問題ない) app.post('/webhook', line.middleware(config), (req, res) => { //console.log(req.body.events); //ここのif分はdeveloper consoleの"接続確認"用なので削除して問題ないです。 if(req.body.events[0].replyToken === '00000000000000000000000000000000' && req.body.events[1].replyToken === 'ffffffffffffffffffffffffffffffff'){ res.send('Hello LINE BOT!(POST)'); console.log('疎通確認用'); return; } Promise .all(req.body.events.map(handleEvent),) .then((result) => res.json(result)); }); const client = new line.Client(config); async function handleEvent(event) { if (event.type !== 'message') { return Promise.resolve(null); } //位置情報が送られた場合 if(event.message.type == 'location') { //検索に必要なパラメータを定義 var query = { "keyid":"アクセスキー", "latitude": event.message.latitude, "longitude": event.message.longitude, "range": 3, "freeword": "日本酒", "hit_per_page": 10, }; //リクエストに必要なオプションを設定 var options = { url: "https://api.gnavi.co.jp/RestSearchAPI/v3/", qs: query, json: true }; } //ぐるなびAPIを叩く request.get(options, function(error, response, body){ if (!error && response.statusCode == 200 || body.rest == undefined) { if('error' in body){ console.log("検索エラー" + JSON.stringify(body)); return client.replyMessage(event.replyToken, { type: 'text', text: '検索結果が0件、または検索エラーです。' //実際に返信の言葉を入れる箇所 }); } } var random = Math.floor(Math.random() * (body.rest.length)); var message = { "type": "flex", "altText": "this is a flex message", "contents": { //中身記載 } }; return client.replyMessage(event.replyToken, message); }); } app.listen(PORT); console.log(`Server running at ${PORT}`); 上記のコードでポイントとなるところのみ解説します。 const config = { channelSecret: 'チャネルシークレット', channelAccessToken: 'チャネルアクセストークン' }; configにはLINE Developersで作成したチャネルの 秘密鍵 とアクセス トーク ンを設定しておきます。 //位置情報が送られた場合 if(event.message.type == 'location') { var query = { "keyid":"アクセスキー", "latitude": event.message.latitude, "longitude": event.message.longitude, "range": 3, "freeword": "日本酒", "hit_per_page": 10, }; Webhookイベントオブジェクトに送信されたメッセージが含まれており、messageプロパティに格納されています。 今回は位置情報が送られた際に処理を行いたいので、event.message.typeがlocationの時に処理します。 ちなみに位置情報が送られた際のメッセージオブジェクトは以下のようになります。 ・ID:メッセージID ・type:location ・title:タイトル ・address:住所 ・latitude:緯度 ・longitude:経度 また、queryには ぐるなび API を叩く際のリク エス トパラメータを設定しています。今回は以下となります。 ・keyId:アクセスキー ・latitude:緯度 ・longitude:経度 ・range:検索範囲 ・freeword:フリーワード検索 ・hit_per_page:検索件数 これで送った位置から半径1km以内の、日本酒のある飲食店を検索することができます。 request.get(options, function(error, response, body){ (中略) var message = { "type": "flex", "altText": "this is a flex message", "contents": { // Flex Message Simulatorで取得したJSONデータ } }; return client.replyMessage(event.replyToken, message); }); 初めはテキストで検索結果を返すようにしていたのですが、少し見た目を良くしたいと思いMessaging API の Flex Messageで返すようにしました。 そのためにtypeを flex としています。 また Flex Message Simulatorを使うことでメッセージを送信しなくてもレイアウトを確認することができます。 Flex Message Simulator 表示される JSON データをコピペして必要に応じて修正し、contentsに設定します。今回は以下のレスポンスデータを使用して表示しています。 ・rest.name:店名 ・rest.url_mobile:携帯サイトURL ・rest.image_url.shop_image1:店の画像 ・rest.address:住所 ・rest.opentime:営業時間 ※店によっては画像が空だったりするので注意が必要です。 おわりに 今回 API を使って飲食店検索 BOT を作ってみましたが、 ぐるなび API はテストツールでレスポンスを確認できるので使いやすさを感じました。 また、LINE Messaging API は送受信が簡単で、レイアウトは Flex Message Simulatorを使うことでわりとすぐ実装ができました。 記事作成時にいろいろな種類の API を見ていましたが使ってみたいものがありましたので、どのように利用するかを考え、また実践してみたいです。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
皆様お初にお目にかかります。楽楽勤怠開発課のy_konnoと申します。2020年7月に入社したあまりフレッシュではない新入りです。 入社してからMQに関して取り扱う機会が多いのですが、 ラク スでMQというとRabbitMQがスタンダードになりつつあります。つい先日(1月22日)、RabbitMQ 3.8.11がリリースされ、なんともタイミングが良いので触れてみようと思います。 ちなみに3.8.9が2020年9月28日のリリースなので、約4ヶ月ぶりのバージョンアップになります。今回は文献のあまり多くないうえにアップデートのあったQuorum Queueについて触れてみます。 Quorum Queue以前のクラスタリング 1.ノード再起動時のミラーメッセージ消失 2.同期によるブロッキング Quorum Queueの特徴 Quorum Queueの概要 Quorum Queueがデータをレプリケーションする仕組み Quorum Queueでのノード障害発生時 Quorum Queueを使う Quorum Queueの制限・注意点 利用できない機能の存在 常にDurableなQueueとして扱われる ディスクI/O ノードの数 レイテンシ おわりに Quorum Queue以前の クラスタリング RabbitMQで クラスタ 構成を組む場合、ExchangeやBindingなどは各ノードへよしなに分散化してくれますが、Queueについては明示的に設定をしなければなにもしてくれません。Queueについての設定をしないまま クラスタ を組んで運用を始めてしまい、マスターノードが死んだ場合、そのままメッセージがロスするという恐ろしい事態が発生します。 バージョン3.8以前ではMirrored QueueがQueueの分散化について用意された唯一の選択肢でした。 Mirrored Queue Mirrored QueueはマスターのQueueでクライアントからのコマンド(Write、ACKなど)を処理し、 ミラーリング されたQueueに対してデータを レプリケーション していきます。もし、マスターが何らかの原因で落ちた場合は、ミラーのいずれかがマスターとしてプロモーションすることでサービスを維持します。 このようにMirrored Queueは クラスタ 内の各ノードにQueueを ミラーリング することで高可用性をもたらす機構ですが、データの一貫性については問題がある設計になっており、状況次第ではデータロスが生じる可能性が高まる危険があります。 1.ノード再起動時のミラーメッセージ消失 Mirrored Queueの1つ目の大きな問題は、あるノードが再起動した場合ミラーにあったデータ内容はすべて消去されるという挙動です。何らかの問題が生じたノードが再起動すると、ミラーにはデータが一切ないため、マスターノードからデータをすべて同期し直す必要があります。 これだけ見ると大して深刻な問題が起きそうにも見えませんが、このマスターからの同期がさらなる問題を引き起こします。 2.同期による ブロッキング 第2の問題はミラーへのデータ同期が ブロッキング で行われる点です。同期中は当該Queueへのメッセージ送受信がすべてブロックされるため、動機が完了するまでそのQueueは一切使えなくなります。 一般にRabbitMQが健全な運用状態であれば、Queueにメッセージが溜まった瞬間にConsumeされることがほとんどです。このため、Queueの状態はごく少数のメッセージが存在するか、もしくは空の状態になっていることがほとんどのはずです。しかし、何らかの問題でConsume側の処理停滞し、Queueに大量のメッセージが滞留した状態で同期による ブロッキング が発生すると、長時間に渡って該当のQueueが利用 不能 になってしまいます。ひどい場合には同期に膨大な時間とノードのリソースを消費した挙げ句に再度ノードがダウンするようなケースもありえます。こうなってしまうと、ミラーの同期を諦めるという選択をせざるを得なくなります。もしミラーの同期をしない場合は、再起動後から蓄積された新規のメッセージについては レプリケーション がされるものの、既存のメッセージについては同期しないため、データロスが発生する可能性が高まります。 MQで扱うメッセージが損失してしまうことが望ましくないシステムでは上記の事象は大きな問題となるでしょう。また、仮にメッセージ損失が許容できるシステムであったとしても、同期による ブロッキング が長時間に及んだ場合は全く影響を受けないわけではありません。 Quorum Queueの特徴 Quorum Queueの概要 Quorum QueueはRabbitMQ 3.8.0から搭載された新機能で、 Raft Consensus Algorithm を利用した高可用性・一貫性を実現するQueueです。特にデータの安全性・一貫性を重視されています。 Quorum Queue Quorum Queueのノードは1つのリーダーと複数のフォロワーから構成されます。このうち、クライアントと実際に対話を行うのはリーダーだけです。フォロワーは 冗長化 のためだけに存在し、万一リーダーが利用 不能 になった場合にはフォロワーの中から新たなリーダーが選出され、サービス全体のダウンを防ぎます。 Quorum Queueがデータを レプリケーション する仕組み Quorum Queueではログ レプリケーション という仕組みで各フォロワーにデータを連携しています。リーダーはクライアントからのコマンドを受け取ると、リーダーノード内のログに一時的にそのコマンドをコミットし、各フォロワーへログを レプリケーション します。この時点では クラスタ 全体として更新は確定していません。フォロワーはログの レプリケーション がなされると、自己のログにコミットを行い、リーダーへ返答を返します。リーダーはフォロワーからの返答の数をカウントし、フォロワーの 過半数 のコミットを以てリーダーもコミットし、 クラスタ 全体での値が一貫して更新されます。 Quorum Queueでのノード障害発生時 Mirrored Queueとは異なり、Quorum Queueではフォロワーノードが再起動しても保持しているデータを破棄しません。データはフォロワーノード上のディスクに書き込まれており、リーダーノードとの差分を レプリケーション でキャッチアップするだけです。 また、 レプリケーション 自体も非同期で行われます。このためMirrored Queueで発生しうるQueueが ブロッキング されてしまう事象ももはや発生しません。 さらに、新規にノードを クラスタ に追加した場合にも非同期で粛々と レプリケーション されるので、Mirrored Queueで発生していた問題は生じません。強いて言えば レプリケーション するデータ量が多い場合にはネットワークI/Oがやや増加する問題があることぐらいでしょうか。 Quorum Queueを使う 能書きが長々としてしまいましたが、実際にQuorum Queueを利用するのは非常に簡単です。クライアントにおいてQueue宣言時にパラメータを追加するだけで作成ができます。 以下は Java Clientでの宣言方法です。 Channel.queueDeclare() の arguments (第5引数)に x-queue-type=quorum を指定して宣言すればQuorum Queueとして作成されます。 Map<String, Object> extraQueueArgs = new HashMap<>(); extraQueueArgs.put( "x-queue-type" , "quorum" ); channel.queueDeclare( "test_queue" , true , false , false , extraQueueArgs); 簡単ですね。 なお、Quorum Queueを作成すると、Management Plugin上では以下の様に表示されます。 Management Console Type が Quorum になっていることが確認できますね。 また、メッセージの送受信については通常通りでよく、特別な処理は必要ありません。つまり、 Channel.basicPublish() や Channel.basicConsume() の内容は通常のQueueやMirrored Queueと何ら変わりません。 Quorum Queueの制限・注意点 ここまでQuorum Queueの利点ばかり述べてきましたが、残念なことにいくつかの欠点が存在します。 利用できない機能の存在 Mirrored Queueに比べて、Quorum Queueはサポートされている機能に制限があります。 以下はその一例です。 DurableではないQueue Exclusive Queue Queueのサイズ制限 drop-head と reject-publish (3.8.10から)のみサポート 公式サイト上では drop-head のみとの記載になっていますが、記述が古いです メッセージごとの永続化 メッセージの TTL メッセージ優先度 グローバル QoS 全く使えないものもあれば、一部のみサポートがされているものがあったりとバラバラな状態ですね。ただ、3.8.10でQueueのサイズ制限に reject-publish が追加されたり、Consumerの優先度がサポートされるようになったりと、今後は徐々にサポートが拡充されていくのかもしれません。 あまりケースとしては考えにくいですが、すでに構築済みのQueueをQuorum Queueに移行したい場合には、利用している機能がすべてサポートされているかは要確認です。最悪の場合は機能不足で移行できない可能性もありえるでしょう。 常にDurableなQueueとして扱われる 先述の通り、DurableではないQueueはQuorum Queueにおいてサポートされていません(そしておそらく今後もサポートされない可能性が高い)つまりQueueは常に永続化がされます。またメッセージもすべて永続化が強制的にされてしまいます。 メッセージの性質が損失を許容できないようなものであれば何ら問題ありませんが、メッセージの安全性よりもパフォーマンスに重きを置きたいような ユースケース には適していません。このあたりは新しい機能だからといって盲目的に採用するのではなく、採用するシステムに適した選択を心がけたいですね。 ディスクI/O Quorum Queueはメッセージを強制的に永続化する、すなわちディスクに書き込むため、ディスクI/Oについて注意をする必要があります。インフラ要件的にはなるべく SSD を採用することが求められます。 インフラ要件以外にも注意すべき点があります。それはExchangeでFANOUTを利用すべきでないということです。 FANOUTはすべてのQueueに対してメッセージを配送するExchangeです。Quorum QueueにおいてはQueueの数が増加するとそれだけディスクに書き込むメッセージ数が増加してしまうため、MQ全体に大量のQueueが存在するような場合には膨大なディスク書き込みを発生させることになります。 このため、Quorum QueueにおいてはFANOUTの利用は避けるべきでしょう。 ノードの数 Quorum QueueはRaft Consensus Algorithmを利用しているため、 クラスタ ーを構成するノード数に留意する必要があります。これを守らないとQuorum Queueの恩恵を受けられず、可用性・一貫性が損なわれる可能性があります。 とりあえず抑えておくべきは以下の2つです ノード数全体が奇数であること 最低ノード数は3 特に注意が必要なのはノード数が2以下の場合はノードが1台も落ちることが許されなくなる点です。また、偶数にしてしまうと、ネットワーク パーティション への耐性が失われる可能性があります。 また、7個以上のノードでQuorum Queueを構成すると性能が低下(レイテンシが増加)するとされています。これを考えると実用的なノード数が3か5ということになります。 レイテンシ Quorum Queueでは常にディスク書き込みが発生することと、Raft Consensus Algorithmのログ レプリケーション の仕組みの関係上、従来のQueueに比べるとレイテンシが高まる可能性があります。 ただ、Quorum Queueの主目的がデータの安全性としているので、パフォーマンスが若干犠牲になるのは致し方ないところではあります。 おわりに 以上、Quorum Queueの紹介でした。 Quorum Queueは日本語はおろか、英語でも文献が少ないこともあって、まだまだ広まっていない印象を受けます。Quorum Queueを利用すること自体はコード上では非常に簡単にできてしまいますが、性質についてはしっかりと理解した上で採用するかどうかを見極める必要があると思います。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
こんにちわ、インフラエンジニアをしている rakus-tatsu-kashi です。 今回は代理投稿です。同じ部署のインフラエンジニアが見つけてくれたテクニックをまとめてくれてました! この場を借りて、改めてお礼させていただきます! ありがとうございます!!! また、インフラエンジニアをやっていると、泥臭くなりやすい設定作業もあります。それを、 それを当たり前だと思いこまず、解決しようとするマインド 実際に解決する手段を見つけて、実現する実行力 が素晴らしい、また凄いなー、と思いました!!負けてはいられん...。 ということで、下記、本編です!! はじめに 今回は皆さんおなじみ、ZabbixのLLD(ローレベルディスカバリ)についてです。 ちょっと便利だなって思ったものがあるのでご紹介したいと思います。 ではさっそくですが、ご紹介する内容は以下2つです。 1.LLDに任意の監視を入れたい! 2.LLDのトリガの深刻度を変えたい! また、実施した環境はこちらになります。 利用するのは、以下の2つです。 いずれも Version 4.0.12 です。 ZabbixServer ZabbixAgent 1.LLDに任意の監視を入れたい! さっそく「1.LLDに任意の監視を入れたい!」からお話ししたいと思います。 皆さんご存じのとおりZabbixLLDはとても便利です。 サーバ(機器)によってデ バイス が何個ほどあるかを考慮せず、 データを取得できるようになったり、 トリガを設定できるようになったり、 をすることができます。 とっても便利です。 ただ、 意外と痒いところに手が届かない。 デフォルトで用意されているアイテムが多くない などはあります。 うちでいうと RAID 監視を作成するときに困りました。 環境によってコントローラの数やvdiskの数が異なるのに…。それぞれ用に結局作らなくちゃいけないの…? この面倒を、LLDの拡張というので解消を試みました。 任意のアイテムキーを json 形式で出力するようにして、そのアイテムキーをディスカバリで指定するとLLDを使えるようになります。 たとえば RAID のvdiskが複数個存在していて、そのvdiskごとにzabbixのアイテムをLLDで作りたい場合は、以下のような スクリプト を書きます #!/bin/bash LIST=`VDISKIDを取得するコマンド` if [ "${LIST}" = "" ] ;then echo "ZBX_NOTSUPPORTED" exit 1 fi echo "{" echo " \"data\":[" FIRST=1 for VER in ${LIST} do if [ ${FIRST} -eq 1 ] ; then echo "" FIRST=0 else echo "," fi echo -e -n "\t\t{ \"{#VDISKID}\":\"${VER}\" }" done echo "" echo " ]" echo "}" すると出力結果はこんな感じ { " data ": [ { " {#VDISKID} ":" 0 " } , { " {#VDISKID} ":" 2 " } ] } ここまで準備できたら、ZabbixAgentに以下の設定を読み込ませます。 UserParameter=vfs.vdisk.discovery,/etc/zabbix/vfs_vdisk_discovery.sh 次に、ZabbixServerでは、 「 vfs .adisk.discovery」をディスカバリルールのキーに指定 「storage.vdisk[{#VDISKID}]をアイテムのプロトタイプのキーに指定 すると! 任意の個数のVDISKがキーとして読み込める!!! という仕組みです。 実施してみると意外と簡単なので試してみてください。 2.LLDのトリガの深刻度を変えたい! つづいて「2.LLDのトリガの深刻度を変えたい!」について とっても便利なLLD、運用していく中で、監視の内容を変更したいと思うことが出来ました。 通常であればテンプレートのトリガの深刻度を修正して…と対応するのですが、LLDのトリガプロトタイプの深刻度を修正しても反映されない! 困りました。 大量にディスカバリで作成されたサーバたち、それらを一つずつ修正しろと…? 現実的ではない…と途方にくれました。 途方に暮れてしばらく空を眺めているうちにひらめきました。 LLDのトリガプロトタイプの深刻度は変更しても反映されない…が、LLDのトリガプロトタイプの条件式の変更は反映される。 ならば 深刻度を修正したうえで、条件式を修正して、また条件式を戻せば…? はやる気持ちを抑えて実験…! 無事深刻度が修正できました! キタ━━(☆∀☆)━━!!! どうやらトリガの無効などもうまく反映されない模様、同じやり方で試してみるのもいいかもしれませんね。 最後に 今回は、ZabbixのLLDについてのTips?を記載させていただきました。 Zabbixはせっかく機能が多いため、こういったTipsを身に身に付けていって、有効活用していきたいですね!! 以上!
こんにちは、masakaです。 前の会社でPWAについて少し調べていたのですが、特に発表することもなかったので 今回はその内容をブログにしてみました。 ざっくりとした説明と、簡単な実装をやってみたいと思います。 PWAとは PWAの代表的な機能 Webとネイティブアプリ、それぞれの特徴とPWAが求めるもの PWAを支える三つの柱 結局のところ、PWAとは PWAの対応状況 デスクトップ環境もPWAの対象に [実践編] PWA化への第一歩 PWA化のために必要なこと - [Web App Manifest]と[Service Worker] manifest Service Worker Webサイトからインストール出来るようにする - A2HS サンプルアプリとWebサーバの準備 A2HSを実装する オフラインでも実行できるようにする おわりに PWAとは ネイティブアプリみたいなWebアプリ PWAは「 progressive web apps」のことを指します。2015年に発表され、話題に上がってきました。 PWAに対応した代表的なサイトとして、 Twitter や国内だとSUUMOなどがよく例に挙げられます。 PWAというワードで検索すると、「ネイティブアプリみたいな」Webアプリである、という抽象的な内容が散見されます。 この表現は間違っていないです が、何をもって「ネイティブアプリみたい」というのか、いまいちはっきりしません。 もう少し詳しく理解してみることにします。 PWAの代表的な機能 機能的な面で調べると、PWAで出来ることとして代表的なものには以下があります。 ホーム画面への追加:アプリの様にインストールし、ホーム画面から起動できる オフライン起動:ネットワークに接続していなくても使用できる バックグラウンド同期:オフライン時に操作した内容を、ネットワーク接続されたタイミングでバックグラウンド送信する プッシュ通知:アプリからの通知 これらの機能が実装されることがPWAなのでしょうか? Webとネイティブアプリ、それぞれの特徴とPWAが求めるもの Google によるPWAの説明 には、ネイティブアプリとWeb アプリの特徴を次のように書いてあります。 ネイティブアプリの特徴 - 機能性・信頼性に優れる ホーム画面、タスクバーなどに存在しネットワークに影響されず使用できる 機能が豊富 Web アプリの特徴 - 到達性に優れる 単一コードベース デ バイス を問わず、誰でもどこでもアクセスできる その上で、PWAはWebアプリに双方の長所を持たせることを目指しているようで、以下のような記載がされています。 PWAはあくまでWeb アプリである モダンな API で構築されている デ バイス やブラウザを問わない到達性 PWAを支える三つの柱 加えてネイティブアプリのように感じさせるための三つの柱についても書かれています。 1.Capable (機能) Webは様々なことが出来るように機能拡張し、成長し続ける これらを取り入れることによりネイティブアプリでしか出来なかったことがWeb で可能になっていく 2.Reliable (信頼) ネットワークに影響されずに使用できる ネットワーク接続が出来ない、あるいは低速なネットワークでも使用できる 3.Installable (インストール可能) ブラウザの中で動くのではなく独立したアプリとして動く 1.はともかく、2.と 3.は具体的ですね。 ちなみに、以前は Google の デベロッパーページ では、 Reliable Fast Engaging という特徴を書いていたようなのですが、少し変わっているようです。 結局のところ、PWAとは これまでの内容で、つまるところPWAとは ネイティブアプリ的なユーザー体験を得られるWebアプリ であり、 ネットワーク状態に影響されず、 独立したアプリのように起動でき、 新しいWebAPIを採用し、機能的にネイティブアプリに大きく劣らないようにする といった要素を満たしておくと、結果的にそうなるという感じでしょうか。 PWAに求められる、より具体的な内容はPWAの チェックリスト を見ると分かります。 よりよいユーザー体験を提供しましょう的な内容が多い印象です。 PWAの対応状況 PWAはあくまでWebアプリなので、ブラウザによって 対応状況 が変わってきてしまいます。 What Web Can Do Today というサイトでは、アクセスされたブラウザでどの機能が使えるか表示してくれます。 Google が推進しているだけあって、 Android Chrome は早くからPWA対応 iOS Safari は一部の機能未対応 セキュリティ的な思惑もあり、すぐに対応は難しそう iOS でもプッシュ通知くらいは使えてほしいですが、iOS14でもまだ未対応です・・。 デスクトップ環境もPWAの対象に PWAは元々モバイル環境をターゲットにしていたようですが、 Chrome とEdgeはデスクトップ環境でもPWAに対応しています。 Chrome は version67 でPWAについての記載があります。 モバイルでPWA対応していたものは、特にデスクトップ用にコードを変更する必要はなく、そのままデスクトップPWAとして使えます。 PCでもPWAを利用できる状況になってきています。 [実践編] PWA化への第一歩 ここからは実践編です。今回は手始めに、PWAっぽくするために インストール可能にする オフラインで使用できる をやってみます。 デスクトップPWAとしての使用をターゲットにします。 PWA化のために必要なこと - [Web App Manifest]と[Service Worker] PWA化において欠かせない要素は、 Web App Manifest Service Worker の二つがあります。 manifest manifestファイルはウェブアプリについての情報や、挙動についての設定が記したファイルです。 ダウンロードし、アプリとして動かすために必要な情報が記載され、中身は JSON です。 ユーザーが取得できるよう、Web上に配置します。 Service Worker Service Workerはブラウザのメイン スクリプト 処理とは別に、バックグラウンドとして実行される スクリプト です。 PWAの肝となる部分かと思います。 ServiceWorkerはWebアプリ(ブラウザ)とネットワークの間で動作します。 必要に応じてキャッシュからデータを取得するか、ネットワークへリク エス トするかを制御できます。 sw オフライン時や、通信環境が悪い状況での実行に密接に影響しそうな機能ですね。 Webサイトからインストール出来るようにする - A2HS アプリとしてホーム画面などに追加する機能を 「A2HS」 と呼びます。(Add-to-Home-Screen の略) 早速、これをやってみましょう。 サンプルアプリとWebサーバの準備 まず、何かWebアプリが必要です。 htmlと JavaScript でごく簡単なクリック連打ゲームを作成しました。 これで試してみましょう。 GitHub にもあります。 クリック連打ゲームのソース index.html <!DOCTYPE html> < html > < head > < meta charset = "utf-8" /> < meta http-equiv = "X-UA-Compatible" content = "IE=edge" /> < meta name = "viewport" content = "width=device-width, initial-scale=1.0" /> < title > button mashing </ title > < link rel = "stylesheet" type = "text/css" href = "app.css" /> </ head > < body > < div class = "wrapper" > < div > 目標クリック連打数: < span class = "js-target-count" > 10 </ span ></ div > < div class = "timer" > < span class = "js-timer-label" > 経過時間: </ span > < span class = "js-spend-time" ></ span > </ div > < div class = "click-btn-wrapper" > < button class = "js-click-target btn-click-target" > < span > Click! </ span >< br /> < span class = "js-counter" ></ span >< br /> </ button > </ div > < div > < button class = "js-reset btn-reset" > リセット </ button > </ div > < div class = "change-count-wrapper" > クリック数を変更する < ul > < li > < button class = "js-change-count btn-change-count" data -count= "10" > クリック数:10回 </ button > </ li > < li > < button class = "js-change-count btn-change-count" data -count= "20" > クリック数:20回 </ button > </ li > < li > < button class = "js-change-count btn-change-count" data -count= "30" > クリック数:30回 </ button > </ li > </ ul > </ div > </ div > < script src = "app.js" ></ script > </ body > </ html > app. css .wrapper { padding : 10px ; max-width : 400px ; margin : 0 auto ; text-align : center ; font-size : 14px ; } .click-btn-wrapper { margin : 10px auto ; } .btn-click-target { display : inline-block ; text-decoration : none ; color : #668ad8 ; background-color : #fff ; width : 80px ; height : 80px ; border-radius : 50 %; border : solid 2px #668ad8 ; text-align : center ; overflow : hidden ; font-weight : bold ; transition : 0.4s ; } .btn-click-target : hover { background : #b3e1ff ; } .change-count-wrapper { max-width : 240px ; margin : 20px auto 0px auto ; } .btn-change-count { position : relative ; display : inline-block ; font-weight : bold ; padding : 0.25em 0.5em ; text-decoration : none ; color : #00bcd4 ; background : #dbebf8 ; border : none ; transition : 0.4s ; } .btn-change-count : hover { background : #00bcd4 ; color : white ; } .header-change-count { border-bottom : solid 3px black ; } ul , ol { padding : 0 ; text-align : center ; margin : 3px 0px ; } ul li { position : relative ; list-style-type : none !important ; padding : 0.3em 0.3em 0.3em 0.3em ; margin-bottom : 1px ; vertical-align : middle ; } .btn-reset { position : relative ; display : inline-block ; font-weight : bold ; padding : 0.25em 0.5em ; text-decoration : none ; color : #00BCD4 ; background : #ECECEC ; border : none ; border-radius : 0 ; transition : . 4s ; } .btn-reset : hover { background : #636363 ; } app.js let clickCount = 0; let playing = false ; let targetCount = 10; let spendTime = 0; let timerId = 0; const clickTarget = document .querySelector( ".js-click-target" ); const resetBtn = document .querySelector( ".js-reset" ); const counterText = document .querySelector( ".js-counter" ); const targetCountText = document .querySelector( ".js-target-count" ); const spendTimeText = document .querySelector( ".js-spend-time" ); const timerLabelText = document .querySelector( ".js-timer-label" ); const countChanger = document .getElementsByClassName( "js-change-count" ); Array .prototype.forEach.call(countChanger, (btn) => { btn.addEventListener( "click" , (e) => { targetCount = btn.getAttribute( "data-count" ); targetCountText.innerHTML = targetCount; } ); } ); const start = () => { clickCount = 0; time = 0; playing = true ; timerLabelText.innerHTML = "経過時間:" ; counterText.innerText = clickCount; spendTimeText.innerHTML = time / 1000; timerId = setInterval(() => { time += 10; spendTimeText.innerHTML = (time / 1000).toFixed(2); } , 10); } ; const complete = () => { playing = false ; timerLabelText.innerHTML = "連打終了! 記録:" ; clearInterval(timerId); clickTarget.disabled = true ; setTimeout(() => (clickTarget.disabled = false ), 2000); } ; const reset = () => { playing = false ; clickCount = 0; counterText.innerText = clickCount; spendTimeText.innerHTML = 0; timerLabelText.innerHTML = "経過時間:" ; clickTarget.disabled = false ; clearInterval(timerId); } ; // 初回クリックでスタート clickTarget.addEventListener( "click" , () => { if (playing) return ; start(); playing = true ; } ); // クリック時のカウントアップ clickTarget.addEventListener( "click" , () => { if (!playing) return ; counterText.innerText = ++clickCount; if (clickCount >= targetCount) { complete(); } } ); // リセットボタン resetBtn.addEventListener( "click" , () => reset()); これらhtml, css , jsファイルを配置したらローカルでwebサーバを起動してアクセスできるようにします。 (ここではnode.jsの http-server を使いますが、なんでも構いません) npm install -g http-server ファイルを配置した場所で http-server -p 8001 これで http://localhost:8001/index.html `にアクセスできるようにします。 ※ちなみに、 GitHub Pagesを使うと HTTPS でアクセスできるので楽です。 A2HSを実装する やることはそう多くはありません。以下を実行すれば、インストールが可能になります。 1.manifest(Web App Manifest)を作成する htmlのヘッダにmanifest. json へのlinkを記述する 2.ServiceWorkerを登録し、fetchイベントをハンドリングさせる この他に HTTPS 経由で提供される必要があるようですが、 localhost の場合はHTTPでもOK です。 1.manifestの作成 まずmanifestを作成していきます。 中身は JSON ですが、拡張子は .webmanifest にするべきなようです。が、 .json でも動きます。 ここでは manifest.webmanifest として作成します。 manifest.webmanifest { " name ": " Button mashing ", " short_name ": " Bm ", " description ": " クリック連打 ", " icons ": [ { " src ": " ./icons/icon-192.png ", " sizes ": " 192x192 ", " type ": " image/png " } , { " src ": " ./icons/icon-512.png ", " sizes ": " 512x512 ", " type ": " image/png " } ] , " start_url ": " ./index.html ", " display ": " standalone ", " background_color ": " #FFFFFF ", " theme_color ": " #FFFFFF " } ざっと項目の説明です。 name: アプリの名称。 icons: ホーム画面やデスクトップに表示するアイコン。192 192と512 512があると良いらしいです。(とりあえず適当に作るか拾う) start_url: インストールして実行するファイルのパス。 display: 表示方法。アプリっぽく動かすには、 standalone か fullscreen を指定。fullscreenだとステータスバーなどのUIも表示されない。 パス系はmanifestファイルの場所からの 相対パス です。 作成したら、index.htmlにこのmanifestへのリンクを記載します。 index.html <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>button mashing</title> <link rel="stylesheet" type="text/css" href="app.css" /> + <link rel="manifest" href="manifest.webmanifest" /> </script> </head> 2.Service Workerの登録 SeriveWorkerの実態は JavaScript です。 sw.js にSeriveWorkerの本体を記載し、それをアプリ内から登録します。 sw.js self .addEventListener( 'fetch' , (e) => {} ) インストールに必要なのは、このfetchイベントをハンドリングさせるだけです。コールバックは空で構いません。 (ServiceWorker内では、selfに ServiceWorkerGlobalScope がbindされています。) これをアプリケーション内で登録します。 index.html <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>button mashing</title> <link rel="stylesheet" type="text/css" href="app.css" /> <link rel="manifest" href="manifest.webmanifest" /> + <!-- ServiceWorker --> + <script> + if ("serviceWorker" in navigator) { + window.addEventListener("load", function () { + navigator.serviceWorker.register("./sw.js").then( + function (registration) { + // Registration was successful + console.log( + "ServiceWorker registration successful with scope: ", + registration.scope + ); + }, + function (err) { + // registration failed :( + console.log("ServiceWorker registration failed: ", err); + } + ); + }); + } + </script> </head> ここまで変更したら、 localhost:8001/index.html にアクセスします。 アドレスバーの右端に、 + のアイコンが追加されました。 PWAのインストールボタン・・・わかりづらい クリックしてインストールしてみます。デスクトップにアイコンが追加され、起動してみると・・ デスクトップから起動したアプリ 起動できました。これでデスクトップに追加することができるようになりました。 オフラインでも実行できるようにする アプリとして起動できるようにはなりましたが、このままではオフラインでは使用できません。 コンテンツをオフラインで使用できるようにするため、キャッシュ処理をService Workerに書かなければならないのですが、 workbox を使うと簡単に試せます。 sw.jsにworkboxを利用したファイルのキャッシュ処理を書いてみましょう。 sw.jsに以下を追加します。 importScripts( 'https://storage.googleapis.com/workbox-cdn/releases/6.0.2/workbox-sw.js' ); workbox.precaching.precacheAndRoute( [ '/index.html' , '/app.css' , '/app.js' ] ); pre-cacheを使用しています。(インストール時にキャッシュされる機能) 本来はファイルにリビジョンを指定して、バージョン管理を行うことも必要ですが今回は割愛します。 キャッシュ処理を追加したところで、再度アプリをインストールし直してみます。(アンインストールはアプリ右上のメニューからできます) http-serverを停止したり、オフライン状態でもインストールしたゲームを起動できるようになっています。 どういう仕組みになっているのか軽く確認してみましょう。 開発者ツールを見るとキャッシュされたファイルはService Workerから取得していることがわかります cache storageに保存されています これで、オフライン実行が有効になります。 PWA化への第一歩を踏み出せました。 おわりに PWAとは何かの把握と実装の第一歩をやってみました。 機会があったらプッシュ通知あたりもやってみたいと思います。 PWA自体は対応するサイトも増えてきているようですが、普及に関しては iOS の対応が未だ不透明である点がネックですね。 とはいえ iOS も徐々に対応機能を増やしてきてはいるので、今後も発展が見込めそうな技術かと思います。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
はじめに 皆さん初めましてseahoseTです。 今回は Linux 上で文字列を処理することに便利な awk について紹介していきたいと思います。 目次 はじめに awkとは ここがすごいよ!awkのアレコレ! awkの基本的な仕様 awkのコマンド パターン 正規表現 BEGIN,END 評価式 アクション awkの組み込み変数 awkのオプション awkの注意点 問題編:行の指定 解決編:行の指定 問題編:複数のパターンを使用する 解決編:複数のパターンを使用する 問題編:NRとFNR 解決編:NRとFNR 問題編:awkでシェル変数を使用する 解決編:awkでシェル変数を使用する awkの実践 おわりに awk とは AWK (オーク)は、 プログラミング言語 の一つ。 テキストファイル、特に空白類(スペースの他、タブなど)やカンマなどで区切られたデータファイルの処理を念頭に置いた仕様となっているが、 一般的なプログラミングに用いることも可能である。 UNIX 上で開発された。( Wikipedia より) awk とは Linux や Unix ( Mac )で使用できるファイルの集計など文字列を扱う場合に便利な プログラミング言語 。 同様に文字列を処理できる sed などが非常に特殊な文法をしていた事に対して、 C言語 ライクで人が分かりやすいような文法をしている。 awk は プログラミング言語 であるが、 Linux のコマンドのように扱うことができる 。 目次へ ここがすごいよ! awk のアレコレ! 殆どの Linux や Unix ( Mac )上で標準で使用することができ、コマンドの使い回しができるなど互換性が高い 「 gawk 」をインストールするなどひと手間必要だが Windows でも問題なく使用することができる プログラミング言語 であるが、 コンパイル は不要 簡単 目次へ awk の基本的な仕様 awk の基本的な構文は下記のようになる。 # コマンドを直接入力する場合 awk ' コマンド ' [ 入力ファイルのパス ] # コマンドをファイルから入力する場合 awk -f コマンドファイルのパス [ 入力ファイルのパス ] また、入力ファイルを複数指定することも可能。 # 入力ファイルを複数設定したい場合 awk ' コマンド ' [ 入力ファイルのパス 1 ] [ 入力ファイルのパス 2 ] ..... 「入力ファイル」を設定せずに「パイプ」や「リダイレクト」での受け渡しも可能。 # 入力を「パイプ」で行う場合の例 echo | awk ' コマンド ' awk では 各行ごと に指定した列に対して処理を行う。 この時 awk では行の事を 「レコード」 、列のことを 「フィールド」 と呼ぶ。 例 ) date.txt  列 1 列 2 列 3 行  1   2   3 行  4   5   6 上記の例のような「date.txt」が存在する場合にフィールド1(列1)を表示したい場合には、 # 「date.txt」のフィールド1(列1)を表示 awk ' {print $1} ' date.txt と記述することで各レコード(行)のフィールド1(列1)を表示し、下記のような結果を得ることができる。 # 結果 1 4 また、「$0」を使用することで全てのレコード(行)、フィールド(列)を参照することが可能。 # 「date.txt」の全レコード(行)、フィールド(列)を表示 awk ' {print $0} ' date.txt # 結果 1 2 3 4 5 6 目次へ awk のコマンド awkの基本的な仕様 で awk の'コマンド'と記述している部分は本来「パターン」と「アクション」の二つから成る。「アクション」の部分は具体的にどのような処理を行うのかを内容を記述する。「パターン」の部分ではどのような場合にアクションを行うかの条件を決定している。また、 awkの基本的な仕様 で行った通り「パターン」の部分に何も記述しない場合でも問題なく動作する。 # 'コマンド'を「パターン」部分と「アクション」部分に分けた場合 awk ' パターン { アクション } ' [ 入力ファイルのパス ] パターンの種類 正規表現 BEGIN END 評価式 正規表現 記述した 正規表現 のパターンにマッチした行にアクション部分の処理を施す。 # 書き方 awk ' /正規表現/ { アクション } ' [ 入力ファイルのパス ] このように 正規表現 の左右にスラッシュを入れて記述する。 例 ) date.txt  列 1 列 2 列 3 行  1   2   3 行  4   5   6 # 「date.txt」ファイル中の「4」で「終わる」フィールド(列)を含むレコード(行)がある場合 # そのフィールド(行)のフィールド2(列2)を表示する awk ' /4$/ { print $2 } ' date.txt # 結果 5 BEGIN,END awk では「BEGIN」、「END」を使用することで「メイン」を含めた三つのブロック構造を作ることが出来る。「BEGIN」と「END」は前処理、後処理の関係になっており、「BEGIN」では入力ファイルを 読み込む前 に処理が行われ、「END」では入力ファイルを 読み込み終わった後 の処理を記述する。 宣言した変数は「BEGIN」、「メイン」、「END」のブロックをまたいで使用することが可能。一般的には「BEGIN」で宣言を行う。 # 書き方 # 例1 awk ' BEGIN { 入力ファイルを読み込む前のアクション } { メイン処理 } ' [ 入力ファイルのパス ] # 例2 awk ' { メイン処理 } END { 入力ファイルを読み込んだ後のアクション } ' [ 入力ファイルのパス ] # 例3 awk ' BEGIN { 入力ファイルを読み込む前のアクション } { メイン処理 } END { 入力ファイルを読み込んだ後のアクション } ' [ 入力ファイルのパス ] 「BEGIN」、「END」は省略可能であるため「メイン」の処理のみを記述した際でも問題なく動作する。 評価式 評価式の評価にマッチした行にアクション部分の処理を施す。 例 ) date.txt  列 1 列 2 列 3 行  1   2   3 行  4   5   6 # 「date.txt」ファイル中の「フィールド3(列3)」が「6」であるレコード(行)が存在する場合 # そのレコード(行)のフィールド3(列3)を表示する awk ' $3 == "6" { print $3 } ' date.txt # 結果 6 この結果だけ見ると前述した 正規表現 で良いように思えるが後述する組み込み変数や「-v」オプションと組み合わせた際に真価を発揮する。 アクション 「アクション」内で複数の処理を行う場合は セミ コロン(;)で区切る。 例 ) date.txt  列 1 列 2 列 3 行  1   2   3 行  4   5   6 # 「アクション」内で複数の処理を行う例 awk ' {print $0; print $1} ' date.txt # 結果 1 2 3 4 5 6 1 4 同じような処理を連続で行う場合にはカンマ(,)での記述も可能。 # 「$0」と「$1」を表示 awk ' {print $0, $1} ' date.txt # 結果 1 2 3 4 5 6 1 4 変数を使用する場合は Linux コマンドと違い「$」をつけない。 # 変数の仕様 awk ' {age = 2021; print age} ' date.txt # 結果 2021 目次へ awk の組み込み変数 予め awk に準備されている変数。「パターン」、「アクション」両方で使える。シェルの場合と違い組み込み変数を使用する際には「$」をつける必要がない点に注意。 変数名 効果 デフォルト(未設定の場合) ARGC コマンドライン 引数の個数 ARGV コマンドライン 引数(配列に格納) ENVIRON シェルの 環境変数 を参照 FILENAME 現在処理しているファイルの名前 FNR 現在処理しているファイルのレコード数(行数) NR 現在処理しているレコード含む処理した総レコードの数(行数) ※入力ファイルが複数の時注意 RS 読み込み時のレコード(行)の区切り文字 改行 ORS 出力時のレコード(行)の区切り文字 改行 FS 読み込み時のフィールド(列)の区切り文字 ※「-F」オプションでも変更可能 空白 OFS 出力時のレコード(行)の区切り文字 空白 例 ) date.txt  列 1 列 2 列 3 行  1   2   3 行  4   5   6 # 「date.txt」の改行を,に変更して表示 awk ' ORS = "," {print $0} ' date.txt # 結果 1 2 3 , 4 5 6 目次へ awk のオプション awk のオプションは一般的な Linux コマンドと同様に使うことができる。 オプション名 効果 デフォルト(未設定の場合) -f コマンドファイル名 awk コマンドが書かれたファイルを指定する -F 区切り文字 区切り文字を指定する 空白 -v 変数名=値 変数を定義する # オプションの記述例 awk -オプション ' コマンド ' [ 入力ファイルのパス ] 目次へ awk の注意点 この項では筆者が awk を使用した際に躓いた事に対する注意点を挙げていく。 問題編:行の指定 awk を実行する時、「パターン」で行数を指定しない場合、デフォルトでは全ての行を対象に取る。 解決編:行の指定 # 「date.txt」のレコード1(行1)のフィールド2(列2)を表示 awk ' NR == 1{print $2} ' date.txt パターンの部分に「NR == 表示したい行数」を設定することで指定した特定の行数のみの結果を得ることができる。パターンには4種類の項目があることは コマンド で記載しているが、原理としては評価式として現在の行数を評価しているといった形になる。 問題編:複数のパターンを使用する 「パターン」は複数を組み合わせることができる。 解決編:複数のパターンを使用する 「&&」や「||」を使うと、複数のパターンを組み合わせることがでる。また、「()」を使用することで数式のようにパターンの優先度を変更できる。 # 複数個パターンを使用したawkの例 例 ) date.txt  列 1 列 2 列 3 行  1   2   3 行  4   5   6 # レコード1(行1)以降でかつフィールド2(列2)が2ではない物を表示 awk ' NR>1 && ! ( $2 ~ 2 ){ print $0} ' date.txt ※「~」はマッチ演算子で「 = 」とほとんど同じ効果を持つ。「 = 」に置き換えた場合でも動作する。 # 結果 4 5 6 問題編:NRとFNR 入力ファイルが複数個の場合のレコード数(行数)が加算されてしまう。 解決編:NRとFNR 組み込み変数「NR」を使用してある特定のレコード(行)にのみ変更を加えたい。そんな時に、「入力ファイル」が複数個存在する場合注意が必要だ。例えば下記のような二つの入力ファイルがあったとしよう、 # 一つ目の入力ファイル 例 ) date1.txt  列 1 列 2 列 3 行  1   2   3 行  4   5   6 # 二つ目の入力ファイル 例 ) date2.txt  列 1 列 2 列 3 行  7   8   9 行  10   11   12 二つの入力ファイルそれぞれのレコード2(行2)を表示したいので「NR == 2」として awk のコマンドを設定する。 # レコード2(行2)を表示したいコマンド awk ' NR == 2 {print $0} ' date1.txt date2.txt # 結果 4 5 6 「NR == 2」ではこのように「入力ファイル1」のレコード2(行2)だけしか表示することができていない。では、「FNR == 2」を使用してみるとどうだろう、 # レコード2(行2)を表示したいコマンド awk ' FNR == 2 {print $0} ' date1.txt date2.txt # 結果 4 5 6 10 11 12 期待した通りの結果、「date1.txt」と「date2.txt」のレコード2(行2)がそれぞれ表示していることが分かる。では次に「NR == 3」を行ってみる。 # レコード2(行2)を表示したいコマンド awk ' NR == 3 {print $0} ' date1.txt date2.txt # 結果 7 8 9 入力ファイル2のレコード1(行1)が表示されている。これはどこからレコード(行)のカウントが始まっているかの違いである。「NR」の場合は入力ファイル1の総レコードの2を処理した後入力ファイル2のレコード1(行1)を現在の行数に 加算 する。つまり入力ファイル2のレコード1(行1)は2+1で「NR = 3」にあたるということになる。 対して「FNR」は入力ファイル1の総レコードの2を処理した後行数のカウントを リセット する。つまり、レコード数(行数)は現在処理している入力ファイルのレコード数(行数)を参照することになる。 # 「NR」の処理イメージ(直列)   列 1 列 2 列 3 行 1   1   2   3 行 2   4   5   6 行 3   7   8   9 行 4   10   11   12 # 「FNR」のイメージ(並列)   列 1 列 2 列 3 行 1   1   2   3 行 2   4   5   6   列 1 列 2 列 3 行 1   7   8   9 行 2   10   11   12 問題編: awk でシェル変数を使用する awk 内ではデフォルトの状態でシェル変数を使用することはできない。 解決編: awk でシェル変数を使用する 例 ) date.txt  列 1 列 2 列 3 行  1   2   3 行  4   5   6 # シェル変数 var = 100 上記のように「date.txt」とシェル変数「var」が設定されている場合に「date.txt」のフィールド2(列2)と「var」の合計を awk を用い表示したいとする時、 # 「date.txt」のフィールド2(列2)とシェル変数「var」の合計を表示 awk ' {print $2 + var} ' date.txt と記述してもシェル変数である「var」を正しく認識できないため、正しい結果を得ることはできない。 awk は Linux のコマンドのように扱うことができるが、あくまで プログラミング言語 の一種であるため同様に扱うことができないのである。そこで解決策として「-v」オプションを使用する。 「-v」オプション オプション名 効果 -v 変数名=値 変数を定義する オプション の項で紹介している物と同様である。「-v」オプションでは任意の変数名に値を設定することで任意の変数を組み込み変数のように「パターン」や「アクション」で使用できるようにする効果がある。正確に言うと プログラミング言語 awk に対して 値を受け渡す オプションとなっている。値を設定する際、 シェル変数を受け渡すことも可能 なのでデフォルトではシェル変数を使用することが出来ないといった問題を解決することができる。 # 上記の例をもとにした「-v」オプション設定例 例 ) date.txt  列 1 列 2 列 3 行  1   2   3 行  4   5   6 # シェル変数 var = 100 # 「date.txt」のフィールド2(列2)とシェル変数「var」の合計を表示 awk -v awkVar = $var ' {print $2 + awkVar} ' date.txt # 結果 102 105 「-v」オプションを複数設定することで複数の変数を設定することもできる。 # 上記の例をもとにした「-v」オプション設定例 例 ) date.txt  列 1 列 2 列 3 行  1   2   3 行  4   5   6 # シェル変数 var = 100 var2 = 200 # 「date.txt」のフィールド2(列2)とシェル変数「var」、シェル変数「var2」の合計を表示 awk -v awkVar1 = $var -v awkVar2 = $var2 ' {print $2 + awkVar1 + awkVar2} ' date.txt # 結果 302 305 注意して欲しいのは設定した変数をコマンド内で使用する場合 組み込み変数 と同様に、「$」をつけずに、設定した変数名のみを記述することだ。シェルでの一般的な変数呼び出しとは勝手が違うので気を付ける必要がある。 ・・・しかし、実は「-v」オプションを使わなくても awk に値を受け渡すことは可能である。 例 ) date.txt  列 1 列 2 列 3 行  1   2   3 行  4   5   6 # シェル変数 var = 100 # 「-v」オプションを使用せずに変数「awkVar3」を設定 awk ' {print $2 + awkVar3} ' awkVar3 = $var date.txt # 結果 102 105 これだけ見ると同様の動作をしているように見えるが次の例を見て欲しい。 # 「-v」オプションを使い「message」を設定 echo | awk -v message = " Test massage " ' BEGIN{print massage} {print massaeg} END{print massage} ' # BEGIN:結果 Test massage # メイン:結果 Test massage # END:結果 Test massage # 「-v」オプションを使わずに「message」を設定 echo | awk ' BEGIN{print massage} {print massaeg} END{print massage} ' message = " Test massage " # BEGIN:結果 # メイン:結果 Test massage # END:結果 Test massage おわかりいただけただろうか。「-v」オプションを使用せずに変数を設定した場合「パターン」の「BEGIN」ブロックにおいて変数が参照できていないのである。この違いにより「-v」オプションを使用することの方が安全であると言える。 また、処理を繰り返しを行う回数は「入力ファイル」のレコード数(行数)であるということに注意。 例 ) date.txt  列 1 列 2 列 3 行  1   2   3 行  4   5   6 # シェル変数 var = 100 # awkVar4の表示 awk -v awkVar4 = $var ' {print awkVar4} ' date.txt # 結果 100 100 # 「date.txt」の総レコード数(行数)である2回分の表示処理が繰り返し行われている。 他にも「-v」オプションを使わずに awk 内でシェル変数を使用する方法があるので紹介しておく。 # シェル変数 var = 100 # 変数名を「'」(シングルクォーテーション)で囲む echo | awk ' {pritn ' ${var} ' } ' # 結果 100 awk は「'」(シングルクォート)に囲まれたところを解析しようとするので、シェル変数の部分は「'」(シングルクォート)から外せばシェル変数として扱ってくれる。 目次へ awk の実践 「stress」コマンドを用いてCPUに負荷をかけそのログの統計情報を算出してみた。ログは長いので折り畳み先に記載する。 5分間の「vmstat」のログ 1 2021 / 01 / 18 09:56:00 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 2 2021 / 01 / 18 09:56:00 r b swpd free buff cache si so bi bo in cs us sy id wa st 3 2021 / 01 / 18 09:56:00 2 0 0 1152892 2284 471684 0 0 0 1 7 10 0 0 100 0 0 4 2021 / 01 / 18 09:56:01 0 0 0 1152752 2284 471680 0 0 0 0 152 333 0 0 100 0 0 5 2021 / 01 / 18 09:56:02 0 0 0 1152752 2284 471680 0 0 0 0 122 272 0 0 100 0 0 6 2021 / 01 / 18 09:56:03 0 0 0 1152752 2284 471680 0 0 0 432 166 345 0 0 100 0 0 7 2021 / 01 / 18 09:56:04 0 0 0 1152752 2284 471680 0 0 0 0 139 292 0 0 100 0 0 8 2021 / 01 / 18 09:56:05 4 0 0 1147864 2284 474028 0 0 0 0 827 263 73 2 25 0 0 9 2021 / 01 / 18 09:56:06 1 0 0 1147864 2284 474028 0 0 0 0 873 242 80 1 19 0 0 10 2021 / 01 / 18 09:56:07 1 0 0 1147864 2284 474028 0 0 0 0 867 241 80 0 20 0 0 11 2021 / 01 / 18 09:56:08 5 0 0 1147864 2284 474028 0 0 0 0 871 242 80 0 20 0 0 12 2021 / 01 / 18 09:56:09 0 0 0 1147864 2284 474028 0 0 0 0 865 241 81 0 19 0 0 13 2021 / 01 / 18 09:56:10 1 0 0 1147864 2284 474028 0 0 0 0 861 253 78 0 22 0 0 14 2021 / 01 / 18 09:56:11 1 0 0 1147864 2284 474028 0 0 0 0 874 241 80 1 19 0 0 15 2021 / 01 / 18 09:56:12 1 0 0 1147864 2284 474028 0 0 0 4 859 230 79 1 20 0 0 16 2021 / 01 / 18 09:56:13 1 0 0 1147864 2284 474028 0 0 0 0 873 250 81 0 19 0 0 17 2021 / 01 / 18 09:56:14 0 0 0 1147832 2284 474028 0 0 0 0 860 239 80 0 20 0 0 18 2021 / 01 / 18 09:56:15 1 0 0 1147832 2284 474028 0 0 0 0 871 255 79 0 21 0 0 19 2021 / 01 / 18 09:56:16 0 0 0 1147832 2284 474028 0 0 0 0 860 232 80 1 19 0 0 20 2021 / 01 / 18 09:56:17 2 0 0 1147832 2284 474028 0 0 0 0 868 239 80 0 20 0 0 21 2021 / 01 / 18 09:56:18 1 0 0 1147832 2284 474028 0 0 0 0 881 255 81 0 19 0 0 22 2021 / 01 / 18 09:56:19 0 0 0 1147832 2284 474028 0 0 0 0 852 236 79 0 21 0 0 23 2021 / 01 / 18 09:56:20 1 0 0 1147832 2284 474028 0 0 0 0 873 248 81 0 19 0 0 24 2021 / 01 / 18 09:56:21 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 25 2021 / 01 / 18 09:56:21 r b swpd free buff cache si so bi bo in cs us sy id wa st 26 2021 / 01 / 18 09:56:21 1 0 0 1147832 2284 474028 0 0 0 0 875 267 79 1 20 0 0 27 2021 / 01 / 18 09:56:22 2 0 0 1147832 2284 474028 0 0 0 0 860 235 78 1 21 0 0 28 2021 / 01 / 18 09:56:23 3 0 0 1147832 2284 474028 0 0 0 0 868 247 80 0 20 0 0 29 2021 / 01 / 18 09:56:24 1 0 0 1147832 2284 474028 0 0 0 0 871 221 81 0 19 0 0 30 2021 / 01 / 18 09:56:25 1 0 0 1147832 2284 474028 0 0 0 0 883 241 81 0 19 0 0 31 2021 / 01 / 18 09:56:26 0 0 0 1147832 2284 474028 0 0 0 0 861 249 78 1 21 0 0 32 2021 / 01 / 18 09:56:27 0 0 0 1147832 2284 474028 0 0 0 0 892 261 81 0 19 0 0 33 2021 / 01 / 18 09:56:28 0 0 0 1147832 2284 474028 0 0 0 0 869 250 79 0 21 0 0 34 2021 / 01 / 18 09:56:29 1 0 0 1147832 2284 474028 0 0 0 0 891 254 80 0 20 0 0 35 2021 / 01 / 18 09:56:30 1 0 0 1147832 2284 474028 0 0 0 0 879 250 79 2 19 0 0 36 2021 / 01 / 18 09:56:31 2 0 0 1147832 2284 474028 0 0 0 0 879 234 80 0 20 0 0 37 2021 / 01 / 18 09:56:32 0 0 0 1147832 2284 474028 0 0 0 0 887 248 81 0 19 0 0 38 2021 / 01 / 18 09:56:33 2 0 0 1147832 2284 474028 0 0 0 2 874 275 78 0 22 0 0 39 2021 / 01 / 18 09:56:34 1 0 0 1147832 2284 474028 0 0 0 0 887 261 81 0 19 0 0 40 2021 / 01 / 18 09:56:35 1 0 0 1147832 2284 474028 0 0 0 0 872 261 80 0 20 0 0 41 2021 / 01 / 18 09:56:36 4 0 0 1147832 2284 474028 0 0 0 0 891 258 80 1 19 0 0 42 2021 / 01 / 18 09:56:37 0 0 0 1147832 2284 474032 0 0 0 0 865 237 79 0 21 0 0 43 2021 / 01 / 18 09:56:38 1 0 0 1147832 2284 474032 0 0 0 0 885 260 80 0 20 0 0 44 2021 / 01 / 18 09:56:39 0 0 0 1147832 2284 474032 0 0 0 0 868 238 80 0 20 0 0 45 2021 / 01 / 18 09:56:40 1 0 0 1147832 2284 474032 0 0 0 0 883 264 78 2 20 0 0 46 2021 / 01 / 18 09:56:41 1 0 0 1147832 2284 474032 0 0 0 0 878 237 81 0 19 0 0 47 2021 / 01 / 18 09:56:42 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 48 2021 / 01 / 18 09:56:42 r b swpd free buff cache si so bi bo in cs us sy id wa st 49 2021 / 01 / 18 09:56:42 2 0 0 1147832 2284 474032 0 0 0 0 871 235 80 0 20 0 0 50 2021 / 01 / 18 09:56:43 1 0 0 1147832 2284 474032 0 0 0 8 880 223 81 0 19 0 0 51 2021 / 01 / 18 09:56:44 1 0 0 1147832 2284 474032 0 0 0 0 872 258 80 0 20 0 0 52 2021 / 01 / 18 09:56:45 2 0 0 1147832 2284 474032 0 0 0 0 856 231 78 0 22 0 0 53 2021 / 01 / 18 09:56:46 1 0 0 1147832 2284 474032 0 0 0 0 888 252 80 1 19 0 0 54 2021 / 01 / 18 09:56:47 1 0 0 1147832 2284 474032 0 0 0 0 872 242 80 0 20 0 0 55 2021 / 01 / 18 09:56:48 1 0 0 1147832 2284 474032 0 0 0 0 896 253 81 0 19 0 0 56 2021 / 01 / 18 09:56:49 0 0 0 1147832 2284 474032 0 0 0 0 874 240 81 0 19 0 0 57 2021 / 01 / 18 09:56:50 0 0 0 1147832 2284 474032 0 0 0 0 872 261 79 0 21 0 0 58 2021 / 01 / 18 09:56:51 1 0 0 1147832 2284 474032 0 0 0 0 875 229 80 1 19 0 0 59 2021 / 01 / 18 09:56:52 0 0 0 1147832 2284 474032 0 0 0 0 854 239 78 0 22 0 0 60 2021 / 01 / 18 09:56:53 1 0 0 1147832 2284 474032 0 0 0 0 869 223 81 0 19 0 0 61 2021 / 01 / 18 09:56:54 1 0 0 1147832 2284 474032 0 0 0 0 861 243 80 0 20 0 0 62 2021 / 01 / 18 09:56:55 1 0 0 1147832 2284 474032 0 0 0 0 870 227 80 0 20 0 0 63 2021 / 01 / 18 09:56:56 0 0 0 1147832 2284 474032 0 0 0 0 887 256 80 1 19 0 0 64 2021 / 01 / 18 09:56:57 1 0 0 1147832 2284 474032 0 0 0 9 856 228 79 0 21 0 0 65 2021 / 01 / 18 09:56:58 1 0 0 1147832 2284 474032 0 0 0 0 865 238 80 0 20 0 0 66 2021 / 01 / 18 09:56:59 1 0 0 1147832 2284 474032 0 0 0 0 872 219 80 0 20 0 0 67 2021 / 01 / 18 09:57:00 1 0 0 1147832 2284 474032 0 0 0 0 898 273 81 0 19 0 0 68 2021 / 01 / 18 09:57:01 0 0 0 1147832 2284 474032 0 0 0 0 868 243 79 2 19 0 0 69 2021 / 01 / 18 09:57:02 1 0 0 1147832 2284 474032 0 0 0 0 872 244 80 0 20 0 0 70 2021 / 01 / 18 09:57:03 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 71 2021 / 01 / 18 09:57:03 r b swpd free buff cache si so bi bo in cs us sy id wa st 72 2021 / 01 / 18 09:57:03 1 0 0 1147832 2284 474032 0 0 0 13 878 249 79 1 20 0 0 73 2021 / 01 / 18 09:57:04 3 0 0 1147832 2284 474032 0 0 0 0 861 232 79 0 21 0 0 74 2021 / 01 / 18 09:57:05 3 0 0 1147832 2284 474032 0 0 0 0 883 234 80 0 20 0 0 75 2021 / 01 / 18 09:57:06 5 0 0 1147832 2284 474032 0 0 0 0 880 238 79 1 20 0 0 76 2021 / 01 / 18 09:57:07 1 0 0 1147832 2284 474032 0 0 0 0 881 227 81 0 19 0 0 77 2021 / 01 / 18 09:57:08 0 0 0 1147832 2284 474032 0 0 0 0 868 235 80 0 20 0 0 78 2021 / 01 / 18 09:57:09 0 0 0 1147832 2284 474032 0 0 0 0 873 257 79 0 21 0 0 79 2021 / 01 / 18 09:57:10 0 0 0 1147832 2284 474032 0 0 0 0 901 273 81 0 19 0 0 80 2021 / 01 / 18 09:57:11 2 0 0 1147832 2284 474032 0 0 0 0 878 244 78 1 21 0 0 81 2021 / 01 / 18 09:57:12 1 0 0 1147832 2284 474032 0 0 0 0 882 242 81 0 19 0 0 82 2021 / 01 / 18 09:57:13 1 0 0 1147832 2284 474036 0 0 0 0 861 234 80 0 20 0 0 83 2021 / 01 / 18 09:57:14 1 0 0 1147832 2284 474036 0 0 0 8 876 209 81 0 19 0 0 84 2021 / 01 / 18 09:57:15 0 0 0 1147832 2284 474036 0 0 0 0 854 228 78 0 22 0 0 85 2021 / 01 / 18 09:57:16 1 0 0 1147832 2284 474036 0 0 0 0 886 265 80 1 19 0 0 86 2021 / 01 / 18 09:57:17 1 0 0 1147832 2284 474036 0 0 0 0 883 260 80 0 20 0 0 87 2021 / 01 / 18 09:57:18 1 0 0 1147832 2284 474036 0 0 0 0 878 241 80 0 20 0 0 88 2021 / 01 / 18 09:57:19 2 0 0 1147832 2284 474036 0 0 0 0 893 245 80 1 19 0 0 89 2021 / 01 / 18 09:57:20 0 0 0 1147832 2284 474036 0 0 0 0 870 235 79 1 20 0 0 90 2021 / 01 / 18 09:57:21 1 0 0 1147832 2284 474036 0 0 0 0 870 238 79 1 20 0 0 91 2021 / 01 / 18 09:57:22 1 0 0 1147832 2284 474036 0 0 0 0 878 244 81 0 19 0 0 92 2021 / 01 / 18 09:57:23 1 0 0 1147832 2284 474036 0 0 0 0 851 241 78 0 22 0 0 93 2021 / 01 / 18 09:57:24 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 94 2021 / 01 / 18 09:57:24 r b swpd free buff cache si so bi bo in cs us sy id wa st 95 2021 / 01 / 18 09:57:24 3 0 0 1147832 2284 474036 0 0 0 0 879 222 81 0 19 0 0 96 2021 / 01 / 18 09:57:25 1 0 0 1147832 2284 474036 0 0 0 0 879 244 80 0 20 0 0 97 2021 / 01 / 18 09:57:26 1 0 0 1147832 2284 474036 0 0 0 0 893 269 80 1 19 0 0 98 2021 / 01 / 18 09:57:27 0 0 0 1147832 2284 474036 0 0 0 0 882 276 79 0 21 0 0 99 2021 / 01 / 18 09:57:28 1 0 0 1147832 2284 474036 0 0 0 0 887 266 80 0 20 0 0 100 2021 / 01 / 18 09:57:29 1 0 0 1147832 2284 474036 0 0 0 0 878 250 80 0 20 0 0 101 2021 / 01 / 18 09:57:30 3 0 0 1147832 2284 474036 0 0 0 0 896 264 80 0 20 0 0 102 2021 / 01 / 18 09:57:31 2 0 0 1147832 2284 474036 0 0 0 0 886 239 80 1 19 0 0 103 2021 / 01 / 18 09:57:32 0 0 0 1147832 2284 474036 0 0 0 0 855 239 79 0 21 0 0 104 2021 / 01 / 18 09:57:33 1 0 0 1147832 2284 474036 0 0 0 67 914 280 82 0 18 0 0 105 2021 / 01 / 18 09:57:34 2 0 0 1147832 2284 474036 0 0 0 0 875 282 78 0 22 0 0 106 2021 / 01 / 18 09:57:35 1 0 0 1147832 2284 474036 0 0 0 0 891 258 81 0 19 0 0 107 2021 / 01 / 18 09:57:36 1 0 0 1147832 2284 474036 0 0 0 0 882 273 79 1 20 0 0 108 2021 / 01 / 18 09:57:37 1 0 0 1147832 2284 474036 0 0 0 0 883 256 80 0 20 0 0 109 2021 / 01 / 18 09:57:38 0 0 0 1147832 2284 474036 0 0 0 0 891 261 80 1 19 0 0 110 2021 / 01 / 18 09:57:39 3 0 0 1147832 2284 474036 0 0 0 0 881 273 78 1 21 0 0 111 2021 / 01 / 18 09:57:40 6 0 0 1147832 2284 474036 0 0 0 0 877 237 80 0 20 0 0 112 2021 / 01 / 18 09:57:41 1 0 0 1147832 2284 474036 0 0 0 0 883 249 79 1 20 0 0 113 2021 / 01 / 18 09:57:42 1 0 0 1147832 2284 474036 0 0 0 0 875 247 81 0 19 0 0 114 2021 / 01 / 18 09:57:43 0 0 0 1147832 2284 474036 0 0 0 0 886 254 81 0 19 0 0 115 2021 / 01 / 18 09:57:44 0 0 0 1147832 2284 474036 0 0 0 0 860 234 79 0 21 0 0 116 2021 / 01 / 18 09:57:45 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 117 2021 / 01 / 18 09:57:45 r b swpd free buff cache si so bi bo in cs us sy id wa st 118 2021 / 01 / 18 09:57:45 2 0 0 1147832 2284 474036 0 0 0 4 893 255 81 0 19 0 0 119 2021 / 01 / 18 09:57:46 2 0 0 1147832 2284 474036 0 0 0 0 881 302 77 1 22 0 0 120 2021 / 01 / 18 09:57:47 1 0 0 1147832 2284 474036 0 0 0 0 893 249 81 0 19 0 0 121 2021 / 01 / 18 09:57:48 1 0 0 1147832 2284 474036 0 0 0 0 866 257 80 0 20 0 0 122 2021 / 01 / 18 09:57:49 1 0 0 1147832 2284 474040 0 0 0 0 875 252 81 0 19 0 0 123 2021 / 01 / 18 09:57:50 0 0 0 1147832 2284 474040 0 0 0 0 870 247 80 0 20 0 0 124 2021 / 01 / 18 09:57:51 1 0 0 1147832 2284 474040 0 0 0 0 861 243 78 2 20 0 0 125 2021 / 01 / 18 09:57:52 0 0 0 1147832 2284 474040 0 0 0 0 861 243 80 0 20 0 0 126 2021 / 01 / 18 09:57:53 3 0 0 1147832 2284 474040 0 0 0 0 865 226 80 0 20 0 0 127 2021 / 01 / 18 09:57:54 1 0 0 1147832 2284 474040 0 0 0 0 871 221 81 0 19 0 0 128 2021 / 01 / 18 09:57:55 0 0 0 1147832 2284 474040 0 0 0 0 868 232 80 0 20 0 0 129 2021 / 01 / 18 09:57:56 1 0 0 1147832 2284 474040 0 0 0 0 879 243 79 1 20 0 0 130 2021 / 01 / 18 09:57:57 0 0 0 1147832 2284 474040 0 0 0 0 857 239 79 1 20 0 0 131 2021 / 01 / 18 09:57:58 1 0 0 1147832 2284 474040 0 0 0 0 876 264 80 0 20 0 0 132 2021 / 01 / 18 09:57:59 4 0 0 1147832 2284 474040 0 0 0 0 897 279 80 0 20 0 0 133 2021 / 01 / 18 09:58:00 3 0 0 1147832 2284 474040 0 0 0 0 875 249 80 0 20 0 0 134 2021 / 01 / 18 09:58:01 1 0 0 1147832 2284 474040 0 0 0 0 904 299 80 1 19 0 0 135 2021 / 01 / 18 09:58:02 2 0 0 1147832 2284 474040 0 0 0 0 867 260 79 0 21 0 0 136 2021 / 01 / 18 09:58:03 1 0 0 1147832 2284 474040 0 0 0 9 870 242 80 0 20 0 0 137 2021 / 01 / 18 09:58:04 1 0 0 1147832 2284 474040 0 0 0 0 863 245 80 0 20 0 0 138 2021 / 01 / 18 09:58:05 2 0 0 1147832 2284 474040 0 0 0 0 881 245 81 0 19 0 0 139 2021 / 01 / 18 09:58:06 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 140 2021 / 01 / 18 09:58:06 r b swpd free buff cache si so bi bo in cs us sy id wa st 141 2021 / 01 / 18 09:58:06 1 0 0 1147832 2284 474040 0 0 0 0 862 232 80 0 20 0 0 142 2021 / 01 / 18 09:58:07 1 0 0 1147832 2284 474040 0 0 0 0 870 269 78 1 21 0 0 143 2021 / 01 / 18 09:58:08 0 0 0 1147832 2284 474040 0 0 0 0 869 231 81 0 19 0 0 144 2021 / 01 / 18 09:58:09 1 0 0 1147832 2284 474040 0 0 0 0 862 230 80 0 20 0 0 145 2021 / 01 / 18 09:58:10 1 0 0 1147832 2284 474040 0 0 0 0 884 250 80 0 20 0 0 146 2021 / 01 / 18 09:58:11 1 0 0 1147832 2284 474040 0 0 0 0 861 239 80 0 20 0 0 147 2021 / 01 / 18 09:58:12 1 0 0 1147832 2284 474040 0 0 0 0 866 243 80 1 19 0 0 148 2021 / 01 / 18 09:58:13 1 0 0 1147832 2284 474040 0 0 0 0 859 228 80 1 19 0 0 149 2021 / 01 / 18 09:58:14 1 0 0 1147832 2284 474040 0 0 0 0 872 252 78 0 22 0 0 150 2021 / 01 / 18 09:58:15 1 0 0 1147832 2284 474040 0 0 0 0 869 232 80 0 20 0 0 151 2021 / 01 / 18 09:58:16 2 0 0 1147832 2284 474040 0 0 0 8 876 246 80 1 19 0 0 152 2021 / 01 / 18 09:58:17 1 0 0 1147832 2284 474040 0 0 0 0 876 234 80 1 19 0 0 153 2021 / 01 / 18 09:58:18 1 0 0 1147832 2284 474040 0 0 0 0 865 262 78 0 22 0 0 154 2021 / 01 / 18 09:58:19 2 0 0 1147832 2284 474040 0 0 0 0 861 231 80 0 20 0 0 155 2021 / 01 / 18 09:58:20 1 0 0 1147832 2284 474040 0 0 0 0 876 262 80 0 20 0 0 156 2021 / 01 / 18 09:58:21 1 0 0 1147832 2284 474040 0 0 0 0 876 242 81 0 19 0 0 157 2021 / 01 / 18 09:58:22 1 0 0 1147832 2284 474040 0 0 0 0 868 241 80 1 19 0 0 158 2021 / 01 / 18 09:58:23 1 0 0 1147832 2284 474040 0 0 0 0 854 230 80 0 20 0 0 159 2021 / 01 / 18 09:58:24 1 0 0 1147832 2284 474040 0 0 0 0 872 237 80 0 20 0 0 160 2021 / 01 / 18 09:58:25 2 0 0 1147832 2284 474040 0 0 0 0 840 208 79 0 21 0 0 161 2021 / 01 / 18 09:58:26 1 0 0 1147832 2284 474040 0 0 0 0 879 232 81 0 19 0 0 162 2021 / 01 / 18 09:58:27 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 163 2021 / 01 / 18 09:58:27 r b swpd free buff cache si so bi bo in cs us sy id wa st 164 2021 / 01 / 18 09:58:27 3 0 0 1147804 2284 474044 0 0 0 0 874 256 78 1 21 0 0 165 2021 / 01 / 18 09:58:28 1 0 0 1147804 2284 474044 0 0 0 0 870 237 81 0 19 0 0 166 2021 / 01 / 18 09:58:29 0 0 0 1147804 2284 474044 0 0 0 0 871 246 81 0 19 0 0 167 2021 / 01 / 18 09:58:30 0 0 0 1147804 2284 474044 0 0 0 0 850 232 79 0 21 0 0 168 2021 / 01 / 18 09:58:31 1 0 0 1147804 2284 474044 0 0 0 0 887 239 81 0 19 0 0 169 2021 / 01 / 18 09:58:32 1 0 0 1147804 2284 474044 0 0 0 0 858 241 78 1 21 0 0 170 2021 / 01 / 18 09:58:33 1 0 0 1147804 2284 474044 0 0 0 0 870 234 81 0 19 0 0 171 2021 / 01 / 18 09:58:34 1 0 0 1147804 2284 474044 0 0 0 2 873 259 80 0 20 0 0 172 2021 / 01 / 18 09:58:35 1 0 0 1147804 2284 474044 0 0 0 0 877 251 80 0 20 0 0 173 2021 / 01 / 18 09:58:36 1 0 0 1147804 2284 474044 0 0 0 0 884 251 80 1 19 0 0 174 2021 / 01 / 18 09:58:37 1 0 0 1147804 2284 474044 0 0 0 0 852 236 78 0 22 0 0 175 2021 / 01 / 18 09:58:38 1 0 0 1147804 2284 474044 0 0 0 0 856 218 79 1 20 0 0 176 2021 / 01 / 18 09:58:39 1 0 0 1147804 2284 474044 0 0 0 0 869 253 81 0 19 0 0 177 2021 / 01 / 18 09:58:40 1 0 0 1147804 2284 474044 0 0 0 0 868 243 79 1 20 0 0 178 2021 / 01 / 18 09:58:41 0 0 0 1147804 2284 474044 0 0 0 0 886 280 81 0 19 0 0 179 2021 / 01 / 18 09:58:42 1 0 0 1147804 2284 474044 0 0 0 0 857 239 79 0 21 0 0 180 2021 / 01 / 18 09:58:43 0 0 0 1147804 2284 474044 0 0 0 0 862 244 79 1 20 0 0 181 2021 / 01 / 18 09:58:44 1 0 0 1147804 2284 474044 0 0 0 0 865 236 80 0 20 0 0 182 2021 / 01 / 18 09:58:45 3 0 0 1147804 2284 474044 0 0 0 0 879 252 81 0 19 0 0 183 2021 / 01 / 18 09:58:46 1 0 0 1147804 2284 474044 0 0 0 0 860 251 80 0 20 0 0 184 2021 / 01 / 18 09:58:47 2 0 0 1147804 2284 474044 0 0 0 8 887 252 80 0 20 0 0 185 2021 / 01 / 18 09:58:48 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 186 2021 / 01 / 18 09:58:48 r b swpd free buff cache si so bi bo in cs us sy id wa st 187 2021 / 01 / 18 09:58:48 1 0 0 1147804 2284 474044 0 0 0 0 857 249 78 1 21 0 0 188 2021 / 01 / 18 09:58:49 1 0 0 1147804 2284 474044 0 0 0 0 883 250 81 0 19 0 0 189 2021 / 01 / 18 09:58:50 1 0 0 1147804 2284 474044 0 0 0 0 851 224 79 0 21 0 0 190 2021 / 01 / 18 09:58:51 4 0 0 1147804 2284 474044 0 0 0 0 881 238 81 0 19 0 0 191 2021 / 01 / 18 09:58:52 1 0 0 1147804 2284 474044 0 0 0 0 860 217 81 0 19 0 0 192 2021 / 01 / 18 09:58:53 0 0 0 1147804 2284 474044 0 0 0 0 836 215 78 1 21 0 0 193 2021 / 01 / 18 09:58:54 2 0 0 1147804 2284 474044 0 0 0 0 873 225 81 0 19 0 0 194 2021 / 01 / 18 09:58:55 0 0 0 1147804 2284 474044 0 0 0 0 857 232 79 1 20 0 0 195 2021 / 01 / 18 09:58:56 1 0 0 1147804 2284 474044 0 0 0 0 854 239 79 0 21 0 0 196 2021 / 01 / 18 09:58:57 1 0 0 1147804 2284 474044 0 0 0 0 875 234 81 0 19 0 0 197 2021 / 01 / 18 09:58:58 1 0 0 1147804 2284 474044 0 0 0 0 863 257 79 1 20 0 0 198 2021 / 01 / 18 09:58:59 1 0 0 1147804 2284 474044 0 0 0 0 857 201 81 0 19 0 0 199 2021 / 01 / 18 09:59:00 0 0 0 1147804 2284 474044 0 0 0 0 855 242 78 0 22 0 0 200 2021 / 01 / 18 09:59:01 2 0 0 1147804 2284 474044 0 0 0 0 873 247 80 0 20 0 0 201 2021 / 01 / 18 09:59:02 0 0 0 1147804 2284 474044 0 0 0 0 862 228 81 0 19 0 0 202 2021 / 01 / 18 09:59:03 2 0 0 1147804 2284 474048 0 0 0 0 868 238 79 1 20 0 0 203 2021 / 01 / 18 09:59:04 6 0 0 1147804 2284 474048 0 0 0 2 872 202 80 1 19 0 0 204 2021 / 01 / 18 09:59:05 0 0 0 1147804 2284 474048 0 0 0 0 857 225 79 0 21 0 0 205 2021 / 01 / 18 09:59:06 5 0 0 1147804 2284 474048 0 0 0 0 876 230 81 0 19 0 0 206 2021 / 01 / 18 09:59:07 2 0 0 1147804 2284 474048 0 0 0 0 861 245 79 0 21 0 0 207 2021 / 01 / 18 09:59:08 1 0 0 1147804 2284 474048 0 0 0 0 870 249 80 1 19 0 0 208 2021 / 01 / 18 09:59:09 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 209 2021 / 01 / 18 09:59:09 r b swpd free buff cache si so bi bo in cs us sy id wa st 210 2021 / 01 / 18 09:59:09 3 0 0 1147804 2284 474048 0 0 0 0 874 245 79 0 21 0 0 211 2021 / 01 / 18 09:59:10 1 0 0 1147772 2284 474048 0 0 0 0 865 226 81 0 19 0 0 212 2021 / 01 / 18 09:59:11 0 0 0 1147772 2284 474048 0 0 0 0 852 235 80 0 20 0 0 213 2021 / 01 / 18 09:59:12 1 0 0 1147772 2284 474048 0 0 0 0 866 247 79 0 21 0 0 214 2021 / 01 / 18 09:59:13 1 0 0 1147772 2284 474048 0 0 0 0 868 237 80 0 20 0 0 215 2021 / 01 / 18 09:59:14 2 0 0 1147772 2284 474048 0 0 0 0 876 239 80 1 19 0 0 216 2021 / 01 / 18 09:59:15 1 0 0 1147772 2284 474048 0 0 0 0 868 232 80 0 20 0 0 217 2021 / 01 / 18 09:59:16 0 0 0 1147772 2284 474048 0 0 0 0 870 235 80 1 19 0 0 218 2021 / 01 / 18 09:59:17 1 0 0 1147772 2284 474048 0 0 0 0 867 222 79 1 20 0 0 219 2021 / 01 / 18 09:59:18 0 0 0 1147772 2284 474048 0 0 0 8 872 264 79 0 21 0 0 220 2021 / 01 / 18 09:59:19 1 0 0 1147772 2284 474048 0 0 0 0 867 235 79 1 20 0 0 221 2021 / 01 / 18 09:59:20 1 0 0 1147772 2284 474048 0 0 0 0 875 230 81 0 19 0 0 222 2021 / 01 / 18 09:59:21 2 0 0 1147772 2284 474048 0 0 0 0 865 248 80 0 20 0 0 223 2021 / 01 / 18 09:59:22 1 0 0 1147772 2284 474048 0 0 0 0 864 205 81 0 19 0 0 224 2021 / 01 / 18 09:59:23 0 0 0 1147772 2284 474048 0 0 0 0 848 233 78 0 22 0 0 225 2021 / 01 / 18 09:59:24 1 0 0 1147772 2284 474048 0 0 0 0 866 230 80 1 19 0 0 226 2021 / 01 / 18 09:59:25 1 0 0 1147772 2284 474048 0 0 0 0 849 221 79 0 21 0 0 227 2021 / 01 / 18 09:59:26 1 0 0 1147772 2284 474048 0 0 0 0 894 259 81 0 19 0 0 228 2021 / 01 / 18 09:59:27 1 0 0 1147772 2284 474048 0 0 0 0 871 234 81 0 19 0 0 229 2021 / 01 / 18 09:59:28 0 0 0 1147772 2284 474048 0 0 0 0 844 232 79 0 21 0 0 230 2021 / 01 / 18 09:59:29 0 0 0 1147772 2284 474048 0 0 0 0 886 251 81 0 19 0 0 231 2021 / 01 / 18 09:59:30 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 232 2021 / 01 / 18 09:59:30 r b swpd free buff cache si so bi bo in cs us sy id wa st 233 2021 / 01 / 18 09:59:30 1 0 0 1147772 2284 474048 0 0 0 0 854 244 78 1 21 0 0 234 2021 / 01 / 18 09:59:31 1 0 0 1147772 2284 474048 0 0 0 0 877 259 81 0 19 0 0 235 2021 / 01 / 18 09:59:32 1 0 0 1147772 2284 474048 0 0 0 0 868 237 80 0 20 0 0 236 2021 / 01 / 18 09:59:33 3 0 0 1147772 2284 474048 0 0 0 0 875 250 80 0 20 0 0 237 2021 / 01 / 18 09:59:34 1 0 0 1147772 2284 474048 0 0 0 3 899 295 81 0 19 0 0 238 2021 / 01 / 18 09:59:35 1 0 0 1147772 2284 474048 0 0 0 0 854 236 77 1 22 0 0 239 2021 / 01 / 18 09:59:36 1 0 0 1147772 2284 474048 0 0 0 0 867 238 81 0 19 0 0 240 2021 / 01 / 18 09:59:37 3 0 0 1147772 2284 474048 0 0 0 0 871 244 79 1 20 0 0 241 2021 / 01 / 18 09:59:38 1 0 0 1147772 2284 474048 0 0 0 0 876 251 80 0 20 0 0 242 2021 / 01 / 18 09:59:39 1 0 0 1147772 2284 474048 0 0 0 0 876 247 81 0 19 0 0 243 2021 / 01 / 18 09:59:40 0 0 0 1147772 2284 474052 0 0 0 0 851 226 79 1 20 0 0 244 2021 / 01 / 18 09:59:41 0 0 0 1147772 2284 474052 0 0 0 0 886 270 81 0 19 0 0 245 2021 / 01 / 18 09:59:42 4 0 0 1147772 2284 474052 0 0 0 0 847 217 78 0 22 0 0 246 2021 / 01 / 18 09:59:43 1 0 0 1147772 2284 474052 0 0 0 0 867 236 80 1 19 0 0 247 2021 / 01 / 18 09:59:44 1 0 0 1147772 2284 474052 0 0 0 0 854 233 79 0 21 0 0 248 2021 / 01 / 18 09:59:45 4 0 0 1147772 2284 474052 0 0 0 0 886 246 80 1 19 0 0 249 2021 / 01 / 18 09:59:46 0 0 0 1147772 2284 474052 0 0 0 0 875 246 81 0 19 0 0 250 2021 / 01 / 18 09:59:47 1 0 0 1147772 2284 474052 0 0 0 0 880 280 79 0 21 0 0 251 2021 / 01 / 18 09:59:48 2 0 0 1147772 2284 474052 0 0 0 0 872 247 79 0 21 0 0 252 2021 / 01 / 18 09:59:49 2 0 0 1147772 2284 474052 0 0 0 8 886 260 81 0 19 0 0 253 2021 / 01 / 18 09:59:50 2 0 0 1147772 2284 474052 0 0 0 0 884 242 80 1 19 0 0 254 2021 / 01 / 18 09:59:51 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 255 2021 / 01 / 18 09:59:51 r b swpd free buff cache si so bi bo in cs us sy id wa st 256 2021 / 01 / 18 09:59:51 2 0 0 1147772 2284 474052 0 0 0 0 864 237 78 0 22 0 0 257 2021 / 01 / 18 09:59:52 0 0 0 1147772 2284 474052 0 0 0 0 859 216 81 0 19 0 0 258 2021 / 01 / 18 09:59:53 1 0 0 1147772 2284 474052 0 0 0 0 877 255 80 0 20 0 0 259 2021 / 01 / 18 09:59:54 1 0 0 1147772 2284 474052 0 0 0 0 869 235 81 0 19 0 0 260 2021 / 01 / 18 09:59:55 1 0 0 1147772 2284 474052 0 0 0 0 866 237 79 1 20 0 0 261 2021 / 01 / 18 09:59:56 1 0 0 1147772 2284 474052 0 0 0 0 879 278 79 1 20 0 0 262 2021 / 01 / 18 09:59:58 1 0 0 1147772 2284 474052 0 0 0 0 864 232 80 1 19 0 0 263 2021 / 01 / 18 09:59:59 3 0 0 1147772 2284 474052 0 0 0 0 871 267 78 0 22 0 0 264 2021 / 01 / 18 10:00:00 1 0 0 1147772 2284 474052 0 0 0 0 877 252 81 0 19 0 0 265 2021 / 01 / 18 10:00:01 4 0 0 1147772 2284 474052 0 0 0 0 878 263 79 1 20 0 0 266 2021 / 01 / 18 10:00:02 4 0 0 1147772 2284 474052 0 0 0 0 908 286 81 0 19 0 0 267 2021 / 01 / 18 10:00:03 2 0 0 1147772 2284 474052 0 0 0 0 863 242 79 0 21 0 0 268 2021 / 01 / 18 10:00:04 1 0 0 1147772 2284 474052 0 0 0 0 874 234 80 1 19 0 0 269 2021 / 01 / 18 10:00:05 2 0 0 1147772 2284 474052 0 0 0 4 872 240 81 0 19 0 0 270 2021 / 01 / 18 10:00:06 0 0 0 1147772 2284 474052 0 0 0 0 861 269 78 0 22 0 0 271 2021 / 01 / 18 10:00:07 1 0 0 1147772 2284 474052 0 0 0 0 884 260 81 0 19 0 0 272 2021 / 01 / 18 10:00:08 2 0 0 1147772 2284 474052 0 0 0 0 894 275 81 0 19 0 0 273 2021 / 01 / 18 10:00:09 0 0 0 1147772 2284 474052 0 0 0 0 845 245 77 1 22 0 0 274 2021 / 01 / 18 10:00:10 0 0 0 1147772 2284 474052 0 0 0 0 882 280 81 0 19 0 0 275 2021 / 01 / 18 10:00:11 1 0 0 1147772 2284 474052 0 0 0 0 867 228 80 0 20 0 0 276 2021 / 01 / 18 10:00:12 1 0 0 1147772 2284 474052 0 0 0 0 873 240 80 0 20 0 0 277 2021 / 01 / 18 10:00:13 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 278 2021 / 01 / 18 10:00:13 r b swpd free buff cache si so bi bo in cs us sy id wa st 279 2021 / 01 / 18 10:00:13 3 0 0 1147772 2284 474052 0 0 0 0 885 245 80 1 19 0 0 280 2021 / 01 / 18 10:00:14 1 0 0 1147772 2284 474052 0 0 0 0 852 232 78 2 20 0 0 281 2021 / 01 / 18 10:00:15 2 0 0 1147772 2284 474052 0 0 0 0 881 242 80 0 20 0 0 282 2021 / 01 / 18 10:00:16 0 0 0 1147772 2284 474052 0 0 0 0 870 286 79 0 21 0 0 283 2021 / 01 / 18 10:00:17 1 0 0 1147772 2284 474056 0 0 0 0 869 226 81 0 19 0 0 284 2021 / 01 / 18 10:00:18 2 0 0 1147740 2284 474056 0 0 0 0 871 249 78 1 21 0 0 285 2021 / 01 / 18 10:00:19 1 0 0 1147740 2284 474056 0 0 0 0 872 242 81 0 19 0 0 286 2021 / 01 / 18 10:00:20 2 0 0 1147740 2284 474056 0 0 0 0 864 241 81 0 19 0 0 287 2021 / 01 / 18 10:00:21 0 0 0 1147740 2284 474056 0 0 0 8 876 291 79 0 21 0 0 288 2021 / 01 / 18 10:00:22 1 0 0 1147740 2284 474056 0 0 0 0 868 220 81 0 19 0 0 289 2021 / 01 / 18 10:00:23 0 0 0 1147740 2284 474056 0 0 0 0 864 229 79 1 20 0 0 290 2021 / 01 / 18 10:00:24 1 0 0 1147740 2284 474056 0 0 0 0 854 240 80 0 20 0 0 291 2021 / 01 / 18 10:00:25 4 0 0 1147740 2284 474056 0 0 0 0 869 245 80 0 20 0 0 292 2021 / 01 / 18 10:00:26 1 0 0 1147740 2284 474056 0 0 0 0 863 231 80 0 20 0 0 293 2021 / 01 / 18 10:00:27 2 0 0 1147740 2284 474056 0 0 0 0 880 237 81 0 19 0 0 294 2021 / 01 / 18 10:00:28 2 0 0 1147740 2284 474056 0 0 0 0 864 253 77 1 22 0 0 295 2021 / 01 / 18 10:00:29 1 0 0 1147740 2284 474056 0 0 0 0 876 236 81 0 19 0 0 296 2021 / 01 / 18 10:00:30 2 0 0 1147740 2284 474056 0 0 0 0 862 229 80 0 20 0 0 297 2021 / 01 / 18 10:00:31 1 0 0 1147740 2284 474056 0 0 0 0 873 236 81 0 19 0 0 298 2021 / 01 / 18 10:00:32 0 0 0 1147740 2284 474056 0 0 0 0 853 215 80 0 20 0 0 299 2021 / 01 / 18 10:00:33 1 0 0 1147740 2284 474056 0 0 0 0 855 230 77 2 21 0 0 300 2021 / 01 / 18 10:00:34 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 301 2021 / 01 / 18 10:00:34 r b swpd free buff cache si so bi bo in cs us sy id wa st 302 2021 / 01 / 18 10:00:34 1 0 0 1147740 2284 474056 0 0 0 0 857 241 80 0 20 0 0 303 2021 / 01 / 18 10:00:35 1 0 0 1147740 2284 474056 0 0 0 47 884 256 79 1 20 0 0 304 2021 / 01 / 18 10:00:36 1 0 0 1147740 2284 474056 0 0 0 0 877 253 81 0 19 0 0 305 2021 / 01 / 18 10:00:37 1 0 0 1147740 2284 474056 0 0 0 0 867 249 80 0 20 0 0 306 2021 / 01 / 18 10:00:38 1 0 0 1147740 2284 474056 0 0 0 0 875 254 79 1 20 0 0 307 2021 / 01 / 18 10:00:39 1 0 0 1147740 2284 474056 0 0 0 0 872 231 81 0 19 0 0 308 2021 / 01 / 18 10:00:40 1 0 0 1147740 2284 474056 0 0 0 0 848 256 79 0 21 0 0 309 2021 / 01 / 18 10:00:41 0 0 0 1147740 2284 474056 0 0 0 0 874 253 81 0 19 0 0 310 2021 / 01 / 18 10:00:42 1 0 0 1147740 2284 474056 0 0 0 0 853 237 79 0 21 0 0 311 2021 / 01 / 18 10:00:43 1 0 0 1147740 2284 474056 0 0 0 0 874 243 80 1 19 0 0 312 2021 / 01 / 18 10:00:44 5 0 0 1147740 2284 474056 0 0 0 0 881 254 80 0 20 0 0 313 2021 / 01 / 18 10:00:45 1 0 0 1147740 2284 474056 0 0 0 0 870 252 80 0 20 0 0 314 2021 / 01 / 18 10:00:46 1 0 0 1147740 2284 474056 0 0 0 0 862 237 81 0 19 0 0 315 2021 / 01 / 18 10:00:47 0 0 0 1147740 2284 474056 0 0 0 0 886 284 79 1 20 0 0 316 2021 / 01 / 18 10:00:48 0 0 0 1147740 2284 474056 0 0 0 0 862 246 80 0 20 0 0 317 2021 / 01 / 18 10:00:49 1 0 0 1147740 2284 474056 0 0 0 0 873 245 79 1 20 0 0 318 2021 / 01 / 18 10:00:50 0 0 0 1147740 2284 474056 0 0 0 0 865 241 81 0 19 0 0 319 2021 / 01 / 18 10:00:51 1 0 0 1147740 2284 474056 0 0 0 0 853 231 77 1 22 0 0 320 2021 / 01 / 18 10:00:52 0 0 0 1147740 2284 474056 0 0 0 4 877 246 80 1 19 0 0 321 2021 / 01 / 18 10:00:53 1 0 0 1147740 2284 474056 0 0 0 0 858 243 80 0 20 0 0 322 2021 / 01 / 18 10:00:54 1 0 0 1147740 2284 474056 0 0 0 0 876 241 80 0 20 0 0 323 2021 / 01 / 18 10:00:55 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 324 2021 / 01 / 18 10:00:55 r b swpd free buff cache si so bi bo in cs us sy id wa st 325 2021 / 01 / 18 10:00:55 2 0 0 1147740 2284 474060 0 0 0 0 853 204 81 0 19 0 0 326 2021 / 01 / 18 10:00:56 1 0 0 1147740 2284 474060 0 0 0 0 870 248 79 1 20 0 0 327 2021 / 01 / 18 10:00:57 1 0 0 1147740 2284 474060 0 0 0 0 868 232 81 0 19 0 0 328 2021 / 01 / 18 10:00:58 0 0 0 1147740 2284 474060 0 0 0 0 852 241 78 0 22 0 0 329 2021 / 01 / 18 10:00:59 1 0 0 1147740 2284 474060 0 0 0 0 866 242 81 0 19 0 0 330 2021 / 01 / 18 10:01:00 1 0 0 1147740 2284 474060 0 0 0 0 867 238 80 0 20 0 0 331 2021 / 01 / 18 10:01:01 1 0 0 1147740 2284 474060 0 0 0 0 868 234 79 1 20 0 0 332 2021 / 01 / 18 10:01:02 0 0 0 1147592 2284 474068 0 0 0 0 873 304 79 2 19 0 0 333 2021 / 01 / 18 10:01:03 1 0 0 1147592 2284 474068 0 0 0 0 886 247 82 0 18 0 0 334 2021 / 01 / 18 10:01:04 1 0 0 1147592 2284 474068 0 0 0 0 856 228 81 0 19 0 0 335 2021 / 01 / 18 10:01:05 1 0 0 1147592 2284 474068 0 0 0 10 850 232 77 1 22 0 0 336 2021 / 01 / 18 10:01:06 0 0 0 1147592 2284 474068 0 0 0 0 164 270 4 0 96 0 0 337 2021 / 01 / 18 10:01:07 0 0 0 1147592 2284 474068 0 0 0 0 133 290 0 1 99 0 0 338 2021 / 01 / 18 10:01:08 0 0 0 1147592 2284 474068 0 0 0 0 143 313 0 0 100 0 0 339 2021 / 01 / 18 10:01:09 0 0 0 1147592 2284 474068 0 0 0 0 126 274 0 1 99 0 0 340 2021 / 01 / 18 10:01:10 0 0 0 1147592 2284 474068 0 0 0 0 121 264 0 0 100 0 0 341 2021 / 01 / 18 10:01:11 0 0 0 1147592 2284 474068 0 0 0 0 125 268 0 0 100 0 0 342 2021 / 01 / 18 10:01:12 0 0 0 1147592 2284 474068 0 0 0 0 120 269 0 0 100 0 0 343 2021 / 01 / 18 10:01:13 1 0 0 1147592 2284 474068 0 0 0 0 107 230 0 0 100 0 0 344 2021 / 01 / 18 10:01:14 0 0 0 1147592 2284 474068 0 0 0 0 108 244 1 0 99 0 0 345 2021 / 01 / 18 10:01:15 0 0 0 1147560 2284 474068 0 0 0 0 112 243 0 0 100 0 0 346 2021 / 01 / 18 10:01:16 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 347 2021 / 01 / 18 10:01:16 r b swpd free buff cache si so bi bo in cs us sy id wa st 348 2021 / 01 / 18 10:01:16 1 0 0 1147560 2284 474068 0 0 0 0 116 260 0 0 100 0 0 349 2021 / 01 / 18 10:01:17 0 0 0 1147560 2284 474068 0 0 0 0 122 265 0 0 100 0 0 350 2021 / 01 / 18 10:01:18 0 0 0 1147560 2284 474068 0 0 0 0 114 255 0 0 100 0 0 351 2021 / 01 / 18 10:01:19 0 0 0 1147560 2284 474068 0 0 0 0 149 316 0 0 100 0 0 352 2021 / 01 / 18 10:01:20 0 0 0 1147560 2284 474068 0 0 0 0 147 321 0 1 99 0 0 353 2021 / 01 / 18 10:01:21 1 0 0 1147560 2284 474068 0 0 0 0 146 318 0 0 100 0 0 354 2021 / 01 / 18 10:01:22 0 0 0 1147560 2284 474068 0 0 0 0 133 294 0 0 100 0 0 355 2021 / 01 / 18 10:01:23 0 0 0 1147560 2284 474068 0 0 0 8 130 281 0 0 100 0 0 356 2021 / 01 / 18 10:01:24 0 0 0 1147560 2284 474068 0 0 0 0 118 254 1 1 98 0 0 357 2021 / 01 / 18 10:01:25 0 0 0 1147560 2284 474068 0 0 0 0 111 246 0 0 100 0 0 358 2021 / 01 / 18 10:01:26 0 0 0 1147560 2284 474068 0 0 0 0 125 275 0 0 100 0 0 359 2021 / 01 / 18 10:01:27 0 0 0 1147560 2284 474068 0 0 0 0 138 297 0 1 99 0 0 360 2021 / 01 / 18 10:01:28 0 0 0 1147560 2284 474068 0 0 0 0 115 256 0 0 100 0 0 361 2021 / 01 / 18 10:01:29 0 0 0 1147560 2284 474068 0 0 0 0 114 250 0 0 100 0 0 362 2021 / 01 / 18 10:01:30 0 0 0 1147560 2284 474068 0 0 0 0 128 280 0 0 100 0 0 363 2021 / 01 / 18 10:01:31 0 0 0 1147560 2284 474072 0 0 0 0 121 269 0 0 100 0 0 364 2021 / 01 / 18 10:01:32 0 0 0 1147560 2284 474072 0 0 0 0 99 220 0 0 100 0 0 365 2021 / 01 / 18 10:01:33 0 0 0 1147560 2284 474072 0 0 0 0 111 240 0 0 100 0 0 366 2021 / 01 / 18 10:01:34 0 0 0 1147560 2284 474072 0 0 0 0 130 282 0 0 100 0 0 367 2021 / 01 / 18 10:01:35 0 0 0 1147560 2284 474072 0 0 0 50 112 239 0 0 100 0 0 368 2021 / 01 / 18 10:01:36 0 0 0 1147560 2284 474072 0 0 0 0 130 282 0 0 100 0 0 実務でよく使用されるのが「r(実行中と実行待ち中のプロセス数の合計)の欄」と「CPU」の欄であるため、今回はその二つの平均を awk を用いて算出する。 「rの平均(プロセスの平均)」 awk ' (NR % 23 < 1 ) || (NR % 23 > 2) {sum += $3; count +=1} END{print "プロセス数合計:"sum, "プロセス数平均:"sum/count} ' vmstat_0956_1001.log ※「vmstat_0956_1001.log」はログファイル名 # 結果 プロセス数合計: 363 プロセス数平均: 1 . 08036 「CPUの各情報毎の平均」 # us(カーネルコード以外の実行に使用した時間) awk ' (NR % 23 < 1 ) || (NR % 23 > 2) {sumUs += $15; count +=1} END{print "実行に使用した時間の合計:"sumUs, "実行に使用した時間の平均:"sumUs/count} ' vmstat_0956_1001.log # 結果 実行に使用した時間の合計: 23939 実行に使用した時間の平均: 71 . 247 # sy(カーネルコード以外の実行に使用した時間) awk ' (NR % 23 < 1 ) || (NR % 23 > 2) {sumSy += $16; count +=1} END{print "実行に使用した時間の合計:"sumSy, "実行に使用した時間の平均:"sumSy/count} ' vmstat_0956_1001.log # 結果 実行に使用した時間の合計: 100 実行に使用した時間の平均: 0 . 297619 # id(アイドル時間) awk ' (NR % 23 < 1 ) || (NR % 23 > 2) {sumId += $17; count +=1} END{print "アイドル時間の合計:"sumId, "アイドル時間の平均:"sumId/count} ' vmstat_0956_1001.log # 結果 アイドル時間の合計: 9561 アイドル時間の平均: 28 . 4554 # wa(I/O待ち時間) awk ' (NR % 23 < 1 ) || (NR % 23 > 2) {sumWa += $18; count +=1} END{print "I/O待ち時間の合計:"sumWa, "I/O待ち時間の平均:"sumWa/count} ' vmstat_0956_1001.log # 結果 I/O待ち時間の合計: 0 I/O待ち時間の平均: 0 # st(CPUリソースを割当ててもらえなかった時間の割合) awk ' (NR % 23 < 1 ) || (NR % 23 > 2) {sumSt += $19; count +=1} END{print "CPUリソースを割当ててもらえなかった時間の割合の合計:"sumSt, "CPUリソースを割当ててもらえなかった時間の割合の平均:"sumSt/count} ' vmstat_0956_1001.log # 結果 CPUリソースを割当ててもらえなかった時間の割合の合計: 0 CPUリソースを割当ててもらえなかった時間の割合の平均: 0 目次へ おわりに 今回は awk コマンドについての説明を執筆させていただきました。 awk の魅力が少しでも伝わっていれば幸いです。少しでも興味を持った方はとてもとっつきやすいので触ってみてはどうでしょうか。解説に関しては長々となってしまい申し訳ありません。本当を言えば筆者の書きたいことはまだまだあるのですが、これ以上長くなってしまうのは忍びないのでこのあたりで〆させていただきます。ご高覧ありがとうございました。 また、 Linux コマンドの一覧表を以下ブログにてまとめておりますので、ご参考ください。 よく使うLinuxコマンド一覧【最新版】 Linux の理解をより深めたい方へ以下関連おすすめブログ ・ ls コマンド 【使い方 まとめ】 ・ find コマンド 【使い方 まとめ】 ・ iptables まとめ【Linux ファイアウォール】 ・ sed コマンド【使い方 まとめ】 ・ vi コマンド【使い方まとめ】 ・ Linuxのファイル操作でよく使うLinuxコマンド ・ 実務で使える!基本的なシェル(Linux)コマンドの話 ~forとsed~ ・ 【Linux】今振り返りたい、プロセスって何?   エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 https://rakus.hubspotpagebuilder.com/visit_engineer/ rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
はじめに 感想 ドメイン駆動設計との出会い 今ではそんなに悪い奴ではないかなと思えるように 知見 なぜドメイン駆動設計は難しく感じられるのか 原典の重厚さ 導入タイミングの難しさ ドメインエキスパートの協力が得られない ドメインモデルは育てるもの 自社サービスにおけるドメインの捉え方 アーキテクチャには適切なフェーズがある これからドメイン駆動設計を実践する方へ 初めは軽量DDDからでも良い すでにある程度開発が進んでおり、ドメイン知識と技術的負債をコードがたっぷり蓄えているプロジェクト これから立ち上げるプロジェクト おすすめはユビキタス言語から いかにしてドメイン知識を得るか 最後に はじめに こんにちは。logyです。 私は前職で一年と少し、 ラク スに入社してから一年間 ドメイン 駆動設計に関連する開発に関わってきました。 今回は、そこから得られた知見や感想、また、これから ドメイン 駆動設計を実践する方におすすめの方法について書こうと思います。 感想 ドメイン 駆動設計との出会い 私が ドメイン 駆動設計に出会ったのは、前職での部署異動がきっかけでした。 新しく関わることになるプロジェクトが ドメイン 駆動設計を採用しており、当然、メンバーになった私もその思想を習得する必要があったのですが、 当時、まだ オブジェクト指向 ですらあまりしっくりと来ていなかった私にとって、分厚い エヴァ ンス本 *1 は解読困難な古文書のようでした。 並行して実践 ドメイン 駆動設計も読み始めましたが、こちらはまだ幾分わかりやすかった気がします。 そのプロジェクトは所謂業務システムとは少し異なる抽象的な領域をターゲットにしており、 ドメイン 自体を理解するのも非常に難易度が高かったと思います。 一方で、戦術的設計が至るところで用いられており、今思えば、実践 ドメイン 駆動設計を辞書代わりにコードリーディングを行うには最高の環境でした。 そんな環境で1年ほど過ごして様々なノウハウを身に着けていきました。 今ではそんなに悪い奴ではないかなと思えるように ドメイン 駆動設計に出会ってから2年以上経った今でも、「完全に理解した」とは到底言えず、むしろ「全くわからない」状態に近いのが正直なところです。 しかし、これまで目にしてきたような、すっかり ドメイン が流出してしまっており、何度も ヒアリ ングを行い想像を重ねることでやっと理解できるようなあのシステム達も、 ドメイン 駆動設計を取り入れれば、もしかしたら救ってあげられるのかも、と思うようになったり、実装を進める際にはこれは果たして ドメイン の関心事だろうか、と意識するようになりました。 。 当然 ドメイン 駆動設計も 銀の弾丸 ではありませんが、うまく使えば、複雑なシステムに立ち向かうための強力な戦力になってくれるはずです。 知見 なぜ ドメイン 駆動設計は難しく感じられるのか 最近はいろんな記事などで触れられることが多い ドメイン 駆動設計ですが、その内容もさることながら、よく同時に語られるのがその難しさについてです。 導入を試みたが、難しすぎて駄目だった、思ったような効果が得られなかったといった声をよく耳にします。 なぜこのようなことになってしまうのでしょうか。私は次の3つが大きな原因ではないかと考えています。 原典の重厚さ その当時の私も同じくこれに心が折られました。 頑張って読み進めてもなかなか頭に入ってこない。 原典で語られている話は抽象的なものが多く、一読しただけでは「じゃあ、どうすれば?」となりがちです。 特に初学者の場合は、実践 ドメイン 駆動設計から読むことをおすすめします。 最近は他にも初学者向けに日本語で書かれたものがいくつか出ているので、分厚い本に抵抗感のある方はそちらから入っても良いかもしません。 ドメイン 駆動設計を学べる書籍について、別の ラク スエンジニアがまとめた記事がありますので、こちらもどうぞ。 tech-blog.rakus.co.jp 導入タイミングの難しさ 正直言って、 ドメイン 駆動設計を導入する際の初期コストは大きいです。 ドメイン モデリング を行うコストを払う必要があったり、大量の ドメイン クラスを作ることで実装コストも膨らみます。 その分、保守コストを削減できるのがメリットなのですが、その効果を実感できるのは、ある程度システムが複雑化してからになるため、 開発初期の段階で導入判断を行うのは難しいのではないでしょうか。 一方で、すでに複雑化してしまったシステムに、徐々に ドメイン 駆動設計を適用することも、かなり骨の折れる作業となり、導入を妨げている要因といえそうです。 ドメイン エキスパートの協力が得られない ドメイン 駆動設計の導入に際して、一番のハードルと言っても良いのではないでしょうか。 ビジネスサイドと開発サイドが肩を並べて隣で仕事をしているような現場であれば、大きな問題にはならないですが、 サイロ化が進んでいる組織では、定期的に時間を割いてもらうのがやっとで、必要なときに十分な協力を得られないことがよくあります。 たとえ、開発サイドが ドメイン 駆動設計の導入に意気込んでいたとしても、ビジネスサイドの理解が得られず、いつの間にか自然消滅…なんてことにも。 ドメイン 駆動設計の文脈から外れてしまうため、このあたりにしておきますが、組織に関する問題は、 システム開発 につきものです。 *2 幸い、 ラク スでは、ビジネスサイドはもちろん、実際のユーザーでもあるコーポレート部門の方たちにも積極的に協力いただきながら開発を進めることができています。 非常に恵まれた環境で開発を進められてることに、この場を借りて感謝したいと思います。 ドメイン モデルは育てるもの とりあえず モデリング をやってみたはいいものの、あまりしっくりこなかったり、すぐに実状と合わなくなってしまったという経験をお持ちの方も多いのではないでしょうか。 しかし、そこで諦めてはいけません。むしろそこからモデルを進化させ続けることこそ ドメイン 駆動設計の醍醐味です。 特にプロジェクト初期のように、業務理解が浅いうちは、それ相応のモデルしか作成できないはずです。 しかし、 ドメイン モデリング を行うことそれ自体が、 ドメイン へのより深い理解を促し、新たな概念の発見を通じて、既存のモデルをより洗練されたモデルへと進化させます。 自社サービスにおける ドメイン の捉え方 ラク スのように自社サービスを開発している現場では、 ドメイン を分析する際に業務 ドメイン とはまた違った難しさが存在します。 それは ドメイン がすぐに変化しやすいという点です。 SaaS の開発では、数多くのお客様に使っていただくため、ある程度、どの現場でも共通する業務をターゲットに開発を行います。 つまり、製品が扱う ドメイン としては、特定のお客様の ドメイン ではなく、ある程度、最大公約数的なものをイメージして定義することになります。 それぞれ微妙に異なる ドメイン すると、「このお客様の現場では正しいけど、別の現場では不適切」となるような ドメイン 知識を得ることもあり、製品としてどうあるべきか常に折り合いをつけ続ける必要があります。 サービスが成長し続ける限り、その検討範囲は拡大し、時折自己矛盾を生むこともあるでしょう。 それらを反映した ドメイン モデルを維持し続けることの大変さは、想像に難くないはずです。 また、これまで存在しなかったような、革新的な機能を提供するサービスでは、そもそも新たな ドメイン そのものを作り出す作業が必要となるため、これもまた大変な仕事になりそうです。 アーキテクチャ には適切なフェーズがある 実践 ドメイン 駆動設計で触れられているような、CQRS+ESといった アーキテクチャ は、複雑なシステムを制御する手段として有効です。 私は実際にこれを採用しているプロジェクトに関わったこともありますが、確かに ドメイン イベントとイベントソーシングの相性は抜群で、どんな要件にも柔軟に対応できるのではという気持ちにもなりました。 集約の設計を突き詰めると、そのうちCQRS+ESにたどり着くといった話も時折耳にします。 しかし、あくまでそれは、そのプロジェクトがいくつもの検討の末にたどり着いた解決手段の一つであるということを忘れてはいけません。 プロジェクトの初期から「DDDをやるならCQRS+ESで決まりでしょ!」みたいな発想で初めるのは明らかに アンチパターン です。 私が関わったプロジェクトでも、初めからCQRS+ESが採用されていたわけではなく、発展を続けるうちに、いろんなパターンを経てたどり着いた、とのことでした。 RDSの限界やNoSQLの発展がCQRS+ESを生み出したように、別の技術の発展がそのうちまた新たな方式の アーキテクチャ を生み、発展させていくのでしょう。 現行の アーキテクチャ が将来の発展に耐えられそうにないと判断したとき、課題に応じた解決策を選択できるようにしたいですね。 これから ドメイン 駆動設計を実践する方へ 初めは軽量DDDからでも良い 所謂、軽量DDDは アンチパターン と言われることが多いですが、個人的には、初めは軽量DDDから導入を進めるのも良い選択だと思います。 というのも、上記で述べたように、 ドメイン 駆動設計は導入、学習コストが非常に高く付く点がネックです。 そこで、戦術的設計を先に導入することで、徐々に理解を深め、最終的に戦略的設計の適用を目指せば、初期コストを低く抑えつつ導入を進められます。 また、評価の結果、 ドメイン 駆動設計がプロジェクトに合わないと判断された場合でも、戦術的設計は オブジェクト指向設計 の1パターンとしてその先も利用でき、負債になりづらいです。 とはいえ、将来的に戦略的設計を全く採用する気がないのであれば、 ドメイン 駆動設計の導入はおすすめしません。 様々な記事で触れられているように、戦術的設計はあくまで ドメイン と向き合うための足掛かりとなる手段であり、最終的には ドメイン を通じてソフトウェアの価値を高めることが ドメイン 駆動設計の目的だからです。 そこで、おすすめしたいのは、次のような導入方法です。 すでにある程度開発が進んでおり、 ドメイン 知識と技術的負債をコードがたっぷり蓄えているプロジェクト 戦術的設計(軽量DDD)を用いて、既存のコードを整理し、 ドメイン 知識を抽出する。 DDDに慣れてきたら戦略的設計を適用してみる。 これから立ち上げるプロジェクト 戦略的設計を積極的に適用し、 ドメイン モデルと共に成長を目指す。 おすすめは ユビキタス 言語から 仮に戦略的設計を導入することになった場合、まずは ユビキタス 言語の徹底から始めることをおすすめします。 通常の システム開発 でも、用語集や辞書といったものを用いて用語の統一を図ることが多いですね。 しかし、 ユビキタス 言語は単なる用語集づくりではありません。 ユビキタス 言語の特徴としては、統一した用語を開発者だけでなく、 ドメイン エキスパートとの会話でも使用する点が挙げられます。 これを徹底することで、仕様とコードの行き来が圧倒的に楽になり、コミュニケーションミスも減ります。 また、 ドメイン エキスパートと開発者が使用する僅かな用語の違いから、新たな ドメイン 知識を発見するなど、 ドメイン のより深い理解に繋がります。 他の戦略的設計である「境界づけられたコンテキスト」の実践にも、 ユビキタス 言語は非常に重要な役割を果たすため、初めに適用することで後続につなげることもできます。 いかにして ドメイン 知識を得るか もちろん ドメイン エキスパートとの会話が一番の機会になるでしょう。 仕様の相談はもちろん、そのときは開発と直接関係がないような業務上の話題まで、 ドメイン エキスパートと同じ目線で ドメイン を捉えることができるようになればなるほど、 開発はスムーズに進むようになるはずです。 また、 ドメイン エキスパートが普段触れている情報源に触れてみるのも一つの手段です。 日々のニュースや、必読とされている書籍など、少しでも同じ知識を手に入れることで、普段の会話にもついていきやすくなります。 関連する資格取得を目指すのも良いかもしれません。銀行検定、証券外務員、簿記、社労士など、資格勉強を通じてたくさんの ドメイン 知識に触れることが出来ます。 最後に この記事では、私が2年間と少し ドメイン 駆動設計に関わって得られた、感じたことについてまとめてきました。 ドメイン 駆動設計については、多くの方がさまざまな媒体を通じて情報発信されています。 私も色々見聞きはしたものの、まだ実践できていないようなプ ラク ティスもたくさんありますので、引き続き経験を積んでいきたいと思います。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com *1 : エリック・ エヴァ ンスの ドメイン 駆動設計。 ドメイン 駆動設計の原典と言われる。 *2 : コンウェイ の法則や 割れ窓理論 、 パーキンソンの法則 を初めとして健全な開発を続けるには人間の性質とうまく付き合っていく必要がありますね。
こんにちは。株式会社 ラク スで先行技術検証や非エンジニアの方向けへの勉強会を実施している技術推進課のt_okkanです。 今回は非エンジニアの方向けの勉強会で、 IPv4 と IPv6 についてまとめる機会があったため記事にしました。 エンジニアでない方でも理解できるようにまとめましたので、 IPアドレス枯渇 問題を調べる際の事前知識としてもらえればと思います。 IPとは IPv4とネットワーク IPv4アドレス枯渇問題 NATを使用した対策 グローバルIPアドレスとプライベートIPアドレス NAT IPv4アドレスの確保 IPv6への移行 IPv6への移行の現状 IPv6へ移行するメリット IPv6へ移行するデメリット IPv6が普及していない理由 まとめ 参考 IPとは IPとは、Internet Protocolの略でコンピュータとコンピュータを繋ぐための通信規格の1つです。 複数のネットワークを相互に接続して、データを中継・伝達しながら1つの巨大なネットワーク「インターネット」を構成する役割を担っています。 IPによって接続されたインターネットでは、個々のネットワークとコンピュータを識別するために IPアドレス を割り当て、 送信先 と送信元を指定して通信を行っています。 IPv4 とネットワーク IPアドレス とは、インターネットに接続されたコンピュータ1台ごとへ割り振られる番号で、コンピュータのインターネット上での住所のようなものです。 そのため、ネットワーク上に接続されているコンピュータの IPアドレス は基本的に重複することはありません。 コンピュータがインターネット上でデータの送受信を行う場合、この IPアドレス を用いてデータの 送信先 と送信元を指定して通信を行っています。 この IPアドレス にはバージョン4とバージョン6が存在し、現在広く使用されているのがバージョン4の IPv4 になります。 IPv4 の IPアドレス は2進数の32桁で8桁ごとの4つに区切られており、それぞれ10進数にした形で表現されています。 2進数の1桁は0と1の2通りで、8桁の場合は256通りを表現できます。 IPv4 アドレスはその8桁の数字を4つ組み合わせているため、約43億通り表現できます。 よって IPv4 アドレスは約43億台のコンピュータを識別できます。 IPv4 アドレス枯渇問題 IPv4 アドレスを使用すると、約43億個のコンピュータを識別できます。しかし、2020年の世界の人口は約77億人と言われており、一人がPCと スマートフォン などの複数のコンピュータを所持する世の中になっています。 IPv4 アドレスでは、43億個以上のコンピュータに IPアドレス を割り当てることができなくなってしまいます。このように、インターネットに接続するコンピュータに割り振る IPv4 アドレスがなくなることを、 IPv4 アドレス枯渇問題と呼んでいます。 実際に、2019年に欧州地域で IPアドレス を管理しているRIPE NCC は IPv4 アドレスが完全に枯渇したと報告しています。 1 また、日本を含むアジア太平洋地域の IPアドレス を管理している組織であるAPNICは、2021年に IPv4 アドレスが完全に枯渇するのではないかと予想しています。 2 この問題を解決するための対策として、 IPv4 を利用して対策を行う延命策と、別の仕組みを利用して解決を行う恒久的な対策があります。延命策としてはNATを利用した対策などが、恒久的な対策として IPv6 への移行が主な対策として挙げられます。 NATを使用した対策 IPv4 アドレスの枯渇問題に対する IPv4 を利用した延命策の一つとして、NATを利用した対応があります。 NATの説明の前に、 グローバルIPアドレス とプライベート IPアドレス の説明をします。 グローバルIPアドレス とプライベート IPアドレス グローバルIPアドレス とは、インターネットに接続しているコンピュータに割り当てられる IPアドレス で、これまで扱ってきた IPアドレス を指します。 一方のプライベート IPアドレス は、企業のネットワークや家庭用のネットワーク内で使用される IPアドレス です。インターネット上では使用できず、同じネットワーク内でのみ使用できる IPアドレス になります。プライベート IPアドレス は、同じ IPアドレス でもネットワークが異なる場合は重複してもよいです。 IPv4 アドレスの枯渇が懸念されすべてのコンピュータに IPv4 アドレスを割り当てできなくなるため、ルータや公開サーバーなどインターネットに直接接続するコンピュータにのみ グローバルIPアドレス を割り当て、ルータ内の閉じられたネットワークに接続されているコンピュータにはプライベート IPアドレス を割り当てるようにしています。こうすることで IPv4 アドレスを効率的に使用できます。 ではどのようにして、 グローバルIPアドレス とプライベート IPアドレス を結び付けているのでしょうか。この IPアドレス の変換を行うのがNATです。 NAT NAT(Network Adress Translation)とは、 グローバルIPアドレス をプライベート IPアドレス に、またはその逆の変換を行う技術のことです。最近は IPアドレス とポート番号を組み合わせたNAPT(Network Address and Port Translation)が主流になっています。主に ルーター にこのNATの機能が組み込まれています。この技術を利用することで、プライベート IPアドレス が割り当てられた複数のコンピュータを1つの グローバルIPアドレス で管理できます。 このように、一つの IPv4 アドレスで複数のコンピュータを効率的に管理でき グローバルIPアドレス を節約できるため、 IPv4 の延命策としてNATが利用されています。 IPv4 アドレスの確保 もう一つの IPv4 アドレス枯渇問題の対策として、未使用の IPv4 アドレスの確保が挙げられます。 IPv4 アドレスが枯渇する前にプロバイダーから事前に未使用の IPv4 アドレスを割り当てを受けて確保しておくことや、未使用の IPv4 アドレスを 保有 している企業や組織から IPアドレス を購入して確保することが挙げられます。 しかし、2014年以降から IPv4 アドレスの消費ペースは上がっており最終的には IPv4 アドレス数の限界があるため、時間が進むにつれ IPv4 アドレスの確保が困難になります。 IPv6 への移行 IPv4 アドレスの枯渇を背景に恒久的な対応策として開発されたのが、 IPv6 です。 IPv4 は2進数の32桁で表現されましたが、 IPv6 は2進数の128桁で16桁ごとに区切り表現できます。また、それぞれ16進数にした形で表現されます。 2進数で16桁の場合は65536通りを表現できます。 IPv6 アドレスはその16桁を8つ組み合わせているため、約340潤個の IPアドレス を管理できます。1潤は1兆の3乗ですのでほぼ無限であることがわかります。 そのため、全世界のコンピュータに対して IPアドレス を割り当てることができ、NATを介さずに直接コンピュータ同士で通信を行えるようになります。 IPv4 アドレスから IPv6 アドレスへ移行することで、 IPv4 アドレス枯渇問題を根本的に解決することができます。 IPv6 への移行の現状 IPv4 アドレスの恒久的な対策である IPv6 への移行ですが、現状は IPv6 が普及しているとは言い難い状況です。 3 IPv6 へ移行するメリットとデメリットを紹介し、 IPv6 が普及しない原因を考察していきます。 IPv6 へ移行するメリット サービスを提供する企業において、 IPv4 アドレスの枯渇問題の制限を受けることなく、サービスの拡大や新規サービスの展開を行うことが挙げられます。 4 IPv4 アドレスが枯渇することで、新たにサービスを拡大する際に必要なネットワーク機器やサーバーに IPアドレス を割り当てることが困難になります。 また今後は IPv4 アドレスの市場価値が高まり値段が高騰する可能性もあり、サービスを拡大するために莫大なコストを投下する必要があるかもしれません。 5 IPv6 に移行することで、ほぼ無限に IPアドレス を付与することができるため、このような制限を気にすることなくサービスの拡大を行うことができます。 逆に IPv6 への対応が遅れると IPv4 アドレスの制限を受け、サービスの拡大や新サービスの展開ができなくなる可能性もあります。 IPv6 へ移行するデメリット IPv6 へ移行することのデメリットとして、 IPv4 との互換性がないことが挙げられます。 IPv4 と IPv6 は同じIPという プロトコル であっても互換性がなく、 IPv4 アドレスのコンピュータと IPv6 アドレスのコンピュータは直接通信することができません。 そのため IPv4 から IPv6 へ移行するために、 IPv6 に対応したルータやソフトウェアの開発・導入するコストが必要になります。 6 また、 IPv4 と IPv6 の通信のどちらにも対応する必要があることも挙げられます。今後も IPv4 を利用し続けるサービスやユーザーが存在することになります。 IPv4 のインターネットと IPv6 のインターネットが同時に存在することになり、 IPv4 の通信と IPv6 の通信のどちらにも対応する必要があります。 デュアルスタックやトンネリングなど IPv4 と IPv6 を共存させる技術があるため、そのための機器の導入や環境を構築するコストが必要になります。 IPv6 が普及していない理由 IPv4 アドレスの枯渇を解消するために開発された IPv6 ですが、今だに主流となっているのは IPv4 になっており、 IPv6 が普及しているとは言い難い状況です。 Google が「 IPv6 の採用状況」という統計で、 IPv6 アドレスを利用して Google サービスにアクセスしているユーザーの割合のデータを公開しています。 7 この統計によると、 IPv6 アドレスを利用している全世界のユーザーの割合は約35%で、日本国内のユーザーの割合は約40%となっています。 IPv6 が普及していない理由としては、以下の記事でも紹介されているようにこのような理由が考えられます。 cloud.watch.impress.co.jp 対応、運用コストがかかる IPv6 のデメリットでも紹介した、 IPv4 から IPv6 へ移行するためのコストや、 IPv4 と IPv6 の通信を共存するための運用コストが高いことが原因で、 IPv6 の普及が進んでいないと考えられます。 新たな利益を獲得できる訳ではなく、優先度が低い また IPv4 と IPv6 を共存させる技術があり、今後も IPv4 を利用できます。 IPv6 に移行しても、新たなユーザーを獲得したり新たな利益を得ることができる訳ではないため、優先度が低く対応が遅れていると考えられます。 また 総務省 の IPv6 についての調査結果によると、データセンター事業者とコンテンツ事業者で IPv6 への移行を検討していない理由として「自社だけで検討しても意味がない」ことや、「同業他社の動向を見てから検討する」ことが挙げれれています。 8 IPv6 に移行する必要性はあるものの、移行にかかるコストを回収できるわけでもないため、他の誰か(他社)が IPv6 に移行するのを待っている状態なのかもしれません。 まとめ IPアドレス のバージョンである IPv4 と IPv6 と、 IPv6 への移行について、簡単に説明してきました。 サービスを提供する企業にとって、 IPv6 に移行しても新たに利益がでない可能性があるものの、移行しないとサービスの拡大の障壁になるかもしれません。 IPv4 枯渇問題や IPv6 対応についての記事を見る前の、事前知識としてもらえたらと思います。 参考 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com The RIPE NCC has run out of IPv4 Addresses ↩ IPv4アドレスはもう残っていないのか、枯渇問題の現状 ↩ 日本におけるIPv6の普及とIPv4 over IPv6 ↩ IPv6@APNIC ↩ IPv4アドレスのお値段について考える ↩ Professional IPv6(無料版) ↩ IPv6の採用状況 ↩ IPv6 によるインターネットの利用高度化に関する研究会 最終報告書 ↩
こんにちは。 株式会社 ラク スで先行技術検証を行っている「技術推進課」の堀内( id:yhoriuchi )です。 今回、先行技術検証の取り組みである「技術推進プロジェクト」で調査を行なったメッセージキュー(MQ)について紹介します。 調査項目としてMQを選定した理由とゴール よくある話として、画面操作からのバッチ実行制御(実行順序制御、リトライ制御、エラー制御など)は非同期に動作するため実装が複雑化しやすいという問題を抱えています。 この「非同期な実行制御」をメッセージキュー製品で解決し、コードベースの簡素化が可能かの結論を出すことをゴールとして進めました。 MQとは何か 非同期型の通信方式のことです。システム間で通信を行う際、キューを挟んでメッセージをやり取りすることで非同期通信を実現します。 技技術的には1980年代から利用されており、歴史がある技術領域となっています。 近年ではマイクロサービス アーキテクチャ や分散処理システムの非同期通信において利用されることが多いため、このコンテキストでは聞いたこと・使ったことのある方もいるかもしれません。 下記にMQを使わない場合、使った場合の違いを簡単な絵で説明します。 MQを使わない場合のイメージ AさんからBさんへの作業依頼を直接行うことがイメージとして近いです。 Bさんが不在だったり、忙しい場合は作業依頼を受け付けてもらうことができないため、依頼できるようになるまでAさんは待ち続ける必要があります。 MQを使った場合のイメージ AさんとBさんとの間に「机」を設置して作業依頼を行うようなイメージです。Aさんは作業依頼を机に置いておくことでBさんに依頼を出すことができます。 Bさんは都合の良いタイミングで依頼を受け取れば良いですし、AさんはBさんの都合に合わせて待つ必要も無くなります。 このように送信側(Aさん)と受信側(Bさん)はMQ(机)を挟むことでお互いが好きなタイミングで処理を行うことができるようになります。 さらには受信側に障害が発生していたとしても、送信側はそれを意識することなく作業依頼を送ることができるため、障害に強いシステムにすることができます。 MQが無い場合のシステム 画面から CSV をアップロードする場合を想定し、手っ取り早く実現することを考えると下記のようになります。 ①ファイルをアップロードする ②Webアプリケーションがリク エス トを受け取り、 バッチ処理 を起動する ③ バッチ処理 の中でDBへの書き込みを行う ④一連の処理が終わった後、ユーザーに結果を返す この場合、リク エス トを受けてバッチが実行されるため、ユーザーはリク エス トを行うとすぐに処理が開始し、処理が終わればすぐに結果を受け取ることができます。また、特別な制御を行わないので実装量も少なくなります。 しかし、リク エス トのたびに バッチ処理 が実行されるため、たくさんのリク エス トを同時に受け付けるとサーバーが高負荷になりやすいというデメリットもあります。 これを回避するために取られる手段としてDBを用いた実行制御が考えられます。 次のようなイメージです。 このようにWebアプリとバッチの間にジョブ管理用のテーブルを用意し、cronや自作の常駐プロセスでジョブ管理テーブルを常に監視しながらバッチ実行を行うことになります。 DBを使ったジョブ管理も悪くはないのですが、1サーバーを複数の顧客で共有する(マルチテナント)場合は途端に考えないといけないことが増えます。 例えば、A社、B社、C社...と複数ある顧客で バッチ処理 が同時に起動しても問題ないのか、サーバーリソースを考えると何社まで同時起動が許容されるか、シーケンシャルに全テナントを処理した方がよいのか、などなど。システム要件にもよるので、どれが良い悪いではありませんが、考えることが増えると実装にも跳ね返ってくるのが世の常ですよね。 MQを導入した場合 先ほどの画面からの CSV アップロードは下記のような構成になります。 ①ファイルをアップロードする ②Webアプリケーションがリク エス トを受け取り、キューに登録する(このタイミングでユーザーにレスポンスを返す) ③ワー カープ ロセスがキューからメッセージを1つずつ取り出す ④DBへの書き込みを行う ⑤一連の処理が終わった後、ユーザーに結果を通知する キューを介してWebアプリと バッチ処理 であるワー カープ ロセスを分離することが可能となり、非同期処理を実現できるようになります。 さらにキューからメッセージを1つずつ取り出して処理するため、同時アクセスによる多重起動を気にする必要はありません。 下記のようなイメージです。 こうなってくると バッチ処理 部分をスケールしたい場合にどうするのか気になるところですが、この場合はキューに接続するバッチをスケールしたい分だけ単純に増やしてあげれば実現できます。基本的にキューのメッセージは 排他制御 されるため、別のプロセスが同じメッセージを取り合うことはありません。 セマフォ のような制御を意識する必要もありません。 さらに、メッセージを取り出すとメッセージは削除されます。何らかの理由でリトライが必要な場合はメッセージをキューに戻す(リキューと呼ぶ)ことも簡単に実現できます。 通常DBでジョブ管理を行うとテーブルをロックしてステータスを「処理中」に更新する、完了したら完了ステータスに更新する、一定の期間が経過したらジョブ管理テーブルから履歴を消す、といったことが必要になってくると思いますが、MQを利用するとこれらの実装は不要となります。 結論 ここまで調べてきた結果、下記の理由から複雑な箇所をMQに任せることができるため、実装が減りコードベースを簡素化できることが分かりました。 MQでリク エス トを1列に整列できるため、多重起動制御の実装が不要になる。 MQのメッセージ登録、取得がジョブのステータス管理に相当するため、ステータス管理を実装する必要がない。 メッセージは重複なくキューから受信側に配信されるため、 排他制御 を意識する必要がない。 利用できる ユースケース CSV ファイルアップロードを例に考えてきましたが、MQの利用が向いていると思われる ユースケース を考えてみました。 下記のような瞬間的に大量リソースを要求するケースや、機能間の 疎結合 を実現したい場合に有効となります。 大量のデータ登録/出力など、長時間リソースを消費するケース CSV アップロード/ CSV ダウンロードなど 画像変換等、瞬間的に大量リソースを使うケース 画像のリサイズ、加工をユーザーリク エス トに応じて実施するなど サービスとサービスを分離したいケース マイクロサービス アーキテクチャ のような構成で、サービス間にMQを挟むことで分離する 最後に MQを調べ始めた頃、基本的な用語が分からず変に時間がかかってしまったので、基本用語の説明と検証した結果からの所管を書いて締めくくろうと思います。 基本用語 MQ製品を調べていると プロデューサー/コンシューマー 、 パブリッシャー/サブス クライバー (略してパブサブとも呼ばれる)が説明として出てくることがありますが、この用語を理解しておくと製品理解がスムーズなのでここで説明しておきます。 プロデューサー/コンシューマー 1つのメッセージが1つの受信者だけに配信されるケースでは、送信側を「プロデューサー」、受信側を「コンシューマー」と呼びます。 1対1通信となる設計で使われる用語で、このページで紹介した内容がまさにプロデューサー/コンシューマーの関係で成り立っています。 多くのWebアプリでは直感的に理解しやすい構成だと思います。 パブリッシャー/サブス クライバー MQでは1つのメッセージを2つ以上の受信者にブロードキャストする仕組みがあり、その場合は送信側と受信側の呼び方が上記と変わります。 送信側が「パブリッシャー」、受信側が「サブス クライバー 」となります。さらにキューは「トピック」と呼ばれるようになります。(調べ始めの頃はトピックが何かが分かっておらず、ドキュメントを読むのに苦労していました...) 検証した結果からの所感 今回の検証でMQを使えば、リク エス ト毎にプロセスを起動する実装のデメリットを解消しつつ、DBでジョブ管理を行う際の煩わしさから解放されることが分かりました。 サーバーのリソースコン トロール が必要な際には是非とも導入しておきたい技術だと思います。 一方で、すでにDBによるジョブ管理を行なっており、実装が複雑になってしまっている場合、MQに置き換えるべきかについてはどうでしょうか。 個人的な結論となりますが、このケースでは無理に置き換えなくて良い考えています。実装が複雑になっていたとしても、それで保守・運用が回っているのであればMQに置き換えるだけのコストメリットはないでしょう。 もしかしたらジョブを追加、変更する頻度が多くて、その都度バグが発生するようなケースがあるかもしれませんが、この場合は作り直しが候補に上がってくると思います。作り直すのであればMQの導入も検討に含めるのが良いでしょう。
はじめに みなさんこんにちは。フジサワです。 「フロントエンド」や「フロントエンドエンジニア」という単語を耳にするようになって久しいですが、自他共に認めるバックエンドエンジニアを出自に持つ私にとって フロントエンド界隈の移り変わりは激しく、追いかけるのもなかなか大変です。 そこで今回は、改めてフロントエンドとは、またフロントエンドエンジニアに必要なスキルとは、といったあたりを整理してみたいと思います。 フロントエンドエンジニアに興味を持ったものの、あまりよくわかっていないと言う方の参考になれば幸いです。 はじめに フロントエンドとは フロントエンドエンジニアとは バックエンドとは バックエンドエンジニアとは フロントエンドエンジニアが押さえておいた方が良い技術要素 フロントエンド基本三要素 パッケージマネージャ ビルドツール群 JavaScriptフレームワーク SPAと状態管理 WebComponents Modern CSS テスト 型システム サーバーサイドレンダリング(SSR) GraphQL おわりに 参考 フロントエンドとは まずはフロントエンドとは何なのか、その定義から確認してみましょう。 Web開発業界におけるフロントエンドとは、システムの利用者が直 接触 れる・見ることができる領域、つまり Webブラウザ 上で動作する領域をさします。 一昔前は、「クライアントサイド」と呼ばれることが多かったですが、最近は「フロントエンド」という呼び方をすることが多い印象です。 実際に、 Google トレンドなどで調べてみると、2014年ごろを境に「フロントエンド」の呼称が増えているようです。 ※「クライアントサイド」の比較対象を「フロントエンドエンジニア」という単語にしているのは、「フロントエンド」という単語がアプリケーション開発以外でも 用いられる単語のためです。厳密には比較する対象の次元が異なっていますが、呼称の移り変わり程度は、上記画像からでも読み取れると思います。 フロントエンドエンジニアとは 主にHTML, CSS , JavaScript を用いて、前述のフロントエンド領域、すなわち Webブラウザ 上のUI部分を開発するエンジニアを指すことが多いです。 利用者からの操作を受け付け、後述のバックエンドに対して情報の取得・検索や更新などのリク エス トを行い、得られた結果を加工・表示する部分を担います。 以前は、 Webデザイナー が兼務をすることも多かったですが、フロントエンド領域の複雑化・大規模化によって求められる範囲が広くなるに従い、分業されるようになっています。 ただし、これはあくまでそういうケースもある、ということで、チームの体制、人員、プロダクトの規模によってはこの限りではありません。 バックエンドとは フロントエンドに対して、バックエンドとは、利用者が直 接触 れない領域、つまりサーバー上で動作する領域を指します。 このため、クライアントサイドの対義語として、サーバーサイドと呼ばれることも多いです。 バックエンドエンジニアとは Java や PHP 、 Python 、 Ruby などの言語を用いて、サーバー上で実行される処理を開発するエンジニアです。 フロントエンドからのリク エス トを受け付け、計算処理やデータベースに対して情報の取得・検索や更新の処理を実行し、処理結果をフロントエンドにレスポンスする部分を担います。 Webデザイナー とフロントエンドエンジニアの線引きがときに存在しないように、フロントエンドエンジニアとバックエンドエンジニアの線引きも、状況によっては存在しない場合もあります。 一人のエンジニアが、フロントエンド領域とバックエンド領域、双方を担うというケースも少なくありません。 大規模な開発においてはフロントエンド、バックエンド、あるいは、デザイナーやインフラエンジニアといった分業が行われることが多いと思いますが、 前述の通り、プロダクトの状況によっては一人のエンジニアが多くの領域を担うことも十分にありえます。 おそらくこの記事を読まれている方の中には、これからエンジニアを目指そうとされている方も多いかと思いますが、 私見 として、どのような領域を目指すにせよ、それはあくまでその領域に対する専門性が突出して高い・強みである、という状態であって、 「フロントエンドエンジニアなのでバックエンドのことは全くわからない」よりは、「フロントエンドエンジニアだけどバックエンドもある程度分かる」という状態を 目指すのが良いのではないでしょうか。(もちろん、その逆も然り) フロントエンドエンジニアが押さえておいた方が良い技術要素 それでは、フロントエンドエンジニアはどのような技術要素を押さえておけば良いかを見ていきましょう。 「これが正解」というものはないと思いますが、筆者が参考にしている下記のWebサイトを元に簡単にそれぞれの技術要素について抜粋する形で補足をします。 また、ここで紹介する技術要素が全て必要、というわけではありませんので、その点もご留意ください。 Developer Roadmaps(のFrontend Developerの項) https://roadmap.sh/frontend フロントエンド基本三要素 HTML CSS JavaScript パッケージマネージャ アプリケーションを開発する際に用いる フレームワーク やライブラリなどのインストール、バージョン、依存関係のある関連パッケージの管理などを行うもの。 パッケージマネージャと呼ばれるもの自体は数多く存在しますが、フロントエンド領域においては、 npm ・ yarn が主に用いられます。 ビルドツール群 タ スクラン ナー 開発の際に実行する様々なタスクを自動化するためのもの。 フロントエンドで開発をする際、 コンパイル する、テストを実行する、ソースを難読化する…など様々なタスクを実行することが多くなりますが、自動化することで、省力化したり、ミスを防いだり、あるいは自動化の設定をチーム内で共有することで属人化を解消することができるようになります。 以前はGulpやGruntをよく耳にしましたが、パッケージマネージャのnpmに備わっている npm-scripts がRoadmapでは推奨されています。 モジュールバンドラー JavaScript や CSS 、画像ファイルを一つにまとめるためのもの。 複数のファイルに分割した JavaScript の依存関係を整理する、Webサイトにアクセスした際のブラウザからのアクセスの回数を減らすことなどを目的に使用されます。 特に、大規模なプロダクトのフロントエンド開発においては、 JavaScript を細かく分割し、可読性や保守性・拡張性の向上を行うことが必要になるため、モジュールバンドラーを用いない場合はこの管理がとても大変になります。 Roadmapでは webpack が推奨。なお、Webpackにはタ スクラン ナーとしての機能も有しているため、タ スクラン ナーの一種として紹介されることもあるので混乱しないように注意してください。 Linter/Formatter ソースコード の整形や記述ルール、構文のチェックを行うためのもの。 ESLint (Linter)や、 Prettier (Formatter)など。 複数のエンジニアでプロダクトを開発する際には、 ソースコード を読みやすくするために、書式を統一することが一般的です。この際に用いられるのがFormatterです。 また、 ソースコード の解析で検出できるレベルの記法ミス・バグを見つけるために用いられるのがLinterです。 なお、両者は ソースコード の静的解析を行うという点で同じ領域を守備範囲に持つため、双方がルールに沿った ソースコード の自動整形や補正機能を持っていることがあり、同時に語られたり、併用する/しないといったケースがあります。 JavaScript フレームワーク 開発の生産性を高めるために、一定の枠組み・ルールに沿って実装を行うための基盤となるソフトウェア。 フロントエンド開発においてもっとも注目されている領域の一つがが JavaScript フレームワーク ではないでしょうか。 メジャーな JavaScript フレームワーク としては React.js 、 Vue.js 、 Anglar など。RoadmapではReact.jsが推奨されていますが、弊社では、React.jsとVue.jsを採用しています。個人的な意見としては、フロントエンドエンジニアでも、バックエンドエンジニアでも、少なくともメジャーな JavaScript フレームワーク のうち、一つだけでも押さえておくと良いのではないかと思います。 厳密には JavaScript フレームワーク ではないのですが、小規模な開発においては古くから活用されている jQuery を採用するケースもあります。 「脱・ jQuery 」という文脈で JavaScript フレームワーク が代替手段として語られることがありますが、完全な代替手段というわけではなく、小規模なフロントエンド開発において、まだ jQuery の活用範囲はあるかなと思っています。 Svelt など、新しい フレームワーク もどんどん出てきており、今後の JavaScript フレームワーク の盛衰に注目です。 SPAと状態管理 JavaScript フレームワーク の進歩と共に、従来の Webブラウザ の画面を全て書き換えて画面遷移を行うスタイルのアプリケーションから、よりリッチな操作性や表現を実現するために、一つの画面だけを用意し、その画面内の一部分だけを更新するというアプローチをとるSPA(SinglePageApplication)という手法がメジャーになっています。 SPAの流れの中で、画面に表示されているUI要素の状態(読み込み中、とか現在選択されている、など)を管理する量、複雑さが増すことになりました。 これらを解決する手段として用いられるのが状態管理ライブラリです。( Redux や Vuex など) WebComponents フロントエンド開発が大規模化すると、画面を構成するHTML要素を意味のあるカタマリ、役割でまとめ、他の要素の影響を受けなくしたり( カプセル化 )、部品として再利用できるようにする必要が生じました。 これを可能にするのがWebComponentsの考え方で、 HTML Templates 、 Custom Elements 、 Shadow DOM 、といった3つの技術要素がベースになっています。 Chrome 、 FireFox 、 Safari やEdgeといった主要なブラウザ全てでWebCompotentsがサポートされています。 なお、HTML要素を部品化する、 カプセル化 するというアプローチは、ReactやVueなどの JavaScript フレームワーク でも行われており、それらも「 コンポーネント 」と呼ばれています。 いずれにせよ、HTMLの要素とその振る舞い、デザイン、これらを意味のあるカタマリでまとめるというアプローチが、現在のフロントエンド開発では重要な考え方となります。 Modern CSS JavaScript は ES Modules によって、HTMLは WebComponents というアプローチによって適切に カプセル化 することができるようになりました。 CSS も、JSやHTMLと同様に適切に意味や責務によって カプセル化 をしたくなります。これを実現するのが Styled Components や CSS Modules といった技術要素になります。 テスト バックエンド開発においては、テストコードを書いてテストするというのは一昔前からスタンダードな開発手法になっていますが、フロントエンド開発の大規模化により、フロントエンドでも同様にテストコードを書くようになりました。Roadmapでは Jest や Cypress などが推奨されています。 型システム JavaScript は実行時に初めてデータの種類(型)が評価される言語であるため、数値を格納するための変数に文字列を代入できてしまうなどの不具合があったとしても、実行時までそれを十分に検出することができません。そこで、 JavaScript に対して型の概念を導入し、安全な実装ができるようにしたいというニーズが生じました。 型の導入により、より安全な実装ができるようになった他、 ソースコード の実装者の意図や処理、部品の役割を表現しやすくなることで、可読性や保守性の向上も実現できるようになりました。 この領域においては、現在ではほぼ TypeScript の採用一択なのではないかと思います。 サーバーサイド レンダリング ( SSR ) SPAで実現されたアプリケーションは、 JavaScript などの読み込みファイルが大きくなったり、ブラウザ上で動的に レンダリング を行うため、従来のWebアプリケーションに比べ、初回アクセス時の表示が遅くなりがちという課題が生じました。 これを解決するためにサーバー側でHTMLを生成してしまおうというアプローチが SSR です。React.jsの場合は Next.js 、Vue.jsの場合は Nuxtjs で実現することができます。 GraphQL SPAでは、フロントエンドとバックエンドの通信を REST API の呼び出しで行うことが一般的です。 REST API の仕様はシンプルである一方、柔軟なリク エス トに対して柔軟なレスポンスを返すことを実現するのが難しく、専用の API を大量に実装したり、あるいは不要なパラメータをフロントエンド側で取捨選択するといった方法が取られていました。また、 REST API では API の仕様を理解する必要があり、フロントエンドのエンジニアがバックエンドの仕様を理解するオーバーヘッドが発生していました。 GraphQLでは、 API のデータ構造の表現方法( スキーマ )と問い合わせ方法(クエリ)を規格化することで、バックエンドの内部実装に依らず、フロントエンドで必要な情報を柔軟にリク エス トすることができるようになります。 おわりに さて、本項では、フロントエンドとバックエンドの定義から、現在フロントエンドで主流となっていると思われる各種技術要素について整理して解説させて頂きました。 今回改めて整理してみると、フロントエンド領域の変化はとても激しく、情報をキャッチアップするのにとても苦労しました。 自分自身の知識整理もかねて、今回の記事を書かせて頂きましたが、これがみなさまのキャッチアップのお役にも立てれば幸いです。 解説に誤りなどありましたら、ご指摘いただけると幸いです! 参考 Developer Roadmaps - https://roadmap.sh/ エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
こんにちは ラク ス開発エンジニアのUKoniです。 社会人になって PHP 開発するようになったら、配列の機能がいろいろあることを知りました。 「あれってどうするんだっけ?」といちいち調べるのもあれなんで、ここにまとめます。 PHP の配列の機能を忘れてしまったときに活用してもらえるとうれしいです。 配列とは PHPでの配列の変数作成 多次元配列 PHPの配列と繰り返し PHPでの配列の操作 追加 式で追加 1つ以上の値の追加(array_push関数) 削除 特定の値の削除(unset関数) 重複した値の削除(array_unique関数) 並び替え 検索 配列内の値の全取得(array_values関数) 指定した値が配列内にあるか(in_array関数) 配列内の添字の取得(array_keys関数) 指定した添字が配列内にあるか(array_key_exists関数) 配列の要素数の取得(count関数) 変更 式で変更 配列同士の値の置き換え(array_replace関数) 変換 配列から文字列へ変換(implode関数) 文字列から配列へ変換(explode関数) 結合 配列同士の結合(同一の文字列添字の値を上書き)(array_merge関数) 配列同士の結合(同一の文字列添字の値をまとめる)(array_merge_recursive関数) まとめ 配列とは 配列とは、複数の値を格納できる変数のことです。配列は値ごとに添字を持ちます。 PHP での配列の変数作成 PHP で配列では、 array() 、または [] (角括弧)で作成することができます。 [] (角括弧)での配列の作成は、PHP5.4以降で使用できます。 この記事では [] (角括弧)の書き方で進めていきます。 では、実際に作成します。 <?php $ country = [ 'Japan' , 'USA' ] ; print_r ( $ country ) ; 実行すると以下のようになります。 Array ( [0] => Japan [1] => USA ) 配列に値を格納することで添字に番号が付けられます。 番号は配列内で使用されている整数の添字の最大値+1が次に追加される値の添字になります。 また、添字に番号の代わりに好きな文字列をつけることができます。 このような、文字列を添字にもつ配列を「 連想配列 」と呼びます。 <?php $ capital = [ 'Japan' => 'Tokyo' , 'USA' => 'Washington D.C.' ] ; echo $ capital [ 'Japan' ] ; 結果: Tokyo PHP では配列と 連想配列 に差はなく、1つの配列で番号の添字と文字列の添字を同時に使うことができます。 多次元配列 多次元配列とは、配列の中に配列を格納している配列です。 PHP では多次元配列を以下のように生成します。 <?php $ numbers = [ 'odd' => [ 'one' , 'three' , 'five' ] , 'even' => [ 'two' , 'four' , 'six' ] ] ; echo $ numbers [ 'even' ][ 0 ] ; 結果: two 配列と繰り返し 条件を満たすまで同じ処理をくり返します。 foreach文の場合 PHP の配列をforeach文で処理するときは、以下のように実装します。 <?php $ prefectures = [ 'Tokyo' , 'Osaka' , 'Kyoto' , 'Fukuoka' , 'Aichi' , 'Kanagawa' ] ; foreach ( $ prefectures as $ value ) { echo $ value . '<br>' ; } 上記のプログラムでは、foreach文の条件式内の $value に配列の値が入ります。 そして、foreach文内の処理が完了すると、 $value の値は配列の次の値に変わります。 これを配列の最後の値の処理が終わるまで繰り返します。 実行結果は以下になります。 Tokyo Osaka Kyoto Fukuoka Aichi Kanagawa また、 連想配列 では添字と値を同時に取得することができます。 <?php $ prefectures = [ 'Tokyo' => '東京' , 'Osaka' => '大阪' , 'Kyoto' => '京都' , 'Fukuoka' => '福岡' , 'Aichi' => '愛知' , 'Kanagawa' => '神奈川' ] ; foreach ( $ prefectures as $ key => $ value ) { echo $ key . ' : ' . $ value . '<br>' ; } foreach文の条件式内の $key に $value と紐づいた添字が入ります。 実行結果は以下になります。 Tokyo : 東京 Osaka : 大阪 Kyoto : 京都 Fukuoka : 福岡 Aichi : 愛知 Kanagawa : 神奈川 for文の場合 先ほどはforeach文での実装を紹介しましたが、for文でも実装は可能です。 <?php $ prefectures = [ 'Tokyo' , 'Osaka' , 'Kyoto' , 'Fukuoka' , 'Aichi' , 'Kanagawa' ] ; for ( $ i = 0 ; $ i < count ( $ prefectures ) ; $ i ++ ) { echo $ prefectures [ $ i ] . '<br>' ; } 実行結果は以下のようになります。 Tokyo Osaka Kyoto Fukuoka Aichi Kanagawa PHP での配列の操作 ここには PHP で配列の操作の方法をまとめています。 追加 PHP の配列に新たな値を追加します。 1. 式で追加する PHP で配列に値を追加する式は以下の通りです。 <?php $ prefectures = [ 'Tokyo' , 'Osaka' ] ; $ prefectures [] = 'Aichi' ; //連想配列の場合 $ prefectures [ 'Kyoto' ] = 'Kyoto' ; print_r ( $ prefectures ) ; 結果: Array ( [0] => Tokyo [1] => Osaka [2] => Aichi [Kyoto] => Kyoto ) 2. 1つ以上の値の追加(array_push関数) 1つ以上の値を配列の最後に追加します。 <?php $ prefectures = [ 'Tokyo' , 'Osaka' ] ; array_push ( $ prefectures , 'Kyoto' , 'Fukuoka' , 'Aichi' ) ; print_r ( $ prefectures ) ; 結果: Array ( [0] => Tokyo [1] => Osaka [2] => Kyoto [3] => Fukuoka [4] => Aichi ) 削除 PHP の配列の値を削除します。 1. 特定の値の削除(unset関数) 配列から指定した添字と紐づいている値を削除します。 <?php $ prefectures = [ 'Tokyo' , 'Osaka' , 'Kyoto' ] ; unset ( $ prefectures [ 0 ]) ; print_r ( $ prefectures ) ; 結果: Array ( [1] => Osaka [2] => Kyoto ) 2. 重複した値の削除(array_unique関数) 配列内で重複している値を削除します。 配列の先頭から最初に当たった値を残して、それ以降同じ値があると削除します。 <?php $ number = [ 'A' => 10 , 0 => 15 , 1 => 10 , 'B' => 13 , 'C' => 15 ] ; $ result = array_unique ( $ number ) ; print_r ( $ result ) ; 結果: Array ( [A] => 10 [0] => 15 [B] => 13 ) 並び替え PHP で配列内のデータの並び替えを行う関数は以下の表の通りです。 関数 説明 sort関数 値の昇順に並び替える。並び替え後の値に新しく番号の添字を割り当てる。 rsort関数 値の降順に並び替える。並び替え後の値に新しく番号の添字を割り当てる。 asort関数 値と添字を紐づけたまま、値の昇順に並び替える。 arsort関数 値と添字を紐づけたまま、値の降順に並び替える。 ksort関数 値と添字を紐づけたまま、添字の昇順に並び替える。 krsort関数 値と添字を紐づけたまま、添字の降順に並び替える。 では実際に使ってみましょう。 商品名を添字にし、値を値段にした $menu という配列を用意します。 この配列にsort関数を使うとこのようになる。 <?php $ menu = [ 'pasta' => 800 , 'hamburger' => 1000 , 'sashimi' => 2000 , 'sarada' => 500 , 'juice' => 300 ] ; sort ( $ menu ) ; print_r ( $ menu ) ; 結果: Array ( [0] => 300 [1] => 500 [2] => 800 [3] => 1000 [4] => 2000 ) このように値段の安い順になりますが、商品名が番号に変わっています。 ではこれをasort関数にするとどうなるでしょうか。 <?php $ menu = [ 'pasta' => 800 , 'hamburger' => 1000 , 'sashimi' => 2000 , 'sarada' => 500 , 'juice' => 300 ] ; asort ( $ menu ) ; print_r ( $ menu ) ; 結果: Array ( [juice] => 300 [sarada] => 500 [pasta] => 800 [hamburger] => 1000 [sashimi] => 2000 ) このように商品名を添字にもったまま、値段の安い順にはなります。 最後にksort関数を使います。 <?php $ menu = [ 'pasta' => 800 , 'hamburger' => 1000 , 'sashimi' => 2000 , 'sarada' => 500 , 'juice' => 300 ] ; ksort ( $ menu ) ; print_r ( $ menu ) ; 結果: Array ( [hamburger] => 1000 [juice] => 300 [pasta] => 800 [sarada] => 500 [sashimi] => 2000 ) このように商品名の昇順に並びます。 検索 PHP の配列内の値や添字、配列の要素の数などを調べます。 1. 配列内の値の全取得(array_values関数) PHP の配列内のすべての値を取得します。 ただし、添字は一緒に取得はできません。 <?php $ prefectures = [ 'Tokyo' => 'Shinjuku' , 'Osaka' => 'Osaka' , [ f : id : UKoni : 20201223191948p : plain ] 'Kyoto' => 'Kyoto' , 'Fukuoka' => 'Fukuoka' , 'Aichi' => 'Nagoya' , 'Kanagawa' => 'Yokohama' ] ; $ result = array_values ( $ prefectures ) ; print_r ( $ result ) ; 結果: Array ( [0] => Shinjuku [1] => Osaka [2] => Kyoto [3] => Fukuoka [4] => Nagoya [5] => Yokohama ) 2. 指定した値が配列内にあるか(in_array関数) PHP の配列内に指定した値があるかを調べます。 array_values関数とは違い、値を取得はしません。 <?php $ productList = [ 'banana' , 'orange' , 'mellon' , 'lemon' ] ; if ( in_array ( 'banana' , $ productList )) { echo 'バナナは取り扱っています。' ; } else { echo 'バナナは取り扱っていません。' ; } 結果: バナナは取り扱っています。 3. 配列内の添字の取得(array_keys関数) PHP の配列の中のすべての添字を取得します。 <?php $ fruits = [ 'banana' => 'yellow' , 'orange' => 'orange' , 'mellon' => 'green' , 'lemon' => 'yellow' ] ; print_r ( array_keys ( $ fruits )) ; 結果: Array ( [0] => banana [1] => orange [2] => mellon [3] => lemon ) また、指定した値を持つ添字を調べることもできます。 <?php $ fruits = [ 'banana' => 'yellow' , 'orange' => 'orange' , 'mellon' => 'green' , 'lemon' => 'yellow' ] ; print_r ( array_keys ( $ fruits , 'yellow' )) ; 結果: Array ( [0] => banana [1] => lemon ) 4. 指定した添字が配列内にあるか(array_key_exists関数) PHP の配列内に特定の添字があるか調べるときに使います。 array_keys関数とは違い、添字を取得はしません。 <?php $ kantou = [ 'Tokyo' => 'Shinjuku' , 'Kanagawa' => 'Yokohama' ] ; $ kansai = [ 'Osaka' => 'Osaka' , 'Kyoto' => 'Kyoto' , 'Hyogo' => 'Kobe' ] ; if ( array_key_exists ( 'Tokyo' , $ kantou )) { echo '東京は関東にあります。' ; } if ( array_key_exists ( 'Tokyo' , $ kansai )) { echo '東京は関西にあります。' ; } 結果: 東京は関東にあります。 5. 配列の要 素数 の取得(count関数) PHP の配列の要 素数 を数えます。 <?php $ fruits = [ 'banana' => 'yellow' , 'orange' => 'orange' , 'mellon' => 'green' , 'lemon' => 'yellow' ] ; echo count ( $ fruits ) ; 結果: 4 変更 PHP の配列内の値をほかの値に変更します。 1. 式で変更 既に配列内にある添字で値を呼び出し、別の値に変更します。 <?php $ prefectures = [ 'Tokyo' , 'Osaka' , 'Kyoto' ] ; $ prefectures [ 2 ] = 'Aichi' ; print_r ( $ prefectures ) ; 結果: Array ( [0] => Tokyo [1] => Kanagawa [2] => Aichi ) 2. 配列同士の値の置き換え(array_replace関数) 配列の値をほかの配列の値に置き換えます。 この時、最初の配列にない添字が置き換える配列にある場合は、最初の配列に追加されます。 <?php $ prefectures = [ 'Tokyo' , 'Osaka' , 'Kyoto' ] ; $ replace = array_replace ( $ prefectures , [ 1 => 'Kanagawa' , 2 => 'Chiba' , 3 => 'Saitama' ]) ; print_r ( $ replace ) ; 結果: Array ( [0] => Tokyo [1] => Kanagawa [2] => Chiba [3] => Saitama ) 変換 PHP の配列を別の型に変換したり、別の型の変数を配列に変換します。 1. 配列から文字列へ変換(implode関数) 配列を文字列に変換します。 <?php $ array = [ 'Tokyo' , 'Osaka' , 'Kyoto' ] ; $ string = implode ( ',' , $ array ) ; echo $ string ; 結果: Tokyo,Osaka,Kyoto 2. 文字列から配列へ変換(explode関数) 文字列を配列に変換します。 <?php $ string = 'Tokyo, Osaka, Kyoto' ; $ array = explode ( ',' , $ string ) ; print_r ( $ array ) ; 結果: Array ( [0] => Tokyo [1] => Osaka [2] => Kyoto ) 結合 PHP の配列同士をつなげます。 1. 配列同士の結合(同一の文字列添字の値を上書き)(array_merge関数) 配列を結合します。そのとき添字が重複した場合は、文字列だと後の配列の値に上書きし、番号だと追記します。 <?php $ car1 = [ 'color' => 'silver' , 'price' => 5000000 , 0 => 'car navigation' ] ; $ car2 = [ 'color' => 'black' , 'price' => 10000000 , 'max_speed' => '200km' , 0 => 'sports car' ] ; $ result = array_merge ( $ car1 , $ car2 ) ; print_r ( $ result ) ; 結果: Array ( [color] => black [price] => 10000000 [0] => car navigation [max_speed] => 200km [1] => sports car ) 2. 配列同士の結合(同一の文字列添字の値をまとめる)(array_merge_recursive関数) 結合するのはarray_merge関数と同じです。 この関数の特徴は、添字が重複した場合は、文字列だとその添字の値同士で配列を作り、番号だと追記します。 <?php $ car1 = [ 'color' => 'silver' , 'price' => 5000000 , 0 => 'car navigation' ] ; $ car2 = [ 'color' => 'black' , 'price' => 10000000 , 'max_speed' => '200km' , 0 => 'sports car' ] ; $ result = array_merge_recursive ( $ car1 , $ car2 ) ; print_r ( $ result ) ; 結果: Array ( [color] => Array ( [0] => silver [1] => black ) [price] => Array ( [0] => 5000000 [1] => 10000000 ) [0] => car navigation [max_speed] => 200km [1] => sports car ) まとめ 今回は PHP での配列機能をまとめました。 まとめたものだけでも、 PHP には配列の操作や関数が多くありました。 ただし、ここでまとめたものは PHP の配列の操作の一部分で、ここで書いたもの以外にも配列の操作や関数はあります。 PHP の配列を活用して、より良いプログラムを作成しましょう。 エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 forms.gle イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com
技術広報の syoneshin です。 今回は当社の開発組織メンバー達に 『2020年の気になったニュース』 と 気になった理由やポイントを聞きました。 質問:皆さんの「2020年の気になったニュース」 を教えてください。 【目次】 『2020年の気になったニュース』ランキング 『WSL2 正式版リリース』 『Apple、MacのAppleシリコンへの移行』 『PHP8リリース』 『東証システム障害』 『Zen3アーキテクチャ』 『オープンソースで作る東京都新型コロナウイルス対策サイト』 『KubernatesがDockerランタイムを非推奨に』 『Centos8 EOL』 『Flash終了』 『Google 障害』 『PostgreSQL13 リリース』 『5G』 『NAVERまとめ終了』 『東芝が量子暗号通信を事業化』 『GitHubのデフォルトブランチ名』 まとめ 『2020年の気になったニュース』ランキング 以下は当社の開発組織メンバーが選んだ「2020年の気になったニュース」ランキングです。 調査概要 調査手法:任意アンケート( ヒアリ ングシート)※複数回答可 調査対象:当社開発組織メンバー(テッ クリード ・開発マネージャー含む) 調査項目:2020年12月18日迄のニュース 有効回答数:60名 ランキング内容:得票数2票以上の2020年の気になったニュース Rank ニュースタイトル(概要) 得票数 1 WSL2 正式版リリース 9 2 Apple 、 Mac の Apple シリコンへの移行を発表 8 3 PHP8リリース 6 4 東証 システム障害 5 5 Zen3 アーキテクチャ 4 6 オープンソース で作る東京都 新型コロナウイルス 対策サイト 3 6 KubernatesがDockerランタイムを非推奨に 3 6 Centos8 EOL 3 6 Flash 終了 3 10 Google 障害 2 10 postgreSQL13 リリース 2 10 5G 2 10 NAVER まとめ終了 2 10 東芝 が量子暗号通信を事業化 2 10 GitHub のデフォルトブランチ名 2 当社で得票数1位の2020年の気になったニュースは 『WSL2 正式版リリース』 forest.watch.impress.co.jp 以下は気になった理由やポイント Windows で気軽に Linux 環境を動かせるようになって良かったです。 windows マシンで手軽に本物の Linux を動かせるようになるということで、ずっと楽しみにしていました。特に Docker Desktop はぐっと使いやすくなったと思います。 最近の Mac OS につらみを感じていて、脱却する手段の一つとしてウォッチしていました。 Windows Terminalも併せてMSの方向性を知ることができたのも良かったです。 業務で使っている Mac を修理に出した時、大した苦労もなく Windows 上に開発環境を構築し、手が止まる時間を最小限にできた。 etc 次いで、得票数2位の2020年の気になったニュースは 『 Apple 、 Mac の Apple シリコンへの移行』 www.apple.com 以下は気になった理由やポイント スマホ で活躍している ARMアーキテクチャ が x86 が主流だった昨今のPCに搭載されるということで注目を浴びています。 アプリ開発 でも ARMアーキテクチャ へのネイティブ対応するなど、大きな変化をもたらしているかと思います。 比較サイトを見ると格段に性能が上がっているらしく、独自開発でこういった結果を残せる Apple はさすがだなと感じた。 スマホ 用途で急速に性能向上してきた ARMアーキテクチャ が、 x86 アーキテクチャ とスペック的に遜色なくなってきて、 x86 に比較して強みだった省電力と GPU 性能を引っさげてデスクトップ用途に入ってきたこと。ARM版Windows10やARM搭載ノートは既にあったのでそこまで不思議はなかったが、一定のシェアをもつ Apple がシフトしたことで、デスクトップ用途のARMが市民権を得た印象。 etc 得票数3位の2020年の気になったニュースは 『PHP8リリース』 www.php.net 以下は気になった理由やポイント 議論がしばらく続いていたので、期待していました。 PHP らしい新機能・非推奨の廃止が見れて楽しい。 JIT 導入によって PHP の活用範囲の幅が広がった。 etc 次いで得票数4位の2020年の気になったニュースは 『 東証 システム障害』 www.itmedia.co.jp 以下は気になった理由やポイント 金融系は ステークホルダー の数が非常に多いため、意思決定の難しさや、普段から備えることの大切さを改めて思い起こさせてくれる出来事でした。 原因解明のスピード感がすごかった。判明している問題をすべて提示して、調査中などのコメントもなく「市場運営者としての責任は私共に全面的にある」の回答など、完璧な記者会見だと思った。 原因自体はマニュアル把握不備(ヒューマンエラー)という部分で、規模や事業の垣根を越えたITにおける根源的で極めて大きな課題を感じた。 etc 次いで得票数5位の2020年の気になったニュースは 『Zen3 アーキテクチャ 』 pc.watch.impress.co.jp 以下は気になった理由やポイント AMD のCPUが高い処理性能のCPUとして認知されるようになったことは、元 AMD 信者として感慨深いものがあります。最近は GPU も nvidia と バチバチ やってますね。 AMD のCPUがシングルスレッドで Intel を超えた。 etc 次いで得票数同率6位の2020年の気になったニュース3つは 『 オープンソース で作る東京都 新型コロナウイルス 対策サイト』 www.itmedia.co.jp 以下は気になった理由やポイント 政府主導ではなくエンジニア・デザイナー主導で公共性のあるサイトが作られて素晴らしい。 COCOA と似ていますが、 自治 体(しかも東京都)の公式サイトが オープンソース で開発されるというのが興味深く感じました。 etc 『KubernatesがDockerランタイムを非推奨に』 www.publickey1.jp 以下は気になった理由やポイント Kubernetes がDockerを経由しなくてもcontainerdを操作できるようになった。コンテナ業界がちゃんと規格化されて発展しているいい話だなあ、と思いました。 コンテナ=Dockerという印象を改めないといけない気になった。Dockersim使っている人は構成変更もあってお祭りになってました。 etc 『Centos8 EOL』 gigazine.net 以下は気になった理由やポイント OSS の商用利用を考えさせられ、ただただ辛いな…と思ったニュースでした。 唐突に「来年末終わって商用に切り替えます」となり、コミュニティから反発があった後、「やっぱ後続続けます」となった経緯が面白かった。 etc 『 Flash 終了』 www.adobe.com 以下は気になった理由やポイント 昔、ネットに大きな影響を与えた Flash がとうとう終了しました。最近では使うこともなくなってきましたが少しさびしい気がしますね。 昔よく見たサイトが Flash だったりして時代の隆盛を実感する一方、製品にも影響するので対応が大変な今日この頃です。 etc 次いで得票数同率10位の2020年の気になったニュース6つは 『 Google 障害』 www.itmedia.co.jp 以下は気になった理由やポイント 障害そのものよりも、ストレージ不足という原因の判明と解消までを45分で乗り切った Google の技術力に驚嘆しました。 影響範囲を考えると日常でどれだけ Google 頼りになっているのかが見えたようで、笑えないけど興味深いと思いました。 『PostgreSQL13 リリース』 www.postgresql.jp 以下は気になった理由やポイント PostgreSQL12からどういうバージョンアップがあったか気になった。 毎年のお約束ですが、変更ポイントは抑えておきたい。 『5G』 www.softbank.jp 以下は気になった理由やポイント キャリアサービス開始とか、みんなが騒ぎ出して5G普及したらどうなる?というのが盛り上がった気がっていました。 「今後の生活にどう影響してくるのか」が楽しみというところで気になっていました。 『 NAVER まとめ終了』 www.itmedia.co.jp 以下は気になった理由やポイント 雑学からグルメから何からものすごくお世話になりました。 なくなっていくのは時代ですね。。。 技術ネタだけでなく、 ウィキペディア よりも オタッキー なネタたちに、たくさんお世話になっていました。大きなサービスが突如終わる切なさ…あります。 『 東芝 が量子暗号通信を事業化』 www.toshiba.co.jp 以下は気になった理由やポイント 中国など競争相手も多いが、ぜひ世界をリードする分野に育ってほしい。 論理的に破られない暗号というのがポイントで、暗号解読される心配がなくなる。まさに最強の暗号技術という点で気になりました。 『 GitHub のデフォルトブランチ名』 [ www.publickey1.jp 以下は気になった理由やポイント OSS 文化も社会情勢を考慮するようになったのだなと思いました。 センシティブな話だとは思いますが、ずっと「master」と呼んでた身からすれば違和感があります…。 その他 『 SpaceX の有人宇宙飛行成功』 jp.techcrunch.com 『 接触 確認アプリ「 COCOA 」、 ソースコード を GitHub 上に公開』 k-tai.watch.impress.co.jp 『Vue3リリース』 news.vuejs.org 『シン・テレワークシステムの開発』 www.itmedia.co.jp 『Zoom』 www.nikkei.com などなど 110件の「2020年の気になったニュース」が当社内で共有されました。 まとめ 以上、いかがだったでしょうか。 改めて、2020年は本当に大変な一年だったと振り返っております。 当社開発組織では 重要な技術ニュースの クリッピング と見解を メンバー達が日常的にチャット共有し 最新の技術動向をチェックしております。 また最新の技術動向をプロダクトに導入するか を検証する社内勉強会も実施しており 検証で得られた知見も今後の主催イベントで発信していきます。 もし、当社活動に少しでもご興味をお持ちいただけましたら 当社イベントにも是非ご参加下さい。 主催イベント一覧 rakus.connpass.com 本記事でご紹介した 2020年の気になったニュース が皆さまの情報探索の一助となれば幸いです。 私たちは一緒に働く仲間を募集しています。 ご興味を持たれましたら以下のサイトからお問い合わせください。 career-recruit.rakus.co.jp
初めに 皆さん初めましてmosyoryです。 画像処理に興味はあるがどうやってやるのかわからない、そんな方もいるのではないでしょうか。 本記事では Windows ・ Mac の環境で Python と OpenCV を使ってちょっとした画像処理の方法を紹介したいと思います。関数等の詳細な解説は行っていないので予めご了承ください。 初めに OpenCVとは OpenCVのインストール Windows Mac pipでインストールできない 基本操作 読み込み 表示 保存 画像処理 色空間の変換 二値化処理 輪郭検出 輪郭描画 終わりに 参考サイト OpenCV とは OpenCV (Open Source Computer Vision Library)とは オープンソース コンピュータ・ビジョン・ライブラリです。 画像処理や汎用的な数学処理、 機械学習 に関する アルゴリズム が多数含まれています。 C+、 Python 、 Java でサポートされており Windows 、 Linux 、 OS X 、 Android 、 iOS などの様々なプラットフォームに対応しています。 BSD 3-Clauseラインセンスでリリースされているので商用利用も可能です。 opencv.org OpenCV のインストール まずは OpenCV のインストールから行います。 Windows と Mac での方法を紹介しますのでお持ちのパソコンに合わせて行ってください。 Python はすでにインストールされている前提で進めますのでまだの方は Python 公式サイトからPython3.xのバージョンをインストールしてください。本記事ではPython3.9で進めています。 www.python.org Windows コマンドプロンプト からpipを使用してインストールします。pipは Python のパッケージ管理ツールでPython3.4以上なら標準で付属していますので別途インストールする必要はありません。 Python の OpenCV はNumpyというライブラリを使用しますのでこちらもインストールします。 OpenCV をインストールするとNumpyの最新バージョンも自動でインストールしてくれるのですがブログ作成時はWindows10 2004とNumpy1.19.4の組み合わせだと Python プログラムを実行した際にエラーになります。 なのでバージョン1.19.3を指定してインストールしましょう。 pip install numpy==1.19.3 pip install opencv-python Mac ターミナルからpipでインストールします。以前はHomeBrewから OpenCV を入れていましたが今はpipだけでインストールできるようになりました。 Mac はNumpy1.19.4でも問題なく動くので OpenCV のインストール時にNumpyも自動でインストールしてもらいましょう。 pip install opencv-python pipでインストールできない pipで OpenCV をインストールしようとするとこんなエラーが出る時があります。 WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123)'))': /simple/opencv-python/ WARNING: Retrying (Retry(total=3, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123)'))': /simple/opencv-python/ WARNING: Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123)'))': /simple/opencv-python/ WARNING: Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123)'))': /simple/opencv-python/ WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123)'))': /simple/opencv-python/ Could not fetch URL https://pypi.org/simple/opencv-python/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: /simple/opencv-python/ (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123)'))) - skipping ERROR: Could not find a version that satisfies the requirement opencv-python ERROR: No matching distribution found for opencv-python どうやら Python パッケージを管理している PyPI との通信で SSL に問題があるらしく接続先を指定する必要があるそうです。 なのでpipを使う時にオプションを設定してインストールしましょう。 pip install opencv-python --trusted-host pypi.python.org --trusted-host files.pythonhosted.org --trusted-host pypi.org 基本操作 ここでは画像処理を行うための基本操作を紹介します。画像はお好きなものを用意してください。 今回は OpenCV のア イコン画 像を使って例をお見せします。 まず最初に OpenCV を Python のプログラム内で使えるようにインポートしましょう。 import cv2 読み込み 画像の読み込みではcv2.imread()を使います。引数は画像のファイル名です。 異なる ディレクト リにファイルがある場合は 絶対パス か 相対パス で指定してください。 パスが間違っていてもエラーにならず処理は継続されるので注意しましょう。 img = cv2.imread( 'OpenCV.png' ) 表示 画像をウィンドウに表示するにはcv2.imshow()を使います。 引数にウィンドウの名前、表示したい画像を指定してください。 表示する際にはcv2.waitKey()とcv2.destroyAllWindows()も一緒に書きましょう。 この2つはキーボード入力を受け付ける関数と作成したすべてのウィンドウを閉じる関数です。 cv2.imshow()だけではウィンドウは表示された後すぐに消えてしまいますが、続けて2つの関数を書くことでキーボード入力が行われるまでウィンドウが表示され続けます。 画像は左が Windows 、右が Mac で表示した際のウィンドウになります。 cv2.imshow( 'OpenCV' , img) cv2.waitKey( 0 ) cv2.destroyAllWindows() 保存 保存はcv2.imwrite()を使います。引数に保存する画像のファイル名、保存したい画像を指定します。 cv2.imwrite( 'save.png' , img) 画像処理 それでは画像処理を行っていきます。 今回は色空間の変更、二値化処理、輪郭検出・描画の方法を Python プログラムと結果画像と併せて紹介します。 色空間の変換 色空間(カラースペース)とは特定の色を数値などのパラメーターで表したものです。RGBや HSV のことですね。 OpenCV では画像はBGRで読み込まれますが画像処理の内容によっては別の方が適している場合があります。 そんな時はcv2.cvtColor()を使いましょう。引数に色空間を変更したい画像、色変換のフラグを指定してください。 よく使用する変換フラグはcv2.COLOR_△△2○○という形式で用意されており△△が変更前、○○が変換後の色空間の名前になります。 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #BGR → グレースケール 二値化処理 二値化処理とはグレースケール画像に対し 閾値 を設け白黒画像に変換することです。 二値化処理にはcv2.threshold()を使います。引数にグレースケール画像、 閾値 、 閾値 以上(フラグによっては値以下)の画素に割り当てる値、 閾値 処理を行うフラグを指定することで 閾値 と二値化画像を返します。 下の Python コードは画素が127以上なら白に、以下なら黒に変換しています。 ret, thresh = cv2.threshold(gray, 127 , 255 , cv2.THRESH_BINARY_INV) OpenCV の緑のマークが映らなくなりましたね。 輪郭検出 輪郭検出はcv2.findContours()を使います。引数に二値化画像、輪郭を検索するモード、輪郭検出方法のフラグを指定し実行することで輪郭と輪郭の階層情報を返します。 OpenCV は黒の背景から白の物体の輪郭を探すことを前提としているので使用する二値化画像に気を付けましょう。 contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) contoursに検出された全輪郭がlistで格納されています。 輪郭描画 描画にはcv2.drawContours()を使います。 引数に画像、listに格納された輪郭、描画したい輪郭のインデックス、描画する色と線の太さを指定します。 下の Python コードは全ての輪郭を線の太さ3の紫色で描画しています。 cv2.drawContours(img, contours, - 1 , ( 255 , 0 , 255 ), 3 ) OpenCV の文字と赤、青のマークに紫色の輪郭線が描画されましたね。 終わりに Python と OpenCV を使った画像処理の例を紹介しました。 今回は色の変換や描画となりましたが、 OpenCV では人の顔の検出や 機械学習 など多くのことができるようになっています。 公式のドキュメントにも Python のサンプルコード付きで説明がありますので詳しい処理内容を知りたい方はそちらをご覧になってください。 参考サイト OpenCV: OpenCV-Python Tutorials Pythonによる画像処理に利用するライブラリを現役エンジニアが解説【初心者向け】 | TechAcademyマガジン 画像処理をマスターしよう!PythonでOpenCVを使う方法を紹介! | TechTeacher Blog Pythonで画像処理をするならOpenCVがオススメ! | 侍エンジニアブログ エンジニア 中途採用 サイト ラク スでは、エンジニア・デザイナーの 中途採用 を積極的に行っております! ご興味ありましたら是非ご確認をお願いします。 https://career-recruit.rakus.co.jp/career_engineer/ カジュアル面談お申込みフォーム どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。 以下フォームよりお申込みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォーム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ イベント情報 会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com