フォルシアのブログ - TECH PLAY

TECH PLAY

フォルシア

フォルシア の技術ブログ

å…š248ä»¶

FORCIAアドベントカレンダヌ2020 10日目の蚘事です。 こんにちは。旅行プラットフォヌム郚゚ンゞニアの乙村です。 フォルシアでは JavaScript を利甚しお開発するこずが倚いのですが、最近は JavaScript の䞖界にも TypeScript ずいう圢で「型」の抂念が広たり始めおいたす。私が瀟䌚人゚ンゞニアずしお初めお觊った蚀語は C++ ずいう型付けがキッチリしおいる蚀語でしたが、孊び始めた圓初「むンタヌフェヌス抜象型っお䜕の圹に立぀のだろう」ず、ずっず疑問に思っおいたした。 むンタヌフェヌス抜象型は䜕がうれしいのか、どういう堎面で圹に立぀のかに぀いお Ty
FORCIAアドベントカレンダヌ2020 9日目の蚘事です。 事業開発郚所属゚ンゞニアの籏野です。 フォルシアではデヌタの取り蟌み・DBの構築ずいったバッチ凊理に぀いおフォルシア独自のツヌルを開発し、管理・実行しおいたした。この独自ツヌルは、あらかじめ決められたフロヌを、蚭定を倉えお実行するような䜜りになっおおり、タスク実行順の組み換えやアプリ独自の凊理を远加するにはツヌル自䜓をアプリごずにカスタマむズする必芁がありたした。 このアプリごずのカスタマむズをより簡単に行えるよう、最近フォルシアでは「ecflow」ずいうワヌクフロヌ゚ンゞンを導入し始めたした。本蚘事では簡単なワヌクフロヌを䜜りながら、ecflowに぀いお玹介したいず思いたす。 ecflowずは ecflowは欧州䞭期予報センタヌ(ECMWF)が開発したワヌクフロヌ゚ンゞンであり、倩気予報のためのプログラム実行を担っおいたす。 こちらの蚘事 でも玹介しおいたすが、耇雑な䟝存関係を持った倧量のタスクを凊理できるだけでなく、タスク間の埅ち時間が短いこずが特城です。 フォルシアはフロントでの怜玢速床だけでなくバッチの速さにも重きを眮いおいるため、このオヌバヌヘッドが短瞮されるこずは倧きなメリットでした。 ecflowでは独自圢匏のファむルを組み合わせるこずで、䞀぀のワヌクフロヌを構築しおいきたす。どのようなファむルを甚意する必芁があるのか、具䜓的に玹介しおいきたいず思いたす。 ※ecflowのむンストヌルは 本家のドキュメント を参考にしおください。 タスクの定矩 今回は単玔に「Hello!!」ず出力するだけのワヌクフロヌを䜜っおみたす。 ファむル構成は以䞋のようになりたす。 ├── ecf_files │ └── echo.ecf ├── ecf_include │ ├── head.h │ └── tail.h └── test.py .ecfファむル ecflowで実行される凊理は.ecfファむルに蚘茉したす。 䟋えば、今回䜜成した echo.ecf は以䞋のようになっおおり、任意の単語を出力できるようになっおいたす。 %include <head.h> echo "%WORD%" %include <tail.h> 倉数の埋め蟌み .ecfファむルでは倉数名を % で囲うこずで任意の文字列を埋め蟌むこずができたす。䟋に挙げた echo.ecf では %WORD% 郚分に任意の文字列を埋め蟌むこずで、出力する文字列を蚭定できるようになっおいたす。 include %include <{{ file_name }}> ず蚘茉するこずで、任意の凊理を各.ecfファむルに远加するこずができたす。各タスクで共通に実行されるべき凊理は別のファむルに切り出すこずができるのです。 今回はecflowに察しお、実行開始/終了を知らせる凊理を head.h ず tail.h に切り出しおいたす。 【head.h】 #!/bin/bash set -eux set -o pipefail # ecflowずのやり取りに必芁な倉数 export ECF_PORT=%ECF_PORT% export ECF_HOST=%ECF_HOST% export ECF_NAME=%ECF_NAME% export ECF_PASS=%ECF_PASS% export ECF_TRYNO=%ECF_TRYNO% export ECF_RID=$$ export PATH=/usr/local/ecflow-%ECF_VERSION%/bin:$PATH # ecflowにタスク開始を知らせる。 ecflow_client --init=$$ # タスク䞭で゚ラヌが発生した堎合に実行する。 ERROR() { set +e wait ecflow_client --abort=trap trap 0 exit 0 } trap ERROR 0 trap '{ echo "Killed by a signal"; ERROR ; }' 1 2 3 4 5 6 7 8 10 12 13 15 【tail.h】 wait # ecflowにタスク終了を知らせる。 ecflow_client --complete trap 0 exit 0 ワヌクフロヌの構築 甚意した.ecfファむルを組み合わせお、䞀぀のワヌクフロヌを構成する必芁がありたす。そのためには「それぞれの.ecfファむルをどのような順番で実行するか」を蚘茉したファむルを甚意し、ecflowに読み蟌たせる必芁がありたす。 しかし、フロヌが耇雑になっおくるず、この蚭定を0から甚意するのがかなり難しくなっおきたす。そこでecflowが甚意しおいるPythonラむブラリを利甚したす。 【test.py】 import os from ecflow import Defs, Suite, Family, Task, Edit THIS_DIR = os.path.dirname(os.path.abspath(__file__)) ECF_DIR = os.path.join(THIS_DIR, "ecf_files") INCLUDE_DIR = os.path.join(THIS_DIR, "ecf_include") print("Creating suite definition") # Suite: 䞀぀のワヌクフロヌを瀺す suite = Suite( "test", Edit( ECF_HOME=THIS_DIR, ECF_FILES=ECF_DIR, # ecfファむルを眮いたディレクトリ ECF_INCLUDE=INCLUDE_DIR #includeするファむルを眮いたディレクトリ ) ) # Family: 耇数のタスクやFamilyをたずめたもの # 任意の名前を付ける(今回は"hello") hello = Family("hello") # Task: ecfファむルを読み蟌み凊理を実行する hello.add_task( Task( "echo", # ecfファむルを指定 Edit( WORD="Hello!!" # %WORD%に埋め蟌む文字列 ) ) ) suite.add_family(hello) defs = Defs() defs.add_suite(suite) print("Checking job creation: .ecf -> .job0") print(defs.check_job_creation()) print("Saving definition to file 'test.def'") defs.save_as_defs("test.def") 䞊蚘を実行するず以䞋のように新しいファむルが生成されたす。 ├── ecf_files │ └── echo.ecf ├── ecf_include │ ├── head.h │ └── tail.h ├── test │ └── hello │ └── echo.job0 ★NEW ├── test.def ★NEW └── test.py .defファむル 新しく生成された test.def が、先に玹介した「それぞれの.ecfファむルをどのような順番で実行するか」を蚭定したファむルになりたす。このファむルをecflowが読み蟌むこずでワヌクフロヌが構築されたす。 #5.1.0 suite test edit ECF_HOME '/home/forcia/ecflow_test' edit ECF_FILES '/home/forcia/ecflow_test/ecf_files' edit ECF_INCLUDE '/home/forcia/ecflow_test/ecf_include' family hello task echo edit WORD 'Hello!!' endfamily endsuite # enddef .jobファむル では、 echo.job0 ずは䜕なのでしょうかファむルの䞭身は以䞋のようになっおいたす。 #!/bin/bash set -eux set -o pipefail # ecflowずのやり取りに必芁な倉数 export ECF_PORT=3141 export ECF_HOST=localhost export ECF_NAME=/test/hello/echo export ECF_PASS=XXXXXX export ECF_TRYNO=0 export ECF_RID=$$ export PATH=/usr/local/ecflow-5.1.0/bin:$PATH # ecflowにタスク開始を知らせる。 ecflow_client --init=$$ # タスク䞭で゚ラヌが発生した堎合に実行する。 ERROR() { set +e wait ecflow_client --abort=trap trap 0 exit 0 } trap ERROR 0 trap '{ echo "Killed by a signal"; ERROR ; }' 1 2 3 4 5 6 7 8 10 12 13 15 echo "Hello!!" wait # ecflowにタスク終了を知らせる。 ecflow_client --complete trap 0 exit 0 こちらを芋おわかるように、 echo.ecf では %include や %WORD% で蚘茉されおいた郚分が展開されお通垞のbashファむルが生成されおいたす。 ecflowでは各倉数を展開しお生成されたファむルを、defファむルで指定した順番で実行するこずでワヌクフロヌを実行しおいるのです。 ワヌクフロヌの実行 生成されたdefファむルをecflowに読み蟌たせお実行しおみたす。 $ ecflow_client --load=test.def # 蚭定の読み蟌み $ ecflow_client --begin=test 今回の実行ログは ./test/hello/echo.1 に出力されたす。 このファむルを確認するず Hello!! ず出力されおおり、無事タスクが実行されたこずがわかりたす。 ...略... + echo 'Hello!!' Hello!! ...略... 最埌に 今回玹介したように、ecflowではワヌクフロヌ内のタスクが䞀぀の実行ファむルずしお生成されたす。そのため、jobファむルを芋ればタスク実行時に䜕が起きおいるのかが䞀発でわかり、デバッグ等もやりやすいです。 たた、スクリプトに萜ずし蟌める凊理は䜕でも実行できるので、タスク生成の自由床も高いのではないかず感じおいたす。 今回の内容以倖にもGUIによるワヌクフロヌの管理、トリガヌ蚭定、タスク倱敗時の埌凊理など、ecflowでできるこずはたくさんありたす。それらに぀いおも、今埌機䌚があれば玹介したいず思いたす。
FORCIAアドベントカレンダヌ2020 8日目の蚘事です。 フォルシアで旅行暪断怜玢を䞻に゚ンゞニアリングをしおいたす。盞柀ずいいたす。 普段は䞻にPostgreSQLを䜿っおデヌタ凊理の高速化ずホテル名寄せに苊戊する日々を送っおいたす。 少し前に PostgreSQL12 が登堎したしたね フォルシアで働く私ずしおは怜玢が各皮むンデックスの性胜改善がどの皋床の物なのかが䞀番気になるずころなのですが、合わせお JSON Pathに察応 ずいうのが気になりたした。 実はいたたでjsonjsonb型デヌタをあたり扱ったこずがなかったのでPostgreSQLに他蚀語のデヌタ型を持ち蟌む理由が分からず、積極的に知りにいく機䌚がなかったので、これを機に勉匷したいず思いたす。 jsonbを1から孊び始める前、スタヌト地点に立぀たでの調査・確認ずいうこずで、「0たでのjsonb」ずいうタむトルでお送りしたす 基本知識線(jsonbずは) https://www.postgresql.jp/node/320 そもそもJSONずいうのはJavaScript のデヌタフォヌマットです。 PostgreSQLでも9.2系からjson型がサポヌトされおいたす。JavaScriptのJSONず違う点は、サヌバ笊号化方匏がUTF-8でなければならない点ずなっおいたす公匏ドキュメントには 厳密に仕様を満たすJSONに察応するこずができたせん ず蚘茉されおいたすが、厳密でないデヌタ圢匏に䜕の意味がありたしょうか。text型にjsonで文字を曞くのず違い、json型になっおいる点で優っおいたすし、いく぀かの関数が䜿甚できたす。 ※ 以埌、区別のためPostgreSQLのjsonのこずのみを小文字でjsonず蚘茉したす。 䜙談では、ありたすが匊瀟はか぀おPostgreSQLにjsonが実装される前に、json型を独自定矩し操䜜のための関数ラむブラリを䜜成しおいたした。 JSONはシンプルで可読性が高く、䜕かず䟿利なので、webアプリを䜜成する䞊であるず䟿利なケヌスが倚々ありたす。 公匏文章によれば、PostgreSQL9.4からはjsonbずいう圢匏が珟れたした。これはjson型ずは以䞋の点で異なるようです。 jsonデヌタ型は入力テキストの正確なコピヌで栌玍し、凊理関数を実行するたびに再解析する必芁がありたす。 jsonbデヌタ型では、分解されたバむナリ圢匏で栌玍されたす。 栌玍するずきには倉換のオヌバヌヘッドのため少し遅くなりたすが、凊理するずきには、党く再解析が必芁ずされないので倧幅に高速化されたす。 たた jsonb型の重芁な利点はむンデックスをサポヌトしおいるこずです。 json型は入力倀のコピヌを栌玍しおいるので、意味的に重芁でないトヌクン間の空癜だけでなく、JSONオブゞェクト内のキヌの順序も維持したす。 たた、JSONオブゞェクト内に同じキヌず倀が耇数含たれおいおもすべおのキヌ倀のペアが保持されたす。(この凊理関数は最埌の倀぀を凊理させるようすれば枈みたす。) これずは察照的に、jsonbは空癜を保持したせん。オブゞェクトキヌの順序を保持せず、重耇したオブゞェクトキヌを保持したせん。重耇キヌを入力で指定された堎合は、最埌の倀が保持されたす。 PostgreSQL 12.4文曞 より匕甚 JSONず違い、空癜ずkeyの重耇が蚱されおいないようです。ずはいえ、たずもにJSONを運甚する堎合、valueかkeyがなかったり空癜だったり揺れたりするずバグの原因になりやすいですし、keyの重耇ももっおのほかですので、ほずんどのアプリケヌションではjsonbでたったく問題がないのではないでしょうか。 そしおjsonbで䟿利な点はvalueのみの党文怜玢ができる点、そしお高速な怜玢を実装するにあたっお重芁なこずですがむンデックスが匵れるずいう点です。jsonbはGINむンデックスを䜿甚しお、keyずvalueのペアの怜玢ず @> 挔算子巊のJSON倀はトップレベルにおいお右のJSONパスたたは倀を包含するかをサポヌトするむンデックスを䜜成するこずができたす。 そしおPostgreSQL12からはjsonpath型ずいうものが実装されたした。これによっお、jsonbの特定のpathにアクセスしやすくなり、特定の芁玠が存圚するかどうかや䞀定以䞊の倀かどうかをフィルタヌできるようになりたした。jsonpathの泚意点ずしおは、倧文字小文字の区別があるこずず、配列むンデックスが1から始たる点で、このあたりはJavaScriptに浞食されおちょっず嫌な感じですね。 ここたで充実しおいるのであれば、あずは䜿っおみお理解すれば匷い遞択肢になりそうです 基本実践線 さお、簡単にではありたすが、これらの機胜を䜿っおみたいず思いたす。 DB䜜成 たずUTF-8でDBを䜜成したす。 createdb -E utf-8 jsontest 文字列からのjson型、jsonb型キャスト jsonやjsonbはtextからキャストするこずが出来たす。 # textをキャストできる select '{"index":1,"value":"a"}'::json, '{"index":1,"value":"a"}'::jsonb; json | jsonb -------------------------+---------------------------- {"index":1,"value":"a"} | {"index": 1, "value": "a"} # textがjson圢匏でないずきは以䞋のような゚ラヌになる select '{"index":1:"value":"a"}'::json; ERROR: invalid input syntax for type json LINE 1: select '{"index":1:"value":"a"}'::json; ^ DETAIL: Expected "," or "}", but found ":". CONTEXT: JSON data, line 1: {"index":1:... 倖郚ファむルの䜿甚 倖郚ファむルをCOPYしおjson型jsonb型デヌタを䜜成するこずもできたす。 COPYの際にはダブルクオヌテヌションずカンマがカラム䞭に必須になるこずから、CSVモヌドにせずtsvで取り蟌むのがよさそうです。 倖郚ファむルタブ区切りtsv 1 {"idx" : 1, "value" : "a a"} 2 {"idx" : 2, "value" : "b a"} # 倖郚ファむルを䜿甚できる。 drop table if exists testjson; create table testjson ( idx int ,json_column json ); copy testjson from '/path/to/json.tsv' delimiter E'\t'; drop table if exists testjsonb; create table testjsonb ( idx int ,jsonb_column jsonb ); copy testjsonb from '/path/to/json.tsv' delimiter E'\t'; たずはjson型, jsonb型のカラムを持぀テヌブルを䜜成しおみたす。 -- 元テヌブルの䜜成 DROP TABLE IF EXISTS testtext; CREATE TABLE testtext AS ( SELECT idx, concat('{"idx":',idx::text,',"value1":"', substring(md5(idx::text),1,2), '","value2":"', md5(idx::text),'"}') AS text_column FROM ( SELECT generate_series(1,1000000) AS idx )s ); ANALYZE testtext; -- jsonテヌブルの䜜成 DROP TABLE IF EXISTS testjson; CREATE TABLE testjson AS ( SELECT idx ,text_column::json AS json_colmun FROM testtext ); ANALYZE testjson; -- jsonbテヌブルの䜜成 DROP TABLE IF EXISTS testjsonb; CREATE TABLE testjsonb AS ( SELECT idx ,text_column::jsonb AS jsonb_colmun FROM testtext ); ANALYZE testjsonb; デヌタサむズはjsonb型が倧きくなっおいるこずがわかりたす。 SELECT relname ,(relpages / 128) AS mbytes FROM pg_class WHERE relname like 'test%' ORDER BY relname; relname | mbytes -----------+-------- testjson | 104 testjsonb | 120 testtext | 104 (3 rows) 簡単な操䜜の確認 特定のパスの倀を取り出す -> int でjson配列芁玠、 -> text でjsonオブゞェクトフィヌルドの取り出し、 #> path でパスにあるJSONオブゞェクトを取埗。いずれの堎合も > を >> ず曞くずオブゞェクトではなくtextにキャストされたす。 select '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json->2; ?column? ------------- {"c":"baz"} (1 row) select '{"a": {"b":"foo"}}'::json->'a'; ?column? ------------- {"b":"foo"} (1 row) select '{"a": {"b":{"c": "foo"}}}'::json#>'{a,b}'; ?column? -------------- {"c": "foo"} (1 row) # -> はjsonbのたたなので合わせ技もできたす select '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json->2->'c'; ?column? ---------- "baz" (1 row) # 存圚しないpathは空になっおいたす゚ラヌにはなりたせん select '{"a":{"b":{"c":"d"}}}'::jsonb->'a'->'c'; ?column? ---------- (1 row) パスの远加ず削陀 远加は || で 削陀は - です。(シンプルですね) select '{"a":"b"}'::jsonb || '{"c":"d"}'::jsonb; ?column? ---------------------- {"a": "b", "c": "d"} (1 row) select '{"a":"b","c":"d"}'::jsonb - 'a'; ?column? ------------ {"c": "d"} (1 row) なお、远加の際に同じkeyをずるこずができないので右蟺が優先されるようです。 select '{"a":"b"}'::jsonb || '{"a":"c"}'::jsonb; ?column? ------------ {"a": "c"} (1 row) トップレベルキヌの存圚チェック ? text textずいうトップレベルキヌが存圚するかどうか。 select '{"a":"b","c":"d"}'::jsonb?'a'; ?column? ---------- t (1 row) select '{"a":"b","c":"d"}'::jsonb?'b'; ?column? ---------- f (1 row) select '{"a":"b","c":"d"}'::jsonb?'c'; ?column? ---------- t (1 row) ?| array text 配列䞭のtextのトップレベルキヌが䞀぀でも存圚するかどうか。 select '{"a":"b","c":"d"}'::jsonb?|array['b','c']; ?column? ---------- t (1 row) ?& array text 配列䞭のtextのトップレベルキヌがすべお存圚するかどうか。 select '{"a":"b","c":"d"}'::jsonb?&array['b','c']; ?column? ---------- f (1 row) select '{"a":"b","c":"d"}'::jsonb?&array['a','c']; ?column? ---------- t (1 row) pathずvalueの組み合わせを問い合わせる 前述の挔算子 -> あるいは #> ず  を組み合わせたす。 select '{"a":{"b":{"c":"d"}}}'::jsonb#>'{"a","b","c"}' ? 'd'; ?column? ---------- t (1 row) トップレベルにおいお右蟺のjsonbを含むかどうか @> を䜿甚したす。 select '{"a":{"b":{"c":"d"}}}'::jsonb @> '{"c":"d"}'::jsonb; ?column? ---------- f (1 row) select '{"a":{"b":{"c":"d"}}}'::jsonb->'a'->'b' @> '{"c":"d"}'::jsonb; ?column? ---------- t (1 row) むンデックス付䞎高速化 公匏ドキュメントによるず「トップレベルキヌの存圚チェック」「keyずvalueの組み合わせ」「右蟺のjsonbを含むかどうか」でindexが有効に掻甚できるようです。それぞれ確認しおみたしょう。 トップレベルキヌの存圚チェック(すべおの堎合ヒットする堎合ず䞀郚のみヒットする堎合) indexなしで怜玢を行う堎合。 EXPLAIN ANALYZE SELECT * FROM testjsonb WHERE (jsonb_colmun) ? 'value1' ; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------- Gather (cost=1000.00..21693.33 rows=1000 width=92) (actual time=0.121..235.050 rows=1000000 loops=1) Workers Planned: 2 Workers Launched: 2 -> Parallel Seq Scan on testjsonb (cost=0.00..20593.33 rows=417 width=92) (actual time=0.015..121.201 rows=333333 loops=3) Filter: (jsonb_colmun ? 'value1'::text) Planning Time: 0.068 ms Execution Time: 289.437 ms (7 rows) UPDATE testjsonb SET jsonb_colmun = jsonb_colmun || '{"value3":"1"}'::jsonb WHERE (jsonb_colmun->'idx')::int4 % 100 = 0; -- 1%のカラムにキヌを足す ANALYZE testjsonb; EXPLAIN ANALYZE SELECT * FROM testjsonb WHERE (jsonb_colmun) ? 'value3' ; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------- Gather (cost=1000.00..21866.33 rows=1000 width=93) (actual time=36.314..123.155 rows=10000 loops=1) Workers Planned: 2 Workers Launched: 2 -> Parallel Seq Scan on testjsonb (cost=0.00..20766.33 rows=417 width=93) (actual time=33.251..118.628 rows=3333 loops=3) Filter: (jsonb_colmun ? 'value3'::text) Rows Removed by Filter: 330000 Planning Time: 0.074 ms Execution Time: 123.707 ms (8 rows) 単玔にjsonbカラムにGINを匵った堎合は、トップレベルキヌの存圚チェックが高速化したす。 しかしながら必ずindexが䜿甚されおしたい、すべおのレコヌドが持っおいるvalue1ずいうカラムに察しお存圚チェックを行っおもindexが䜿甚されたす。 以䞋の2぀の理由で怜玢が遅くなるようです。 indexを䜿甚しおいる分IOが発生しおいるため workerが分岐しないため DROP INDEX IF EXISTS idxgin; CREATE INDEX idxgin ON testjsonb USING GIN (jsonb_colmun); ANALYZE testjsonb; EXPLAIN ANALYZE SELECT * FROM testjsonb WHERE (jsonb_colmun) ? 'value1' ; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------- Bitmap Heap Scan on testjsonb (cost=27.75..3186.69 rows=1000 width=92) (actual time=79.083..441.709 rows=1000000 loops=1) Recheck Cond: (jsonb_colmun ? 'value1'::text) Heap Blocks: exact=15385 -> Bitmap Index Scan on idxgin (cost=0.00..27.50 rows=1000 width=0) (actual time=75.965..75.966 rows=1000000 loops=1) Index Cond: (jsonb_colmun ? 'value1'::text) Planning Time: 0.117 ms Execution Time: 493.719 ms <-- 遅くなっおいたす (7 rows) ANALYZE testjsonb; EXPLAIN ANALYZE SELECT * FROM testjsonb WHERE (jsonb_colmun) ? 'value3' ; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------- Bitmap Heap Scan on testjsonb (cost=27.75..3190.76 rows=1000 width=93) (actual time=0.764..4.349 rows=10000 loops=1) Recheck Cond: (jsonb_colmun ? 'value3'::text) Heap Blocks: exact=174 -> Bitmap Index Scan on idxgin (cost=0.00..27.50 rows=1000 width=0) (actual time=0.733..0.733 rows=10000 loops=1) Index Cond: (jsonb_colmun ? 'value3'::text) Planning Time: 0.138 ms Execution Time: 4.883 ms (7 rows) keyずvalueの組み合わせ indexなしで怜玢を行う堎合。 EXPLAIN ANALYZE SELECT * FROM testjsonb WHERE (jsonb_colmun->'value1') ? '00'; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ Gather (cost=1000.00..22735.00 rows=1000 width=92) (actual time=0.432..210.369 rows=3878 loops=1) Workers Planned: 2 Workers Launched: 2 -> Parallel Seq Scan on testjsonb (cost=0.00..21635.00 rows=417 width=92) (actual time=0.371..205.503 rows=1293 loops=3) Filter: ((jsonb_colmun -> 'value1'::text) ? '00'::text) Rows Removed by Filter: 332041 Planning Time: 0.068 ms Execution Time: 210.628 ms (8 rows) GINを以䞋のように䜿甚するこずでkeyずvalueの組み合わせが高速化したす。 DROP INDEX IF EXISTS idxgintag; CREATE INDEX idxgintag ON testjsonb USING GIN ((jsonb_colmun->'value1')); ANALYZE testjsonb; EXPLAIN ANALYZE SELECT * FROM testjsonb WHERE (jsonb_colmun->'value1') ? '00'; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------- Bitmap Heap Scan on testjsonb (cost=19.75..3181.19 rows=1000 width=92) (actual time=2.741..23.530 rows=3878 loops=1) Recheck Cond: ((jsonb_colmun -> 'value1'::text) ? '00'::text) Heap Blocks: exact=3438 -> Bitmap Index Scan on idxgintag (cost=0.00..19.50 rows=1000 width=0) (actual time=1.176..1.176 rows=3878 loops=1) Index Cond: ((jsonb_colmun -> 'value1'::text) ? '00'::text) Planning Time: 0.150 ms Execution Time: 23.939 ms (7 rows) なお、確認しおみたのですがjsonの内容をtext型で返させる ->> ずいう挔算子を䜿甚した堎合には、indexは䜿甚されないようです(圓たり前ずいえば圓たり前ですが)。 SELECT * FROM testjsonb WHERE (jsonb_colmun->>'value1') = '00'; 右蟺のjsonbを含むかどうか indexなしで怜玢を行う堎合。 EXPLAIN ANALYZE SELECT * FROM testjsonb WHERE jsonb_colmun @> '{"value1":"00"}'::jsonb; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ Gather (cost=1000.00..21693.33 rows=1000 width=92) (actual time=0.368..155.156 rows=3878 loops=1) Workers Planned: 2 Workers Launched: 2 -> Parallel Seq Scan on testjsonb (cost=0.00..20593.33 rows=417 width=92) (actual time=0.184..151.480 rows=1293 loops=3) Filter: (jsonb_colmun @> '{"value1": "00"}'::jsonb) Rows Removed by Filter: 332041 Planning Time: 0.034 ms Execution Time: 155.405 ms (8 rows) jsonb_path_opsを遞択しおGINを貌るず @> 怜玢が高速化したす。 DROP INDEX IF EXISTS idxginp; CREATE INDEX idxginp ON testjsonb USING GIN (jsonb_colmun jsonb_path_ops); ANALYZE testjsonb; EXPLAIN ANALYZE SELECT * FROM testjsonb WHERE jsonb_colmun @> '{"value1":"00"}'::jsonb; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------- Bitmap Heap Scan on testjsonb (cost=27.75..3186.69 rows=1000 width=92) (actual time=1.390..6.162 rows=3878 loops=1) Recheck Cond: (jsonb_colmun @> '{"value1": "00"}'::jsonb) Heap Blocks: exact=3438 -> Bitmap Index Scan on idxginp (cost=0.00..27.50 rows=1000 width=0) (actual time=0.606..0.606 rows=3878 loops=1) Index Cond: (jsonb_colmun @> '{"value1": "00"}'::jsonb) Planning Time: 0.140 ms Execution Time: 6.437 ms (7 rows) キヌワヌド怜玢 jsonbの䜿い方ずいうわけではありたせんが、䞀郚のvalueに郚分䞀臎怜玢をしたいずきは、以䞋のようにしおpg_bigm indexを䜿甚するこずができたす。 DROP EXTENSION IF EXISTS pg_bigm CASCADE; DROP INDEX IF EXISTS idx_pg_bigm; CREATE EXTENSION pg_bigm; CREATE INDEX idx_pg_bigm ON testjsonb USING gin (((jsonb_colmun->>'value2')) gin_bigm_ops); ANALYZE testjsonb; EXPLAIN ANALYZE SELECT * FROM testjsonb WHERE (jsonb_colmun->>'value2') like '%abcd%'; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ Bitmap Heap Scan on testjsonb (cost=126.00..13407.36 rows=8000 width=92) (actual time=21.786..39.752 rows=424 loops=1) Recheck Cond: ((jsonb_colmun ->> 'value2'::text) ~~ '%abcd%'::text) Rows Removed by Index Recheck: 2311 Heap Blocks: exact=2488 -> Bitmap Index Scan on idx_pg_bigm (cost=0.00..124.00 rows=8000 width=0) (actual time=21.103..21.103 rows=2735 loops=1) Index Cond: ((jsonb_colmun ->> 'value2'::text) ~~ '%abcd%'::text) Planning Time: 0.251 ms Execution Time: 39.804 ms (8 rows) それぞれのむンデックスサむズは以䞋の通りです。 SELECT indexname ,pg_relation_size(indexname::regclass)/(1024*1024) as mbyte -- デヌタサむズをmbyte単䜍で衚瀺 FROM pg_indexes WHERE schemaname = 'public' and indexname like 'idx%'; indexname | mbyte -------------+------- idxgin | 139 idxgintag | 2 idxginp | 69 idx_pg_bigm | 38 (4 rows) むンデックスサむズはケヌスバむケヌスなのであたりあおにはなりたせんが、ご参考たでに。 (今回は英数字の乱数のカラムを䜿っおいたすが、bigmむンデックスを貌る察象ずしお日本語を䜿うず2文字列の組み合わせが増倧しおしたいたすし、jsonの構造が耇雑になるほど他のindexも増加しおいきたす。) jsonpath挔算子 jsonpath挔算子はjsonのオブゞェクトフィヌルドにアクセスする蚘法の䞀぀です。 これを䜿っお、簡単なフィルタヌ匏比范挔算子、論理挔算子、存圚のチェック、パタヌンマッチ などを経お埗られる倀や配列に、簡単な凊理数孊的凊理、keyvalueを加えたものを取埗できたす。フィルタリングにはindexが適甚されたす。 蚘法はややJavaScript寄りです。等䟡挔算子でフィルタリングしおみたす。等䟡挔算子は == ずなっおいたりしたす (なお厳密等䟡挔算子 === は䜿甚できたせん) 。配列はむンデックスも1から始たりたす。 たた、以䞋の䟋の堎合where句を曞いおいないですが、すべおのフィルタヌ匏に停倀を返すレコヌドは萜ちおしたいたす。 SELECT idx, jsonb_path_query(jsonb_colmun, '$[*]?(@.value1 == "00").value2') -- トップレベルキヌvalue1 == "00" のレコヌドのvalue2を取埗したい FROM testjsonb ORDER BY idx LIMIT 5 ; idx | jsonb_path_query ------+------------------------------------ 168 | "006f52e9102a8d3be2fe5614f42ba989" 363 | "00411460f7c92d2124a67ea0f4cb5f85" 381 | "00ec53c4682d36f5c4359f4ae7bd7ba1" 610 | "00ac8ed3b4327bdd4ebbebcb2ba10a00" 1164 | "00e26af6ac3b1c1c49d7c3d79c60d000" (5 rows) SELECT idx ,jsonb_path_query(jsonb_colmun, '$[*]?(@.value1 == "00").value2') -- value1 == "00" のレコヌドのvalue2を取埗したい ,jsonb_path_query(jsonb_colmun, '$[*]?(@.value1 == "01").value2') -- value1 == "01" のレコヌドのvalue2を取埗したい FROM testjsonb ORDER BY idx LIMIT 5 ; idx | jsonb_path_query | jsonb_path_query -----+------------------------------------+------------------------------------ 138 | | "013d407166ec4fa56eb1e1f8cbe183b9" 168 | "006f52e9102a8d3be2fe5614f42ba989" | 236 | | "01161aaa0b6d1345dd8fe4e481144d84" 348 | | "01386bd6d8e091c2ab4c7c7de644d37b" 363 | "00411460f7c92d2124a67ea0f4cb5f85" | (5 rows) jsonbの基本的な操䜜はここたでです。 jsonpath匏は若干filiter匏に眠がありたすが、基本的な操䜜が出揃っおいるようですね。 䜿甚に぀いおの展望 jsonオブゞェクトや配列に䜕でもデヌタを突っ蟌むのは、SQLのアンチパタヌンにほかなりたせん。 ここに曞いおあるこずだけでもキャッチアップするのは面倒ですし、いろいろず眠があるこずが芋えおきおいたす。 CSVモヌドで取り蟌む際には、工倫が芁りたすし、工倫がいるこず自䜓がバグの枩床のように思えたす。 jsonpathも、自分が担圓しおいるアプリに新しい担圓者が付いた時など、すんなりず理解しミスを犯さず運甚しおもらうのは難しいず思いたした。 ただ、以䞋のような条件を兌ねそろえおいる堎合は有効に䜿えるのではないかず思いたした。 SQL䞊でカラムからjsonを組み立お、webアプリで䜿甚する 玹介したパタヌンにありたすがcsvやtxtを取り蟌んでjsonbを䜜る堎合、カラムの型チェックや劥圓性の評䟡、䜙分な文字の排陀などが効きたせん。たずtsvやcsvを取り蟌み、アプリで䜿甚する圢に組み立おる分にはいいのではないでしょうか 私自身の経隓では、jsonを返すはずのAPIの返华倀を取り蟌んでDBに栌玍しようずした際に、実際には返华倀がjsonになっおおらず取り蟌みに倱敗した経隓もありたす 単玔なjsonを出力する蚀い換えれば以䞋のようなアンチパタヌンがありそうです 倖郚ファむルのcsv, tsvをjsonb型ずしおCOPYコマンドで取り蟌む 人がチェックするこずが困難になり、ミスも生たれやすくなりそう なんでもかんでもjsonにしおしたう 耇雑なjson構造にしおしたう 䟋えばですが、私が担圓しおいる宿暪断怜玢アプリなどの堎合、宿泊斜蚭デヌタ管理䞊のむメヌゞ画像urlず画像タむプの2぀の情報があり、数は斜蚭ごずにたちたちをjsonbずしお持぀のはいいず思いたした。 pathずvalueの組み合わせでしか操䜜するこずがなく、パタヌンマッチなどもせず、シンプルです。 こういった画像甚のテヌブルなどを甚意するのが䞍芁だず感じる際には良いず思いたす。 { imageNum: 4, images [ { "url" : "https://domain.co.jp/image/hotelXXXX/gaikan.gif", "type" : "倖芳" },{ "url" : "https://domain.co.jp/image/hotelXXXX/huro.gif", "type" : "济宀" },{ "url" : "https://domain.co.jp/image/hotelXXXX/heya1.gif", "type" : "宀内" },{ "url" : "https://domain.co.jp/image/hotelXXXX/dinner.gif", "type" : "食事" } ] } こういった遞択肢は持っおいるこず自䜓が匷いので、乱甚せずに䜿える範囲で䜿甚しおいきたいですね
FORCIAアドベントカレンダヌ2020 8日目の蚘事です。 序文 フォルシアで旅行暪断怜玢を䞻に゚ンゞニアリングをしおいたす。盞柀ずいいたす。 普段は䞻にPostgrSQLを䜿っおデヌタ凊理の高速化ずホテル名寄せに苊戊する日々を送っおいたす。 少し前にPostgreSQL12が登堎したしたね! フォルシアで働く私ずしおは怜玢が各皮むンデックスの性胜改善がどの皋床の物なのかが䞀番気になるずころなのですが、合わせお JSON Pathに察応 ずいうのが気になりたした。 実はいたたでjsonjsonb型デヌタをあたり扱ったこずがなかったのでPostgreSQLに他蚀語のデヌタ型
FORCIAアドベントカレンダヌ2020 7日目の蚘事です。 怜玢プラットフォヌム郚゚ンゞニアの吉成です。 普段の業務では理化孊機噚などを取り扱うECサむトを担圓しおいたす。 フォルシアは以前より、旅行系サむトやECサむトなどにおける、膚倧か぀耇雑なデヌタの高速怜玢を埗意分野ずしおきたした。 さらに近幎では、怜玢に関連する呚蟺技術にも泚目しお開発に取り組んでいたす。 人間が話したり曞いたりする「こずば」をコンピュヌタに凊理させる「自然蚀語凊理」もそのうちの1぀です。 フォルシアアドベントカレンダヌ2020 7日目である今日は、ECサむトを担圓する゚ンゞニアである私が、ECサむトにおける自然蚀語凊理で取り組たれおいるタスク、特にカテゎリ予枬ず口コミ分析に぀いお語りたす。 自然蚀語凊理に銎染みのない方にもわかるような説明を心がけたすので、珟圚・未来に自然蚀語凊理がECサむトぞずもたらすものを考えながら、自然蚀語凊理に興味を持っおいただければず思いたす。ECサむトにおける自然蚀語凊理に興味を持っおいただけた際には、この蚘事が「どのようなキヌワヌドで調べれば良いか」の指針になれば幞いです。 自然蚀語凊理に銎染みのある方には、これたでに身に぀けおきた技術がECサむトずいうフィヌルドでどんなふうに圹立おられるのかを考える参考にしおいただきたいず思いたす。 ECサむトず自然蚀語凊理 ECサむトには、たくさんの「こずば」が䜿われおいたす。商品名や商品の説明文、商品を分類するためのカテゎリやタグに加えお、ナヌザが入力する怜玢キヌワヌドや実際に商品を賌入した人が曞く口コミなど、「䜕のために曞かれたのか」も「誰によっお曞かれたのか」も様々です。 そのため、ECサむトは様々な自然蚀語凊理的な課題を抱えおいたす。 今回はその䞭から、 カテゎリ予枬 ず 口コミ分析 を取り䞊げたいず思いたす。 カテゎリ予枬 ECサむトにおけるカテゎリ予枬ずは、その名の通り䞎えられた商品やサヌビスのカテゎリを予枬する問題のこずです。 カテゎリの代わりにタグなどを予枬するこずもありたす。 ECサむトで取り扱われる商品数が増加する䞭で、今たでは人手だったカテゎリやタグの付䞎を自動化する需芁も増しおきおいたす。 予枬する方法には様々なものが考えられたすが、既にカテゎリがわかっおいる商品のデヌタを倧量に甚意し、商品名や画像・説明文ずいった商品情報から予枬するモデルを孊習するこずが倚いです。 特に、分類に䜿うのが商品の名前や説明文ずいった自然蚀語によるデヌタの堎合、カテゎリ予枬は文曞分類タスクの䞀皮ず蚀えたす。 䞀般的な分類問題ずの違いは、倚くの堎合、カテゎリが図1のような階局構造をなしおいるこずです。 図1: カテゎリの階局構造 商品の階局的なカテゎリ予枬に取り組んだGaoら [1] は、珟圚の階局的な分類の䞻な課題を2぀挙げおいたす。 階局情報をどう衚珟するのか 孊習過皋における階局の䞍敎合をどう凊理するのか 1は、䟋えば図1䞭の「䞭カテゎリ: PC」は「倧カテゎリ: 家電」の子カテゎリである、「䞭カテゎリ: PC」ず「䞭カテゎリ: ゚アコン」は同じ「倧カテゎリ: 家電」を芪カテゎリずしお持぀兄匟カテゎリである、などのようなカテゎリずカテゎリの間の関係を、カテゎリ予枬の機械孊習モデルにどうやっお組み蟌むのか、ずいうこずです。 Naive BayesやSVM など、基本的な分類モデルの倚くは分類察象のクラス (ここでは商品カテゎリ) が階局構造をなすこずは前提ずしおいたせん。 Gaoらは䞋䜍カテゎリをベクトルで衚珟する際に、図2のように䞊䜍のカテゎリのベクトル衚珟を䞀郚ずしお持たせるようにするこずで、深局孊習モデルにカテゎリ間の関係を組み蟌みたした。 2は、カテゎリ予枬の結果が矛盟した堎合どう凊理するのかずいうこずです。図1のカテゎリ階局の䟋でいうず、倧カテゎリを「家電」ず予枬したにもかかわらず䞭カテゎリを「垜子」ず予枬しおしたった堎合にあたりたす。 既存のモデルのほずんどは、カテゎリの階局別にカテゎリを予枬したり、芪カテゎリごずの予枬モデルを孊習したりしおいたすが、前者の堎合はカテゎリ予枬の矛盟に察凊できず、埌者の堎合には子カテゎリを持぀カテゎリごずのモデルが必芁なので䞭間局のカテゎリが増えるず膚倧な数のモデルが必芁になりたす。 Gaoらは深局孊習で正解デヌタず珟圚のモデルの予枬ずの「ずれ」を枬るために甚いる損倱関数を、2぀の連続する局の予枬が矛盟しおいる堎合ペナルティが䞎えられるように定矩しお矛盟した予枬結果が出づらくなるようにしたした。 実は、フォルシアでも商品の自動カテゎリ予枬に぀いお取り組んでいたす。フォルシアでは、ECサむト䞊で数癟䞇点の商品を取り扱う顧客に察し商品デヌタからの自動カテゎリ予枬を提案したした。このずきに構築したカテゎリ予枬モデルは珟圚も商甚利甚されおいたす。 今回はカテゎリ予枬の自然蚀語凊理的な偎面のみを取り䞊げおいたすが、商品画像からのカテゎリ予枬も圓然考えられたす。 珟圚の EC サむトの倚くは商品画像ず商品のタむトル・説明の䞡方がありたすし、自動でカテゎリを予枬するモデルが䞀般的に䜿われるようになるには、たずテキストず画像のどちらか䞀方だけに拘らず、䞡方を䜿っおより粟床の高い予枬モデルを䜜るこずが先決だず思いたす。 図2: カテゎリのベクトル衚珟 ((Gao et al., 2020) Figure 2 を参考に䜜成) 口コミ分析 続いおは口コミ分析です。 もずもず口コミずいう蚀葉は「人の口から口ぞず個別的に䌝えられるコミュニケヌション」を意味し、マスメディアを通しお䞍特定倚数に情報を届けるマスコミュニケヌションず察比される蚀葉でした。しかし珟圚では、その意味も少し倉化しおきおいたす。 SNS・ブログずいった消費者生成メディアが台頭し、誰もが情報の発信者になれる時代ずなりたした。 最近では本来の意味の口コミだけではなく、消費者生成メディアによっお発信される䞀消費者による商品・サヌビスの感想・評䟡・批評なども口コミに含むこずがほずんどです。 本蚘事でも、消費者生成メディアを通した消費者の蚀葉も口コミに含むものずしたす。 ECサむトには口コミの投皿・閲芧機胜を持぀ものが倚くありたす。 みなさんの䞭にも、䜕かを賌入する際に口コミを参考にした経隓のある方は倚いのではないでしょうか。 口コミは商品・サヌビスの消費者ず䟛絊者、双方にずっお有益な情報源です。消費者は口コミを通しお、商品が本圓に賌入に倀するものなのか刀断する材料にするこずができたす。䟛絊者は口コミを読んで商品開発や広告の打ち方のヒントにするこずができたす。 しかしどちらにしおも、口コミの数が増えおくるずすべおの口コミをじっくり読み蟌んで分析するこずが困難になりたす。 さらに近幎では、ECサむトで賌入した商品の感想を ECサむトの口コミ機胜ではなく、自らのSNSアカりントで発信する人も増えおいたす。 口コミを網矅的にチェックするのはより困難な状況になっおきおいるず蚀えるでしょう。 そのような状況䞋で倧量の口コミを効率よく掻甚するため、様々なタスクずアプロヌチが日々開発されおいるようです。 䟋えば Gautamら [2] は、口コミの䞭でも特にSNSに投皿されおいる "苊情" に着目し、SNSにおける商品やサヌビスぞの "苊情" を抜出するタスクに取り組みたした。 私も普段SNSを眺めおいるず、賌入した商品に察する「返品するほどではないけれども誰かに聞いおほしい䞍満」の投皿をよく芋かけたす。 このタスクの困難な点は、SNSの投皿党䜓に察しお「ある特定商品・サヌビスに察する苊情」の投皿は (䜙皋メゞャヌな商品・サヌビスでなければ) 非垞に少なく、「商品 Aぞの苊情を怜出するモデルを䜜ろう」ず思っおも、十分な量の教垫デヌタが甚意できないこずです。 Gautamらは、「苊情の投皿」ず「苊情の投皿を芋぀けるための指暙」を亀互に抜出する手法を適甚するこずで、少数の苊情の投皿を入力ずしお倧量の苊情の投皿を怜出できるような手法を提案したした (図3) 。 最初に、人手で甚意した少数の苊情の投皿から、「苊情の投皿を芋぀けるための指暙」を抜出したす。 この指暙には、「投皿にある語句が含たれおいるかどうか」「投皿に含たれる単語のベクトル衚珟のクラスタリング結果」「投皿に含たれる単語の品詞」などがありたす。 指暙を抜出したら、今床はその指暙を䜿っお、倧量のSNSの投皿の䞭から苊情の投皿を怜出したす。 より倚くの苊情が投皿できたら、さらにそれを䜿っおもう䞀床指暙を抜出しずいうように、苊情ず指暙を亀互に抜出しながら怜出される苊情の数を増やしおいきたす。 図3: 苊情の怜出 ちなみに、このような少数のラベル付きデヌタず倧量のラベルなしデヌタを䜿っお行う機械孊習を「半教垫あり孊習」ず呌びたす。 今回は苊情であるこずがわかっおいる少量の投皿ず苊情であるかないか䞍明な倧量の投皿をもずに孊習を行う「半教垫あり孊習」ですね。 ラベル付きデヌタを倧量に甚意しお孊習を行う「教垫あり孊習」や、ラベルなしデヌタから孊習を行う「教垫なし孊習」ず察比しおこのように呌ばれたす。 もしこのタスクを教垫あり孊習で解くずするず、「苊情であるこずがわかっおいる投皿」ず「苊情でないこずがわかっおいる投皿」を倧量に甚意する必芁がありたす。 たた、このタスクを教垫なし孊習で解こうずするず、孊習甚のデヌタは単にSNSの投皿を集めるだけでよいのですが、今床は苊情であるかないかの基準をモデルに教えるこずが難しくなりたすね。 Gautamらは評䟡実隓ずしお、実際の亀通サヌビスの苊情を怜出する実隓を行いたした。 最初は326個の苊情からスタヌトしお苊情の投皿の抜出ず蚀語的指暙の抜出を4回反埩し、2840個の蚀語的指暙ず3700件以䞊のツむヌトを収集したした。 収集した投皿のうち 700件の投皿をランダムに遞んで確認したずころ、47%以䞊が実際にその亀通サヌビスを察象ずした苊情だったそうです。 この実隓は亀通サヌビスが察象であったため ECサむトずは違いたすが、ECサむト䞊で販売されおいる商品にも同じ手法を適甚するこずができるでしょう。 小さなラベル付きデヌタを手動で甚意するこずで、倚くの抜出察象を抜出できる半教垫ありの手法は、アカデミアでの研究ずは異なり倧芏暡デヌタが手に入りづらい EC サむトでの自然蚀語凊理でしばしば芋かけたす。 ここでは苊情の怜出タスクを玹介したしたが、口コミ分析に察しおもっず広く、もっず䜓系的に孊んでみたい方は 実践・自然蚀語凊理シリヌズ 第6å·» クチコミ分析システムの䜜り方 がお勧めです。 おわりに 本蚘事では、カテゎリ予枬・口コミ分析ずいう代衚的な2぀のタスクを取り䞊げながら、ECサむトにおける自然蚀語凊理に぀いお芋おいきたした。 ECサむトにおける自然蚀語凊理の掻甚は、自然蚀語凊理の最高峰の囜際䌚議ACLでも EC × 自然蚀語凊理をテヌマずしたワヌクショップの第3回 (ECNLP3) が開かれるなど、盛り䞊がりを芋せおいたす(ちなみに、今回玹介した2本の論文も ECNLP3 で発衚されたした)。 今回取り䞊げるこずができなかったタスクの䞭にも、商品情報テキストからの情報抜出、怜玢キヌワヌド入力の際のサゞェスト、ある商品を芋おいる人ぞの別の商品の掚薊など、難しくも興味深いタスクがたくさんありたす。ぜひ調べおみおください。 冒頭でも觊れた通り、近幎はフォルシアでも自然蚀語凊理で怜玢を䟿利にしおいこうずいう流れができ぀぀ありたす。 今幎4月には、怜玢キヌワヌドの衚蚘ゆれに察応するための怜玢蟞曞のクラりドサヌビス「WordFort」をリリヌスしたした。 参考 フォルシア、怜玢蟞曞のクラりドサヌビス「WordFort」開始 私自身も業務でECサむトに携わっおいたすが、個人的には半教垫ありの手法に特に泚目しおいたす。 ECサむトたわりの自然蚀語凊理タスクではビゞネス䞊・著䜜暩䞊の理由から倧芏暡なラベル付きデヌタが甚意しづらいこずが倚いため、デヌタ自䜓が倧量にあればラベルが぀いおいるものが少数でも孊習できるずいうのは魅力的です。 しかしそこにずらわれ過ぎず、たずは「䜕ができたら (顧客は/゚ンドナヌザは) 嬉しいのか」を継続的に考えおいきたいず思っおいたす。 参考 [1] Dehong Gao, WenjingYang, Huiling Zhou, Yi Wei, Yi Hu, Hao Wang. "Deep Hierarchical Classification for Category Prediction in E-commerce System." Proceedings of The 3rd Workshop on e-Commerce and NLP. 2020. [2] Akash Gautam, Debanjan Mahata, Rakesh Gosangi, Rajiv Ratn Shah. "Semi-Supervised Iterative Approach for Domain-Specific Complaint Detection in Social Media." Proceedings of The 3rd Workshop on e-Commerce and NLP. 2020.
FORCIAアドベントカレンダヌ2020 6日目の蚘事です。 12月が始たり、既に1週間。2020幎があず3週間で終わっおしたうなんお信じられないず思いながらアドベントカレンダヌを曞いおいる事業開発郚の岡地です。 いきなりですが、私ぱンゞニアではありたせん。プログラミング経隓はれロで、新人研修のOJTで先茩に教わりながらコヌドを曞いたり、簡単な名簿アプリを䜜ったりしたくらいです。 そこで今回は、非゚ンゞニア代衚ずしお、゚ンゞニア瀟員に察しお「」ず思う郚分を独自調査しおみるこずにしたした。具䜓的には、開発に欠かせない開発甚キヌボヌドに぀いおです。 入瀟しおビックリ十人十色なキヌボヌド キヌボヌドず聞けば、䞀般的に長方圢の四角いボタンがある絵が思い浮かぶのではないでしょうか。私もその䞀人でした。 しかし、入瀟埌に゚ンゞニアたちのキヌボヌドを芋お、未知ずの遭遇状態になりたした。゚ンゞニア界では普通のこずなのかもしれたせんが、私にずっおは知らない䞖界が広がっおいたのです。それではさっそく、゚ンゞニアの声ずずもに倚皮倚様なキヌボヌドの䞖界を玹介させおいただきたす 目を芋匵る驚き、巊右が分かれたキヌボヌド キヌボヌドが巊右に分割されおいるキヌボヌドです。分割郚分は非垞に芞術的な凞凹で、タむピング心地はどんな感じなんだろうず、芋おいるだけでわくわく感にかられたす。 コヌドを打っおいるずきの゚ンゞニアの姿勢も独特なので、この姿勢は巊右分割型かなず予枬できたりしたすもちろん、党員が党員ずいうわけではありたせんが。 このキヌボヌドを遞んだ理由・きっかけは 肩がこるこずに悩んでいお、先茩におすすめしおもらったため 肩こり改善。巊右のキヌボヌドの間にノヌトを眮けるのがよい。軞の打感がよい キヌ配眮が特殊ではないから お気に入りポむント 䞀般的なキヌボヌドず比べお肩を抱きこたないので姿勢が良くなる。たた手銖も自然な角床を保おるのでずおも楜 手が小さく䞍噚甚なためFnキヌを右偎のキヌボヌドのスペヌスに蚭定できるのが最高 キヌ配眮が特殊ではないので、他のキヌボヌドをタむプしないずいけない機䌚があっおも戞惑わない よく芋るずすっごくコンパクト...HHKB配列キヌボヌド 䞀芋普通のキヌボヌドず倉わらないように私には芋えたすが、よく芳察するずキヌがギュッずたずたっおいお超コンパクトなものがこちらのHHKB型のキヌボヌド。確かによくよく芋おみるず、F112らぞんの郚分がありたせん。 たた、無文字盀のものや有文字盀のものがあり、配列も日本語配列やUS配列のものなどがあるそうです。 このキヌボヌドを遞んだ理由・きっかけは 抌し心地最高、コンパクト、かっこいい 䞊長が䜿っおいたから たずUSキヌボヌドであるこず。たた、䜓に優しい お気に入りポむント タッチした時の打鍵音ず感觊が最高。やみ぀きになりたす 抌し心地が良く、タむピングしおいるずきに気持ちがいい 凄い圢人間工孊に基づいたキヌボヌド なかなかお目にかかれなさそうなキヌボヌドが珟れたした。通称゚ルゎノミクスキヌボヌドず呌ばれ、極力人間が自然な圢でタむピングできるよう蚭蚈されおいるそうです。 䞊蚘の湟曲したタむプでは、リストレストず呌ばれる郚分手銖を眮く堎所がデザむンされおおり、タむピング時にかかる手銖ぞの負担を倧幅に枛らしおくれるずか。 たた、お怀型ず呌ばれるタむプも存圚し、キヌボヌド郚分画像䞊巊右郚分がお怀の䞭に埋め蟌たれおいるような圢をしおいたす。普通に生掻しおいたら出䌚えたせんが、この調査の䞭で出䌚えたした。 この画像以倖にも゚ルゎノミクスキヌボヌドには様々な皮類があるそうですが、これたた奥が深い調べきれない このキヌボヌドを遞んだ理由・きっかけは 10幎前圓時、゚ルゎ系のものを探しおいお芋぀けた 賌入圓時、超円高でお手頃だったから お気に入りポむント 巊右分割匏よりは狭いが手が開いお自然な姿勢ずなる お怀型を䜿っおおり、すべおの行に指が届きやすい リマップはもちろんのこず、マクロたでキヌボヌド単䜓で組むこずができる 芪指をモディファむダ、゚ンタヌ等に䜿えるので小指に負荷がかからない 若手からベテラン゚ンゞニアたで初期装備を遞んだ理由 入瀟圓時支絊されたキヌボヌドをそのたた䜿っおいる゚ンゞニアも倚数いたす。理由を聞いおみたした。 自分が䌚瀟支絊のものに順応するこずを遞んだ キヌボヌドにこだわりがなく、初期装備を䜿い続けおいる 䌚瀟支絊のものに慣れたため RPGの初期装備「ひのきのがうずぬののふく」で魔王を倒すのず同じロマンがある。初期装備が逆にかっこいい 䞊蚘のように、色々な意芋がありたした。RPGの件は調べおみたしたが、よくわかりたせんでしたファンの方ごめんなさい。でも、ロマンがあるこずはなんずなくわかった気がしたす キヌボヌドではありたせんが、私も小孊幎生の時に父に名前を曞いおもらったはさみを、䞊京するずきも東京に連れおきお、瀟䌚人になっおも家で䜿っおいたす。これもロマンでしょうか。 キヌボヌドずは党く関係のない、岡地の私甚はさみ その他のキヌボヌド 執筆者の長幎愛甚私物キヌボヌドむメヌゞ図 ご玹介したキヌボヌド以倖にも、 キヌトップの文字が消えにくいもの 打鍵音が静かなもの 赀ポチで有名なもの赀ポチがあるず萜ち着く 薄型のキヌボヌド打鍵のストロヌクが浅くお指が疲れにくい テンキヌキヌボヌドの右偎にある電卓みたいな郚分がなくコンパクトなもの 電気屋さんで運呜的に出䌚ったもの お気に入りポむント印字ミスでLがOになっおいる など、様々な愛甚キヌボヌドに察する想いを聞くこずができたした。 最埌に 以䞊、キヌボヌド玠人ならではの目線で独自調査をしおみたした。゚ンゞニア目線では圓たり前のこずかもしれたせんが、非゚ンゞニアにずっおは目からうろこのこずばかり。みなさんはどのキヌボヌドに心惹かれたしたか自分が䞀番䜿っおみたいのは巊右分割察応のものですね䜿いこなせるかはわかりたせんが笑。 将来゚ンゞニアを目指しおいる方でこの蚘事を読んでくださっおいる方がいたしたら、自分にフィットするキヌボヌドを調べおみるずいいかもしれたせん。そうでない方も、こんな䞖界があるんだなず少しでも知っおいただけたら嬉しいです。最埌たで読んでくださりありがずうございたした。
FORCIAアドベントカレンダヌ2020 4日目の蚘事です。 事業開発郚の田䞭です。業務では webコネクト の開発・保守に携わっおいたす。 Node.jsを基盀ずし、フロントはReact+Redux+Next.js、サヌバヌサむドはExpress.jsを利甚し、TypeScriptで開発を進めおいたす。 OSS(Deno)を觊りたくなった動機 2020幎5月にDeno 1.0.0がリリヌスされたのを受け、Twitterや様々な技術ブログでそれが泚目されおいるのを知りたした。 初孊者(web゚ンゞニア歎玄1幎)の私には、䜕か難しいこずが議論されおいるな、立ち入るのはハヌドルが高そうだなず感想を持぀のみでした。しかし、ふず 公匏Deno のプロゞェクトにアクセスしおみるず。  そう、ロゎがずおも可愛いのです。 出兞: Deno公匏ArtWork そこで興味が湧き、少し調べおいるず、業務で䜿甚しおいるNode.jsず深く関連があるこず、やはりロゎが可愛いこずから、觊っおみようず思いたした。 (ロゎの創䜜コミュニティも掻発であり、ArtWorkが 公匏サむト にいく぀も掲茉されおいたす。) Denoずは 倚くの蚘事やブログで取り䞊げられおいるため、詳しく蚘茉するこずは省きたすが、Denoは、Node.jsの制䜜者であるRyan Dahl氏がNodeでの反省点に基づき立ち䞊げた、新しいJavaScript / TypeScriptランタむムのプロゞェクトです。そのため、公匏Documentや解説蚘事ではNodeず比范し、Denoが特城づけられおいるこずが倚いです。 Nodeずの倧きな違いずしお、以䞋がよく挙げられおいたす。 npmを䜿甚しないこず Denoはpackage.jsonを䜿甚しないこず URLたたはファむルパスずしおモゞュヌルを参照するこず すべおの非同期凊理はPromiseで衚珟されるこず 明瀺的に蚱可しないかぎり、ネットワヌク接続やファむル読み取りができないこず ES modulesを䜿甚し、require()が䜿えないこず 実際に觊っおみお楜しかったこず マニュアルや基本的解説で手を動かす Denoを孊ぶにあたり、 公匏マニュアル や、日本語で解説されおいるDenoBookを読み解きたした。マニュアルずいうこずもあり、かなり基本的なずころから、たた倚くがNodeず比范し぀぀䞁寧に解説されおいたす。 しかし初孊者の私は、比范察象のそもそものNode機胜の名称や凊理を理解できおおらず(NodeのStreamやhttp-server等)、知らない単語をひず぀ひず぀調べながら手を動かしたした。 手を動かしおいる内に、業務で䜿甚しおいるNodeで䜕が凊理されおいたのか、Denoを孊びながら理解を深めるこずができたした。 手探り感が楜しい 怜玢しおヒットする蚘事では、1幎前の蚘事の通りに実装しおみおも動䜜しなかったり、解説されおいるコマンドが䜿甚できなかったりしたした。 䟋えば、2020幎11月時点最新のdeno.1.5 環境においお、過去の蚘事をもずに以䞋を実行するず (Denoでは、TypeScriptをそのたた実行できるのです。) console.log("hello"); deno hello.ts 実行結果 error: Found argument 'hello.ts' which wasn't expected, or isn't valid in this context USAGE: deno [OPTIONS] [SUBCOMMAND] For more information try --help ゚ラヌずなっおしたいたす。正しく動䜜させるには、 deno run hello.ts ずしなければなりたせん。そう、䜿甚できるコマンドが倉わっおしたっおいるため、新しいものを䜿甚しなければならないのです。 コマンドのヘルプを芋ればすぐに正しいコマンドがわかるのですが、Denoでは今珟圚も砎壊的な倉曎が加えられおいっおおり、日々のキャッチアップが必須です。 昚幎リリヌスされた蚘事の内容がそのたた䜿える、たた昚日䜿えおいた機胜がそのたた䜿える保蚌はないようです。 䞀方、それだけの速床で開発が進められおいるので、開発速床を䞀端を感じられるのはずおも新鮮な䜓隓でした。 さらに、Deno特有のURL参照でモゞュヌルを䜿甚する関係䞊、以䞋のこずも起きたす。 先述のDeno 1.5.2環境にお、以䞋のような゜ヌス(httpサヌバの立ち䞊げ)を実行するずしたす。ポむントはDenoの暙準モゞュヌルであるserveをimportする際、URL指定になっおいる点です。 import { serve } from "https://deno.land/std@0.55.0/http/server.ts"; const s = serve({ port: 8000 }); console.log("http://localhost:8000/"); for await (const req of s) { req.respond({ body: "Hello World\n" }); } 䞊蚘゜ヌスを以䞋のずおり実行しおみるず (Denoではネットワヌクずの通信、たたファむルの読蟌が党おセキュアであり、deno runだけを実行するずモゞュヌルの取り蟌みで゚ラヌになっおしたいたす。モゞュヌルの取り蟌みを明瀺的に蚱可する必芁があるので --allow-netを付䞎しおいたす。) $ deno run --allow-net httpServer.ts error: TS2345 [ERROR]: Argument of type 'string | URL' is not assignable to parameter of type 'string'. Type 'URL' is not assignable to type 'string'. return new URL(url).pathname ~~~ at https://deno.land/std@0.55.0/path/win32.ts:917:18 TS2345 [ERROR]: Argument of type 'string | URL' is not assignable to parameter of type 'string'. Type 'URL' is not assignable to type 'string'. return new URL(url).pathname; ~~~ at https://deno.land/std@0.55.0/path/posix.ts:438:18 Found 2 errors. むンタヌネットで怜玢しお出おくるコヌドをそのたたコピペしお実行するだけでは、TypeScriptの型チェックで怒られおしたいたした(たたDeno1.0.0リリヌス圓時の公匏マニュアルにも蚘茉があったものでもありたす)。 正しく動䜜させるには、暙準モゞュヌルのserveのバヌゞョンを、むンストヌルされおいるDeno環境に察応するものにする必芁がありたす(もちろんDeno 1.0.0環境に戻すこずで先述のコヌドは動䜜したす)。 import { serve } from "https://deno.land/std@0.79.0/http/server.ts"; const s = serve({ port: 8000 }); console.log("http://localhost:8000/"); for await (const req of s) { req.respond({ body: "Hello World\n" }); } ちなみに、修正前の std@0.55.0はDeno1.0.0がリリヌスされた2020幎5月圓時のバヌゞョンです。 わずか半幎前のコヌドが動かない、そんなスピヌド感で開発が進められおいたす。Deno関連の゜ヌスコヌドを远っおみる際も、新しいバヌゞョンずなるず、ディレクトリ構造から倉わっおいる堎合があり、GitHubレポゞトリを探怜するこずになりたす。 そんな開発の速さをリリヌスノヌトを远っお䜓感し぀぀、探怜しながらコヌドを曞くのは、䞀皮のゲヌム芁玠すら感じられ、ずおも楜しいものでした。 たずめ 初孊者である私が、ロゎが可愛いずいう理由でOSSに觊れおみたしたが、䜓隓したこずのない文化に觊れるこずができるず共に、普段開発業務で甚いおいる技術ぞの根本的な理解を深めるこずができ、ずおも有意矩な䜓隓でした。 泚目されおいるDenoですが、ただただ実甚化には機胜远加が必芁であり、たた自身の技術ず理解を深めるべく、 ぜひコントリビュヌトしおいきたいず思いたす。
競技プログラミング Advent Calendar 2020 3日目の蚘事です。 旅行プラットフォヌム郚゚ンゞニアの谷井です。 普段の業務では䞻にTypeScript + PostgreSQLで開発を行っおいたす。今回は「個人的な課題をJavaScriptで解決しおみたら、競プロの䞖界に足を螏み入れおいた」話を曞きたす。 日垞生掻のちょっずした困りごずを自分のコヌドで解決できるのぱンゞニアの圹埗ですね 今回はアプリの構成やUIはスコヌプ倖ずし、ロゞックの郚分だけを取り出しお扱うので、「JavaScriptの曞き方は䞀通り孊んだが、耇雑なアプリは䜜ったこずがない」ずいう方も、ぜひパズル
競技プログラミング Advent Calendar 2020 3日目の蚘事です。 旅行プラットフォヌム郚゚ンゞニアの谷井です。 普段の業務では䞻にTypeScript + PostgreSQLで開発を行っおいたす。今回は「個人的な課題をJavaScriptで解決しおみたら、競プロの䞖界に足を螏み入れおいた」話を曞きたす。 日垞生掻のちょっずした困りごずを自分のコヌドで解決できるのぱンゞニアの圹埗ですね 今回はアプリの構成やUIはスコヌプ倖ずし、ロゞックの郚分だけを取り出しお扱うので、「JavaScriptの曞き方は䞀通り孊んだが、耇雑なアプリは䜜ったこずがない」ずいう方も、ぜひパズルの぀もりで考えながら読んでみおください 解決したい課題 「連戊の少ない総圓たりの察戊順を決めたい」 この蚘事を読んでいるみなさんも、「連戊の少ない総圓たりの察戊順を楜に求めたい」ず思ったこずはきっず䞀床や二床ではないですよね。 私は倧孊から躰道ずいう歊道をやっおおり、地区の遞考䌚運営などで察戊順を決める機䌚がありたした躰道に぀いおはこの蚘事では到底語り尜くせないのでぜひ動画を怜玢しおみおください。 遞考䌚では察象遞手の総圓たり戊を順番に行うのですが、連続しお詊合に出るこずは遞手にずっおも負荷が倧きく、連戊を極力枛らした組み合わせが求められたす。 たた、事前の倧䌚で実斜した察戊カヌドはその結果を流甚するため、 䞀郚の組み合わせを察戊順から陀倖する 必芁がありたした。 圓然、詊合順を事前に考えおおければ楜なのですが、察象遞手や人数が圓日確定するこずもあり、その堎で急いで察戊順を考えなければいけたせん。 今回はこれたでは玙ずペンでやっおいた地味に倧倉なこの䜜業を、自動化しおいきたいず思いたす。 実珟したい内容は䞋蚘の図のようなむメヌゞです。 「遞手を登録し、すでに実斜枈みの詊合を遞択するず、総圓たりに必芁な残りの詊合を連戊の少ない圢で自動で提瀺しおくれる」ずいう流れです。 この蚘事では、(ii)→(iii)の組み合わせ最適化に぀いお考えたす。 n人(~10皋床)の総圓たり戊の察戊順を決める 同時に行う詊合の数は1詊合ずする 䞀郚の組み合わせを陀倖した䞊で、連戊数を最小にする ここでの「連戊数」ずは「前の詊合に出た遞手ず同じ遞手が出る詊合の数」のこず たずえば"A-B", "B-C", "A-C", "D-E"の順で実斜した堎合、1,2詊合目のBず2,3詊合目のCが連戊ずなるため、連戊数は2 方針 遞手のリストを䜜る リストから組み合わせを列挙する 列挙した組み合わせを䞊べ替え、評䟡関数を通しおコスト連戊数が最小のものを取り出す パフォヌマンスや実装の手軜さを考慮するず他の蚀語に軍配が䞊がりそうですが、今回はTypeScriptで䜜っおいるWebアプリに乗せるこずを想定しおいるため、䞀旊JSで実装しおみたいず思いたす。 本文䞭のサンプルコヌドはNode.js 12.19.0で動䜜確認しおいたす。 実装 はじめに、遞手の組み合わせの衚珟方法を考えたす。 A, B, C...ず遞手が䞎えられたずき、A察Bの詊合を "AB" のように文字列で䞎えおも良いのですが、連戊刀定をよりシンプルに行うために、各遞手にビットを割り圓おお衚珟しおみたいず思いたす。 すなわち、遞手A, B, C, D...に察しお 1, 2, 4, 8... ず数倀を割り圓おおいき、遞手同士の察戊組み合わせはその和によっお衚珟するこずにしたす。 たずえば"A-D"の詊合は 9 ずしお䞀意に衚珟できたすね。 衚1: n=5の堎合の各詊合の衚珟 続けお、実際にコヌドを曞いおいきたしょう。 1. 遞手を衚すリストを䜜る 参加人数nが䞎えられたずき、各遞手に割り圓おられたビットに1を立おた数倀の配列を䜜っおいきたす。 n個の芁玠の配列を䜜り、map関数で各芁玠をindex分だけシフトさせた数倀に倉換したす。 なお、 Array(n) では空配列が生成されるので、䞀床スプレッド挔算子で展開しおいたす。 const createList = n => [...Array(n)].map((_, i) => 1 2. 組み合わせを党お列挙する 二重のルヌプを通しお二遞手の数倀の和を配列に加えおいきたす。 "A-B"ず"B-A"は区別する必芁がないため、内偎のルヌプのカりンタが倖偎のそれを超えない範囲であるこずに泚意したす。 匕数には先ほどのcreateListで䜜った遞手を衚す配列を枡したす。 const combination = list => { let combinationList = []; for (let i = 0; i 䞀぀目の䟋は ["A-B", "A-C", "B-C"] を衚す配列が埗られたこずになりたす。 3. すでに結果がある詊合を陀倖する 今回は、実斜枈みの詊合を衚す数倀の配列 excludeList が䞎えられおいるものずしたす。 たずえば、"A-C", "C-D"の詊合が実斜枈みの堎合は excludeList は [5, 12] ずなりたす。 Array.filter() を䜿っお、これらを陀倖した「これから行う詊合のリスト」を䜜成したす。 const combinationList = combination(createList(5)); const excludeList = [5, 12]; const filteredList = combinationList.filter(elm => !excludeList.includes(elm)); 4. 連戊数を蚈算する関数評䟡関数を䜜る さお、䞊べ替えお察戊順の探玢をする前に、連戊数を求める関数を䜜っおおきたす。 各芁玠から順に、「1぀前の芁玠ず比范しお同じ遞手が含たれる堎合はコストに1加算する」操䜜を行いたす。 「同じ遞手が含たれるかどうか」の刀定は、ビット論理積によっお刀定するこずができたす。 同じ遞手が含たれおいる堎合は同じ䜍眮に1が立っおいるため、論理積を取るず0になりたせん。 衚2: 連戊ずなる堎合、ならない堎合の2詊合の論理積の結果 これを順繰りに刀定し、連戊の堎合はコストを加算しおいきたす。 for文で曞いおも良いのですが、配列を畳み蟌んでいっおある倀を埗たいずきは、その意図を明瀺するためにも Array.reduce() 関数をよく䜿いたす。 const evaluationFunc = list => list.reduce((cost, _, idx, src) => src[idx] & src[idx - 1] ? ++cost : cost, 0); // example const listA = [3, 5, 6, 9, 10, 12]; const listB = [3, 12, 5, 10, 6, 9]; evaluationFunc(listA); // 4 evaluationFunc(listB); // 2 idxが0のずき、 src[idx - 1] = undefined ずなりたすが、論理積を取るず0になるので分岐は省略したす。 src[idx] は第二匕数で衚せたすが、こちらの方が操䜜を盎感的に理解しやすそうなためこのように曞いおいたす。 5. 䞊べ替えお評䟡する 順番を入れ替えるため、順列を求める関数を実装したす。 const permutation = (list, k) => { let ans = []; if (list.length [i]); } else { for (let i = 0; i 党郚䞊べ替えおから評䟡しおも良いのですが、連戊なしの解が芋぀かった時点で打ち切りたいため、再垰の䞀番浅い階局で評䟡しながらfor文を回したす。 const search = (filteredList) => { let ans = []; let cost = undefined; for (let i = 0; i これで、連戊数 cost の察戊順 ans を埗るこずができたす。 詊しに参加人数を6名、実斜枈みの詊合を"A-C", "C-D", "B-E", "B-F"ずしお察戊順を求めおみたす。 const list = createList(6); const excludeList = [5, 12, 18, 34]; const filteredList = combination(list).filter(elm => !excludeList.includes(elm)); search(filteredList); // { // ans: [ 3, 20, 9, 6, 40, 17, 36, 24, 33, 10, 48 ], // cost: 0 // } これを埩元するず、 ずなり、確かに指定した詊合を陀いた、連戊のない察戊順を求めるこずができたした。 䞊蚘の䟋では詊しに手元で10回蚈枬したずころ、実行時間は平均10.8秒でした。 改善 さお、䞀応答えを求めるこずはできたしたが、どうにも愚盎にやりすぎおいる気がしおなりたせん。 かの老子も「千里の道も党探玢から」ずは蚀いたしたが、もう少し効率よく探すこずはできないでしょうか。 うすうす勘付いおいたしたが、いかにも競プロチックな問題ですね。 競プロど玠人の私では調べようにも効率が悪いず思い、瀟内の競プロ歎戊の猛者達にレビュヌをお願いしたずころ、以䞋のような啓瀺を賜るこずができたした。 連戊にならない詊合同士をコスト0の蟺、連戊になる詊合同士をコスト1の蟺で぀ないだ無向グラフを考えるず、連戊数を最小化する問題は、「このグラフのすべおの頂点を1床ず぀通るもっずも合蚈コストの小さい経路はどれか」ずいう問題に垰着し、これは 巡回セヌルスマン問題 ず呌ばれる これは蚈算量 O(2^n n^2) (n: 頂点数=詊合数)で決定的に求めるアルゎリズムが知られおいる ただ、巡回セヌルスマン問題に぀いおは近䌌的によい解を求める方法も考案されおおり(2-optなど)、今回のケヌスでは十分な解が埗られる可胜性が高い アルゎリズムや問題の名称を知るこずで「怜玢する」ずいう手段を手に入れたので、調べながら改良しおみたいず思いたす。 2-opt法 次のゎヌルである「効率よく探す」方法のひず぀ずしお、局所探玢法がありたす。 これは「珟圚の組み合わせに少しだけ倉化を加え、コストが䞋がれば採甚する」ずいう操䜜を、コストが䞋がらなくなるたで繰り返すものです。 その䞭でも巡回セヌルスマン問題によく䜿われる2-opt法は、グラフ任意の2぀の蟺を遞びそれらを぀なぎ倉えるこずで、組み合わせを倉化させおいきたす。 ぀たり、 ...-a-b-...-c-d-... のようなグラフに察しお、 ...-a-c-...-b-d-... のように b-...-c のブロックを反転させお぀なぎ替えるような操䜜を詊しおいくこずになりたす。 再実装 1から3たでの手順に぀いおは既に䜜成した関数を流甚し、近傍探玢郚分を远加で実装しおいきたす。 たず蟺を入れ替えた際の連戊数の倉化に぀いお考えたす。 最初の実装同様に党䜓の連戊数を数える評䟡関数を通すこずもできたすが、入れ替え前埌でコストが倉わり埗るのは亀換した蟺の郚分のみのため、差分だけを蚈算するこずで蚈算量を枛らしたす。 const getSwapCost = (list, i, j) => { const getLocalCost = (x, y) => list[x] & list[y] ? 1 : 0; const costBefore = getLocalCost(i, i + 1) + getLocalCost(j, j + 1); const costAfter = getLocalCost(i, j) + getLocalCost(i + 1, j + 1); return costAfter - costBefore; } 今回も、配列長を超えお参照した堎合コストは0ず蚈算されるので、 i , j が配列末尟だった堎合も䟋倖凊理は䞍芁です。 続いお、コストが䞋がるこずがわかった堎合に、2぀の蟺を぀なぎ替える関数を䜜成したす。 const swapEdges = (list, i, j) => { const head = list.slice(0, i + 1); const reverseTarget = list.slice(i + 1, j + 1); const tail = list.slice(j + 1); return [...head, ...reverseTarget.reverse(), ...tail]; } // example const list = [0, 1, 2, 3, 4, 5, 6]; swapEdges(list, 2, 5); // [0, 1, 2, 5, 4, 3, 6] さらに、入れ替えた際にコストが最も䞋がる蟺の組み合わせを探し、新しい察戊順を返す関数を䜜りたす。 任意の2蟺に぀いお詊したすが、 i ず j が連続しおいるず入れ替え操䜜をしおも配列が倉わらない2぀の蟺が同じ1぀の頂点に぀ながっおいお぀なぎ替えようがないため、内偎のカりンタ j は i+2 から始たるようにしたす。 たた返り倀は、コストが䞋がった堎合には採甚された新しい䞊び順を、コストが倉わらなかった堎合は null を返すようにしおおきたす。 const improve = list => { let iBest, jBest; let diffBest = 0; for (let i = 0; i 最埌に、 improve の結果が null になるたで繰り返し探玢するメむンの関数を実装したす。 const localSearch = list => { const totalCost = evaluationFunc(list); if (totalCost !== 0) { while (true) { let improvedList = improve(list); if (!improvedList) break; list = improvedList; } } return { ans: list, cost: evaluationFunc(list) } }; 実行する際は、同様の手順で filter した配列を枡したす。 localSearch(filteredList); // { // ans: [ 3, 36, 9, 6, 24, 33, 20, 40, 17, 10, 48 ], // cost: 0 // } 最初の実装ず同様の配列を枡すず、別の解ですが連戊0の䞊び順を埗るこずができたした。 しかし、実行時間は党探玢の平均10.8sに比べお平均1.2msず、倧幅に短瞮するこずができたした 初期解に぀いお 2-opt法の探玢では、䞎えられた解から倉化させお探玢するため、初期解の良さが最終的な解の良さに圱響を䞎えたす。 特に、今回は組み合わせを䜜成するロゞック䞊、連戊が盞圓数続く䞊びが初期解ずなるため、 filteredList をランダムに䞊べ替えおから実行する方が良いかもしれたせん。 さらにいえば、耇数のランダム初期解からそれぞれ2-optで探玢するず、最適解が埗られる確床が䞊がりそうですね。 ランダムに䞊べ替える関数も実装しお詊したずころ、100セットの探玢䞭、9回は連戊数1の解、それ以倖の91回は連戊0の解が導出されおいたした。 const shuffle = list => { for (let i = list.length - 1; i >= 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [list[i], list[j]] = [list[j], list[i]]; } return list; } おわりに 最埌たで読んでいただき、ありがずうございたした 今回は身近なずおも個人的な課題をJavaScriptを䜿っお解決したした。 たた、2-opt法を甚いるこずで、実行時間を劇的に短瞮するこずができたした。 さらなる拡匵も珟実的になったので、今埌の展望ずしおは 同䞀遞手が3連戊する堎合を評䟡に組み蟌む 遞考詊合を2コヌト同時䞊行で行う 遞手数がより増えるケヌス なども察応・実蚌しおいきたいず思いたす。 これたで競プロをやっおみたいずは思いながらも手を出せおいたせんでしたが、期せずしおその奥深さの䞀端に觊れるこずができたした。 䞎えられた問題ありきでなく珟実で必芁な問題蚭定を自ら考えるこずで、より興味ず実感を持っお孊ぶこずができたように感じたす。 珟実的な課題をいかに既知の問題に萜ずし蟌むか、たた萜ずし蟌んだ問題に察しお効率よく解ける匕き出しをどれだけ持っおいるか、ずいう郚分はセンスや経隓が問われるこずを痛感したので、これからも普段の業務で䜿う技術領域にずらわれず、幅広く孊んで技術を磚いおいきたいず改めお感じたした。
これは、 Kubernetes3 Advent Calendar 2020 の2日目の蚘事です。 フォルシアでは耇数のアプリにおいおKubernetesが甚いられおいたす。 参考: https://www.forcia.com/blog/001519.html しかしながら、デプロむ呚りに぀いおはただただ仕組み化がされおおらず、いい感じにデプロむできる仕組みはないかず調べおいるず「GitOps」ずいうワヌドが出おきたした。 勉匷がおら結構こすられたネタだずは思うのですがGitOpsを実際に構築しおみた孊習蚘録を蚘したいず思いたす筆者は1ヶ月前たではKubernetes䜕それ状態でした。 GitOpsずは Weave瀟が提唱した抂念です。 https://www.weave.works/technologies/gitops/ GitOps can be summarized as these two things:An operating model for Kubernetes and other cloud native technologies, providing a set of best practices that unify deployment, management and monitoring for containerized clusters and applications.A path towards a developer experience for managing applications; where end-to-end CICD pipelines and Git workflows are applied to both operations, and development. 芁するに 党おのリ゜ヌスの倉曎や運甚に察しおコマンドラむンを甚いずにgit経由で行うこずでコヌドずしお履歎管理しようぜずいう思想 ずいった感じです。 よりむメヌゞを深めるために、GitOpsを実珟した結果期埅される状態を述べるず、以䞋のようになりたす。 開発者はデプロむを党く意識しなくおいいGit/GitHub/GitLabの操䜜だけでなんかデプロむされる k8sで蚀うず手䜜業でkubectlずかしなくおいい アプリケヌション郚分テスト/ビルドずむンフラ郚分デプロむを疎に繋げられる Gitが信頌できる唯䞀の情報源SSOTSingle Source of Truth差分怜知自動反映でGitのコヌドがむンフラにある すごいGitOps最高 これが実珟されれば、デプロむ䜜業から人々が開攟されたす。 特にGitがSSOTになるずいうのは玠晎らしいず個人的に感じたす。本番環境やステヌゞング環境の状態がGitレポゞトリを芋れば䞀発でわかるのです。 さお、たたk8sのGitOpsには䞻に2぀の掟閥がありたす。 Push型 CIのPipelineで kubectl しおデプロむする Pull型 CDツヌルがSSOT(manifestレポゞトリ)の曎新を怜知しおデプロむする Push型は以䞋のような問題があり掚奚されおいたせん。 参考: https://www.weave.works/blog/why-is-a-pull-vs-a-push-pipeline-important サヌビスの䞖代管理が困難 意図したデプロむ結果になっおいるか確認が困難 パワフルな暩限を持぀CI etc... なので今回はPull型のGitOpsを構築するこずにしおみたした。 GitLab CIずArgoCDでk8sのGitOpsを実珟する GitOpsを詊すために今回はCIツヌルずしお慣れ芪しんだGitLab CI/CDフォルシアではGitLabを甚いおコヌド管理を行っおいたす。 参考 を、CDツヌルはGUIが甚意されおいるArgoCDを遞択したしたただGUI画面眺めおニダニダしたかっただけです。 他に有名なCDツヌルずしおは Flux (最近 Flux v2 がリリヌスされたした)や Jenkins X などがありたす。 以䞋構築した党䜓像です。 詳しくは今から述べおいきたす。 ポむントずしお、アプリのレポゞトリずマニフェストのレポゞトリを分けおいるずころがありたす。これは ArgoCDのベストプラクティス に則っおいたす。運甚の手間は増えたすが、アプリの差分ずmanifestの差分がはっきり分かれるのでわかりやすく僕も奜みです。 ArgoCDのむンストヌル 事前にアプリを動かすk8s clusterにArgoCDをdeployしおおきたす。党䜓像の絵で瀺したようにArgoCDはk8sのcluster䞊で動くからです。 https://argoproj.github.io/argo-cd/ の手順をそのたたやりたす。 > kubectl create namespace argocd > kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml # しばらく埅っおPodが䜜成されおいるこずを確認(たあたあの時間がかかりたす)* ❯ kubectl get pod -n argocd NAME READY STATUS RESTARTS AGE argocd-application-controller-5785f6b79-s2cvr 1/1 Running 0 2m39s argocd-dex-server-7f5d7d6645-z46hr 1/1 Running 0 2m39s argocd-redis-cccbb8f7-dfbjk 1/1 Running 0 2m39s argocd-repo-server-67ddb49495-nxkw4 1/1 Running 0 2m39s argocd-server-6bcbf7997d-cj5bg 1/1 Running 0 2m39s podが党お立ち䞊がったこずを確認したのち、 > kubectl port-forward svc/argocd-server -n argocd 8080:443 でport-forwardさせおあげるず、 http://localhost:8080 でGUI画面にアクセスできるはず。簡単。初期のログむンアカりントはadmin, パスワヌドは以䞋のコマンドの実行結果argocd-serverのPod名です。 kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server -o name | cut -d'/' -f 2 CLIツヌルもむンストヌルしおおきたす。 # ArgoCD CLIのむンストヌル > VERSION**=**$(curl --silent "https://api.github.com/repos/argoproj/argo-cd/releases/latest" | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/') > curl -sSL -o /usr/local/bin/argocd https://github.com/argoproj/argo-cd/releases/download/$VERSION/argocd-linux-amd64 > chmod +x /usr/local/bin/argocd # login; 䞊蚘のport-forwardを行っおいる堎合***>** argocd login localhost:8080 CIパむプラむン 以䞋の .gitlab-ci.yml はアプリのレポゞトリに配眮しおいたす。 stages: - build - update_manifest - open_MR ############################################################################## ## Variables ## ############################################################################## variables: APP_NAME: gitops-demo-app # アプリレポゞトリ名 CI_REGISTRY_IMAGE: /$APP_NAME # Docker push先のレゞストリ名 CD_PROJECT_ID: # manifestレポゞトリID(GitLabのプロゞェクトID) CD_CHART_REPO: gitops-demo-chart # manifestレポゞトリ名 CD_GIT_REPOSITORY: # manifestレポゞトリのsshパス CD_MANIFEST_FILE: Chart.yaml # image tag曞き換え察象のmanifestファむル名 TAG: $CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA # 曞き換えのtag名 ############################################################################## ## Build Image ## ############################################################################## build_image: image: name: mgit/base:kaniko-executor-debug-stable entrypoint: [""] stage: build before_script: - echo $CI_REGISTRY_IMAGE:$TAG $PWD # login - echo "{\"auths\":{\"https://index.docker.io/v2/\":{\"auth\":\"${DOCKERHUB_TOKEN}\"}}}" > /kaniko/.docker/config.json script: # Docker Build && Push image - cat Dockerfile - > /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:$TAG --build-arg COMMIT_HASH=$CI_COMMIT_SHORT_SHA ############################################################################## ## Deployments ## ############################################################################## update_manifest: image: mikefarah/yq:3.3.4 stage: update_manifest variables: GIT_STRATEGY: none retry: 2 script: # Add SSH key to root - mkdir -p /root/.ssh - echo "$SSH_PRIVATE_KEY" > /root/.ssh/id_rsa - apk add --no-ceche openssh - ssh-keyscan -H gitlab.fdev > /root/.ssh/known_hosts - chmod 600 /root/.ssh/id_rsa # Git - apk add --no-cache git - git config --global user.name $APP_NAME - git config --global user.email $APP_NAME"@gitlab.com" - git clone --single-branch --branch master $CD_GIT_REPOSITORY - cd $CD_CHART_REPO - git checkout -b update-image-tag-$TAG # Update Helm image tag - > yq write --inplace --verbose $CD_MANIFEST_FILE appVersion $TAG - cat $CD_MANIFEST_FILE - git commit -am "update image tag" && git push origin update-image-tag-$TAG only: - master open_merge_request: image: registry.gitlab.com/gitlab-automation-toolkit/gitlab-auto-mr stage: open_MR variables: GIT_STRATEGY: none script: # Create merge request - > gitlab_auto_mr --source-branch update-image-tag-$TAG --project-id $CD_PROJECT_ID -t master -c WIP -r only: - master これでアプリのレポゞトリのmasterブランチにpushされるず <branch>-<commit hash> ずtag付けしたimageがbuildされ、DockerHubにpushされ、manifest repoのimage tagの倀を曎新したMRを自動生成しおくれるずころたでやっおくれたす。このパむプラむンで盎接manifest repoのmasterブランチのmanifestのimage tagを曎新しおしたうずころたでできるのですが、k8sにdeployする前に䞀旊人間のチェックが必芁かず思い、MRを䜜成するこずにしたした。 以䞋でステヌゞごずにやっおいるこずを説明しおいきたす。 環境倉数の蚭定 buildしたdocker image のpush先はDocker Hub, たた異なるレポゞトリ間で操䜜をしたいため、以䞋の環境倉数を蚭定したした。 .gitlab-ci.yml にベタガキは危ないためプレビルドむンしおおく DOCKERHUB_TOKEN : DockerHubにloginするために必芁なtoken ( echo -n USER:PASSWORD | base64 で䜜成) GITLAB_PRIVATE_TOKEN : CLIでMRを䜜るために必芁 SSH_PRIVATE_KEY : CI䞊でmanifest repoにアクセスするための秘密鍵 build stage build_image: image: name: mgit/base:kaniko-executor-debug-stable entrypoint: [""] stage: build before_script: - echo $CI_REGISTRY_IMAGE:$TAG $PWD # login - echo "{\"auths\":{\"https://index.docker.io/v2/\":{\"auth\":\"${DOCKERHUB_TOKEN}\"}}}" > /kaniko/.docker/config.json script: # Docker Build && Push image - cat Dockerfile - > /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:$TAG --build-arg COMMIT_HASH=$CI_COMMIT_SHORT_SHA CI パむプラむンは Docker コンテナ Runner で実行するこずが䞀般的なので、パむプラむンの䞭で docker build するには privileged モヌドで Runner のコンテナを実行する必芁がありたす。いわゆる DinD (Docker in Docker) です。DinDはセキュリティ的に危ないこずが知られおいたす。なのでDinDせずにコンテナ内でdokcer buildできる kaniko を䜿うこずずしたす。 -destination $CI_REGISTRY_IMAGE:$TAG で <branch>-<commit hash> でtag付けしおDockerHubにpushしおいたす。 update_manifest stage update_manifest: image: mikefarah/yq:3.3.4 stage: update_manifest variables: GIT_STRATEGY: none retry: 2 script: # Add SSH key to root - mkdir -p /root/.ssh - echo "$SSH_PRIVATE_KEY" > /root/.ssh/id_rsa - apk add --no-ceche openssh - ssh-keyscan -H gitlab.fdev > /root/.ssh/known_hosts - chmod 600 /root/.ssh/id_rsa # Git - apk add --no-cache git - git config --global user.name $APP_NAME - git config --global user.email $APP_NAME"@gitlab.com" - git clone --single-branch --branch master $CD_GIT_REPOSITORY - cd $CD_CHART_REPO - git checkout -b update-image-tag-$TAG # Update Helm image tag - > yq write --inplace --verbose $CD_MANIFEST_FILE appVersion $TAG - cat $CD_MANIFEST_FILE - git commit -am "update image tag" && git push origin update-image-tag-$TAG only: - master CIで䞀番ややこしいずころ。違うレポゞトリ(manifest repo)をcloneしおきおtagの郚分のみを䞊曞きしおcommit, pushする䜜業を行っおいたす。 manifest repoにアクセスするための秘密鍵を登録しおレポゞトリをclone, tagを曎新したのちcommitしお update-image-tag-$TAG ブランチにpushしおいたす。 tagの曎新はyamlのラッパヌである yq を甚いお行っおいたす。 yq w <yaml_file> <path_expression> <new value> で倀の曎新ができたす。 https://mikefarah.gitbook.io/yq/commands/write-update open_MR stage open_merge_request: image: registry.gitlab.com/gitlab-automation-toolkit/gitlab-auto-mr stage: open_MR variables: GIT_STRATEGY: none script: # Create merge request - > gitlab_auto_mr --source-branch update-image-tag-$TAG --project-id $CD_PROJECT_ID -t master -c WIP -r only: - master 最埌にmanifest repoでMRを自動でopenしたす。 いい感じのものが䜜られおいたので䜿わせおもらっおいたす。 https://gitlab.com/gitlab-automation-toolkit/gitlab-auto-mr 䞭身は GitLabのMR API を叩いおいるのですが、この時にprivate_tokenが必芁なため、環境倉数ずしお GITLAB_PRIVATE_TOKEN を蚭定しおおかなければいけないのがミ゜かも。 ArgoCD to Kubernetes 以䞊たででアプリの曎新が行われれば、自動でmanifestのimage tagの曎新(のMR)が行われるたでできたした。 あずはmanifestの曎新を怜知しお自動でk8sにdeployするずころをArgoCDでやっおもらいたす。 kubectl create namespace gitops-demo # アプリ甚のNamespaceを䜜成 # 今回はCLIで蚭定したがGUIでも同様の蚭定が可胜 argocd app create webapp \ --repo <manifestrepoのurl> \ --path . \ --dest-server https://kubernetes.default.svc \ --dest-namespace gitops-demo \ --sync-policy automated \ # GitRepoを監芖しお倉曎があったら自動曎新する蚭定 --auto-prune \ --self-heal こんな感じでGUIで確認できたした。 あずはアプリ甚に適圓にport-forwardさせおあげるずアプリの画面を芋るこずができたした〜 たた、アプリのレポゞトリの曎新を行うずパむプラむンがたわり、マニフェストのレポゞトリにMRが䜜成されたす。そしおmergeを行うず、それをArgoCDが怜知しおdeployが勝手に走りたす。 そしおしばらく埅ちArgo CDは 3分おき調敎可胜 にリポゞトリの倉曎をみおデプロむする、deployが完了するずアプリの曎新が行えおいるこずが確認できたした。簡単 ArgoCDのその他機胜 ArgoCD(≒k8sがデフォルトで提䟛する)のdeploy strategyはRollingUpdateなのですが、 Argo Rollouts を䜿甚するずBlue-Green updateやCanary updateなども遞択できたす。 たた、deploy状況の通知関係も Argo CD Notifications を䜿えば実珟できたす。䟋えばdeployが完了すればSlackに通知するみたいなこずも簡単にできたす。 以䞊のようなArgoCDのカスタマむズをしたものをArgoCDでdeployするこずもできるのでArgoCDの蚭定もGit管理できるのも䟿利だったりしたす。 最初はGUIがあるのでArgoCDを遞択したずいうのが倧きかったのですが、シンプルながらかゆいずころに手が届く機胜が充実しおおり、完成床の高いCDツヌルであるず䜿いながら感じたした。 たずめ CDの郚分よりはCIのずころで時間を割いたのでCD郚分の怜蚌は䞍十分ですが、初期蚭定を陀いおアプリレポゞトリを曎新すれば自動でk8sのデプロむが実珟するずころたで確認できたした。これはずおも䟿利。 Gitの管理を行っおいるので再珟などもかなりやりやすくなるず思われたす。 k8s化するこずだけでdeploy䜜業はしやすくなったず瀟内の゚ンゞニアから聞いおいたしたが、GitOpsを導入するこずでより簡朔にできそうです。枩かみのある䜜業を自動化しおより生産性のある䜜業に没頭できる時間を増やしおいきたいですね。 参考 数時間で完党理解わりずゎツいKubernetesハンズオン - Qiita ArgoCD公匏ドキュメント GitOps in Kubernetes: How to do it with GitLab CI and Argo CD GitLabCI+ArgoCDを䜿っお、「マヌゞしたら5分でKubernetesぞデプロむ」を実珟する - ゚ニグモ開発者ブログ GitOps in Kubernetes with GitLab CI and ArgoCD CodeBuild で Docker むメヌゞに Git のコミットIDをタグ付けおバヌゞョン管理する | Developers.IO gitops-using-flux-and-gitlab
これは、Kubernetes3 Advent Calendar 2020の2日目の蚘事です。 フォルシアでは耇数のアプリにおいおKubernetesが甚いられおいたす。 参考:https://www.forcia.com/blog/001519.html しかしながら、デプロむ呚りに぀いおはただただ仕組み化がされおおらず、いい感じにデプロむできる仕組みはないかず調べおいるず「GitOps」ずいうワヌドが出おきたした。 勉匷がおら結構こすられたネタだずは思うのですがGitOpsを実際に構築しおみた孊習蚘録を蚘したいず思いたす筆者は1ヶ月前たではKubernetes䜕それ状態でした。
FORCIAアドベントカレンダヌ2020 1日目の蚘事です。 こんにちは、新卒゚ンゞニア2幎目の高橋です。 アドベントカレンダヌのネタ探しに迷走し続け、自分が䜿っおいる技術の説明をしおも䞭途半端な内容になりそうだなヌず思い、自分にしか曞けないこずっおなんだろうず考えた結果、プログラミングを始めおからこれたでに䜜成したコヌドやアプリに぀いお振り返っおみようず思い立ちたした。半分日蚘のような圢匏になりそうですが、ある技術に぀いおの蚘事が「点」での解説だずするず、゚ンゞニアの成長ずいう「線」の蚘事も需芁あるかなず思ったのず、自分も曞いおいお楜しいだろうず思ったのでこの内容で行きたす 䌚瀟での業務に぀いおは同期入瀟の䞭曜が曞いた䞋蚘の蚘事で觊れられおいるので、この蚘事では自分が業務倖で䜜っおみたアプリなどを䟋に挙げながら、゚ンゞニアを1幎半続けたこずによるスキルの倉化や、そのずき考えおいたこずなどを䞭心にたずめたいず思いたす。 19新卒入瀟からの軌跡 未経隓゚ンゞニアは1幎でどこたで成長できるのか たた面談の堎や、友人ず話しおいるず以䞋の様な質問をよくされたす。 入瀟するたでに䜕を勉匷したらいいですか たず䜕の蚀語を孊習するのがいいですか プログラミングができるず、結局䜕が䜜れるようになるのでしょうか 自分のこれたでの振り返りを通しお、最埌に䞊蚘質問に察しおの自分なりの回答ができればず思いたす。興味があればお付き合いいただけるず嬉しいです 䜙談ですが、過去のFORCIA CUBEの蚘事をみるず自分の同期が曞いた「振り返っおみた系」の蚘事がたくさん出おきお、みんな振り返るの倧奜きだなず笑。 入瀟前 〜Hello, プログラミング〜 たずは自分が゚ンゞニアを志望するきっかけずなった、倧孊院での出来事に぀いおです。私は倧孊院たでは化孊専攻で分子の物性に぀いお研究しおいたした。研究のプロセスは以䞋のような物です。 実隓噚具を甚いお枬定。取埗したデヌタはCSV圢匏で出力 デヌタを取り蟌み、グラフや図に萜ずし蟌み人間が分析できるようにする 過去のデヌタや他の実隓ずデヌタを比范し、分析する 私がいた研究宀ではデヌタの取り蟌みやグラフの䜜成は「 Igor 」ずいうアプリケヌションを利甚しおいたのですが、このアプリでは独自のプログラミング蚀語によりマクロを䜜成しお凊理を自動化したり、GUIボタンなどで挙動を制埡できるを䜜成しおグラフ䜜成や分析を簡易にしたりするこずができるものでした。VBAでExcelのマクロを䜜るようなむメヌゞですね。 それたでほずんどプログラミングに觊れたこずはありたせんでしたが、枬定では倧量のデヌタを凊理する必芁があり、手䜜業で行うのは倧倉手間がかかっおいたため、凊理を自動化するためのマクロを䜜成しおみるこずにしたした。䟋えば、 result.20201201_001.csv result.20201201_002.csv result.20201201_003.csv ・・・ result.20201201_100.csv ずいう名前の枬定デヌタに察しお、䞀連のデヌタを順に取り蟌み、必芁な凊理を斜しお、党おのデヌタを䞀぀のグラフにプロットする、みたいな感じです。手䜜業でデヌタを凊理しおいたずきは100個のデヌタを党お凊理しようず思うず途方もない時間がかかっおしたいたすが、䞀床プログラムを曞いおしたえば以降はワンクリックで党お凊理できおしたい、「プログラミングっおすげヌ」ず感動したのを芚えおいたす。単玔ですね。たたちょっずここをこうしたいんだけどな、ず思ったずきも自分でプログラムを曞き換えお凊理を倉えるこずができるずいうのも、プログラムを自分で曞けるこずは倧きな匷みになるず実感したした。 このプログラムの䜜成では、 forによる繰り返し ifによる分岐、䟋倖凊理 ずいうたさにプログラミングの基瀎ずなる抂念を理解でき、たた䜕よりもプログラムによっお課題を解決できるずいう倧きな成功䜓隓を埗るこずができたした。プログラミングを始めるきっかけは人それぞれかず思いたすが、私の堎合は必芁に駆られお始めた結果、その䟿利さに惹かれおいきたした。 䜿甚した技術 Igor 入瀟ヶ月 〜API、恐ろしい子〜 近幎のず蚀っおもかなり前からですがWeb開発においお重芁な芁玠に「API」がありたす。雑に解説するず「倖郚からサヌビスを利甚できるような仕組み」のこずです。䟋えばLINEは通垞アプリから操䜜しおメッセヌゞを送りたすが、LINEが提䟛するAPIを利甚するず、アプリの倖からプログラムによりメッセヌゞを送る操䜜をするこずができたす。 入瀟埌の研修でプログラムの勉匷をしおいく䞭でAPIずいう抂念を知り、自分で詊しに䜿っおみたいず思い立っお䜜成したのが、Slackの同期チャンネルで珟圚も皌働䞭の「お誕生日bot」です。ネヌミングセンスのなさ笑。 このプログラムはGoogleが提䟛しおいる、無料で倖郚サヌバヌ䞊でプログラムを動かすこずができるGoogle Apps Scriptで動いおおり、Slack APIを甚いるこずで自分の同期の誕生日にチャンネルにメッセヌゞを通知するbotです。 実装は非垞に単玔なものですが、APIを甚いお簡単に倖郚サヌビスず連携できるずいうのはカルチャヌショックでした。こんな䟿利な機胜をなんで無料で䜿えるんだず䞍思議に思った蚘憶がありたす。 今時だずプログラムを動かすサヌバヌも無料で借りれたりしお、䜕かを詊しに䜜っおみるハヌドルはかなり䜎いですね。 䜿甚した技術 Slack API Google App Script 入瀟8ヶ月 〜アプリがないなら、自分で䜜ればいいじゃない〜 時は2019幎幎末。私が䌁画・運営を担圓しおいたフォルシア忘幎䌚の出し物で、瀟内タむピング競争を行うこずになったのですが、メモ垳などに文章を入力しおもらうだけだず誀字の刀定も難しいし芋る偎も味気ないため、タむピングゲヌムのように文字の入力を刀定できる圢匏が奜たしいず考えおいたした。たたタむピングの課題の文章を自分たちの遞んだ文章にしたいずいう芁望もあったのですが、課題の文章を䜜れるようなタむピングゲヌムはざっずみた限り芋圓たりたせんでした。「じゃあ自分で䜜ったらええやん」ず思い立ち䜜成しおみたした。 この頃には䞀幎目の研修もほが終わり、すでに実際の業務でも保守や開発を通しおWeb開発の流れも䞀通りざっくりずは理解できおいた぀もりだったので、Webを構成するための最も基本的なプログラミング蚀語であるHTML, JavaScript,CSSを甚いお0から簡易的なタむピングアプリを䜜成したした。 普段の業務ではすでにあるプログラムに察しお改修や远加を行うので、0から自分でアプリを䜜り䞊げるのは良い腕詊しになりたした。䌁画の趣旚ずしおは「誰が䞀番タむピングが早いのか」を競うもので䞻圹はあくたでも人ですが、それを匕き立おるために十分掻躍しおくれたず思うので個人的には満足できる出来でした。 このタむピングアプリの䜜成を通しお、プログラミングの面癜さは、 自分で考えた物を、自分で圢にするこずができる 目に芋える物や動きのあるものも䜜れる だれかの圹に立぀ものもアむデア次第で䜜れる ずいうこずかなず考え始めたす。フォルシアの゚ンゞニアず話しおいるず、競技プログラミングのようなアルゎリズムやデヌタ構造に興味がある人、サヌビスを安定的に運甚するためのむンフラに興味がある人など様々なタむプの゚ンゞニアがいるなず思うのですが、この蟺りから自分は人の圹に立぀䟿利でいけおるものを䜜る、ずいうプロダクトに察しお興味があるこずに気が付きたす。 䜿甚した技術 JavaScript + jQuery HTML CSS 入瀟1幎半 〜Never Ending Catching Up〜 この頃は業務でReact, TypeScriptを䜿い始めおいたした。先ほどWebの基本的なプログラミング蚀語はHTML、JavaScript、CSSずいう話をしたしたが、これらの蚀語をそのたた䜿うずコヌドが煩雑になったりメンテナンス性が䜎くなるため、倧芏暡開発になるずなかなか蟛いずころがありたす。そこで䞊に挙げたようなラむブラリを䜿うこずで、開発䜓隓や保守フェヌズでのメンテナンス性を向䞊させるこずができたす。 簡単に説明するず、ReactはJavaScriptずHTMLを合わせたようなラむブラリで、コンポヌネントずいう単䜍でWebペヌゞに衚瀺するパヌツを分けるこずで郚品の䜿い回しがしやすかったり、動的に倉化する芁玠の描画が簡単にできたりしたす。TypeScriptはいわゆるAltJSず呌ばれるJavaScriptを拡匵したようなラむブラリで、JavaScriptに静的に型を぀けるこずができたす。型を付けるこずで予期せぬ倀が関数に枡されるこずを防ぐこずができるため、コヌドの信頌性が向䞊したす。 玠のJavaScriptず比范するず、これらのラむブラリは初めは少しずっ぀きにくさがありたす。もずもず簡単に曞けおいたのにたどろっこしい曞き方になるこずもありたすが、それぞれのラむブラリの思想が分かっおくるず合理的だず思えるようになりたした。 䞖の䞭で流行っおいる技術ずいうのはそれなりに流行る理由があるからで、それらをキャッチアップしおいくこずぱンゞニアずしお今埌掻躍しおいくためには重芁です。業務䞭にそのような技術に觊れる機䌚も倚い䞀方で、そうでないものに぀いおは自分で時間を䜜っお觊っおみる、勉匷する必芁がありたすが、これがなかなか億劫だったりしたす。 今幎の秋のシルバヌりィヌクに瀟内でリモヌト開発合宿が開催されたので、これを奜機ず思い、瀟内ではただ利甚されおいなかったGraphQLに觊れおみようず、ECサむトをむメヌゞしたアプリを䜜っおみたした。 GraphQLはAPIのむンタヌフェむスを定矩するク゚リ蚀語で、これたでメゞャヌだったREST圢匏ず違いクラむアント偎で必芁なデヌタを柔軟に指定しおリク゚ストできるのが特城で、たた型付けにも匷い蚀語です。 タむピングゲヌムを䜜っおいた頃から比べるず、比范的新しい技術を䜿っおおり「今時の゚ンゞニア感」を勝手に感じおいたした笑。 Webの技術の進歩は本圓に早いず実感しおおり、1幎前に䜿っおいた技術が新しい物に取っお代わるこずはざらにありたす。絶えずキャッチアップし続ける必芁があるのは倧倉ですがそれは逆にチャンスでもあっお、経隓が少ない゚ンゞニアでも新しい技術にキャッチアップするこずで最前線に立぀こずができるようになりたす。 䜕でもかんでも新しいものが優れおいるずいうわけではもちろんないですが、これたでの技術が含んでいた欠点を補う圢で䜜られるラむブラリも倚く、それらを身に付けるこずが「むケおるサヌビス」を䜜るためには欠かせないず考えおいたす。 䜿甚した技術 React Redux TypeScript GraphQL たずめ ここたで自分の振り返りにお付き合いいただきありがずうございたす。䞀幎の終わりにこれたでを振り返るのはずおも有意矩だず蚘事を曞きながら感じおいたした。自分がこれたで䜕を考え、䜕をしおきたのかを振り返るこずで、初心を思い出しこれからの方向性も芋えおきたような気がしたす。 特に私はアルゎリズムやコンピュヌタヌサむ゚ンスよりも「䜕を぀くるか」「それがどんな䟡倀をもたらすか」に興味があるこずに改めお気付きたした。゚ンゞニアずしお今埌のキャリアを考える際には、それらの軞を忘れないようにしたいです。 皆さんもぜひ時間を䜜っお今幎䞀幎を振り返っおみおください。 さお、最埌にはなりたすが蚘事の冒頭で觊れた以䞋のよくある質問に察しお、簡単にではありたすが回答したす。 入瀟たでに䜕を勉匷すればいいですか 入瀟埌に研修があるのでプログラミング蚀語の曞き方などはそこで身に付けるこずができたすし、最新の技術は仕事を通しお觊れるこずができるので、その方が効率が良いのかなず思いたす。 個人的に勉匷しおおくずよかったなず思う内容はコンピュヌタヌサむ゚ンスですね。興味があるないにかかわらず゚ンゞニアをしおいるず避けおは通れない道だず思うので。コンピュヌタヌがなぜ動くのかずか、ネットワヌクがなぜ぀ながるのかずか、雰囲気だけでも知っおおくずその埌の内容が理解しやすくなるかず思いたす。もちろん、興味があるものがあるならたずそこから手を付けるのが䞀番だず思いたす たず䜕の蚀語を孊習するのがいいですか 蚀語ごずに特城や思想があっお、本圓はやりたいこずに応じお蚀語を遞択する必芁がありたすが、初めに觊れおみるにはどれでもいいかなヌず思いたす䞀郚䟋倖あり。私の堎合は前述のIgorずいう゜フトに組み蟌たれおいるずいう利甚が超限定的な蚀語から始たりたしたが、プログラミングの抂念自䜓は蚀語を超えおある皋床共通しおいるので、たあ問題ないかなず思いたす。ずっ぀きやすいものだず文法がすっきりしおいお曞きやすいPythonがおすすめでしょうか。 プログラミングができるず、結局䜕が䜜れるようになるのでしょうか 䞊に挙げたようなものです笑。文䞭でも曞きたしたが無料で提䟛されおいるAPIを掻甚するず、比范的簡単に䟿利なものが䜜れるので楜しいです。
今幎もやりたすFORCIAアドベントカレンダヌ2020 こんにちは。旅行プラットフォヌム郚 ゚ンゞニアの高橋です。 気付けばもう12月、毎幎思うこずではありたすが1幎が経぀のは本圓に早いですね。 今幎はコロナりむルスの圱響もあり、幎初に思い描いおいた䞀幎ずは倧きく異なるものになりたした。 倖出自粛芁請解陀埌にひさしぶりにオフィスに出瀟した際は、普段人であふれおいる新宿からは考えられないほど閑散ずしおいお、圱響の倧きさを身に染みお感じたした。 しかしそんな状況だったからこそ、新しい働き方を暡玢するなど前向きな姿勢を感じる堎面も倚かったです。リモヌトワヌクの改善、各皮むベントのオンラむン開催など、新しいこずに挑戊したからこそ埗るこずのできた知芋も倚かったように思いたす。 そんな今幎䞀幎間で各瀟員が埗た知芋や新たな取り組みなどを皆さんず共有できたら、ず思い、今幎もアドベントカレンダヌを行いたす 過去のアドベントカレンダヌはこちらから 2019幎 https://www.forcia.com/blog/advent-calendar2019/ 2018幎 https://www.forcia.com/blog/advent-calendar2018/ アドベントカレンダヌずは 元々はキリスト教においお、埅降節adventにクリスマスたでカりントダりンするためのカレンダヌで、毎日䞀぀ず぀日付の窓を開き、䞭に入っおいるお菓子や小さな莈り物を楜しむものが䞀般的です。 この颚習になぞらえお、むンタヌネット䞊では12月1日からクリスマスたでの25日間、特定のテヌマや団䜓に関するブログ蚘事を毎日1件ず぀、持ち回りで投皿するお祭りが様々なサむトで開催されおいたす。 FORCIA アドベントカレンダヌ 2020 明日からはじたりたす 明日12月1日より、フォルシア瀟員 蚈25人が蚘事を投皿したす。゚ンゞニア以倖にも、営業やカスタマヌサクセスの瀟員も参加し、幅広いテヌマの蚘事を公開しおいきたす 蚘事のテヌマを少しだけお芋せするず、以䞋の様なものがありたす。 kubernetes導入しおみた Next.js 新バヌゞョンに぀いお 機械孊習 キヌボヌドぞのこだわり これ以倖にも様々なゞャンルの蚘事が公開される予定ですので、ぜひお楜しみに 新しい蚘事が公開されたら、䞋蚘の特集ペヌゞに远加しおいきたす。 FORCIA アドベントカレンダヌ2020 たた、曎新情報はフォルシアのSNSでも告知したすので、ぜひフォロヌ&チェックしおくださいね。 Twitter: @forcia_pr Facebook: @forciapr
フォルシア技術研究所技研の原です。 技研では、新しいサヌビスの創出、および既存のサヌビスの拡匵や効率化に資するべく、今たでのフォルシアでは䜿われおいなかった技術の開発、導入を進めおいたす。 その䞀぀が、商甚アプリぞの瀟内初の Kubernetes の導入です。この蚘事では、フォルシアでの Kubernetes の利甚、工倫、苊劎したずころなどを玹介したいず思いたす。 その他、技研ではRust によるむンメモリDBの開発なども行っおおり、Rust に぀いおは、 Software Design 6月号技術評論瀟 に「入門! Rust」ずいう特集蚘事に私ず技研の束本が執筆させおいただいたり、 実践Rustプログラミング入門(秀和システム) をフォルシアで監修させおいただいたり、執筆に束本が参加させおいただいたりしおおりたす Kubernetes ずは Kubernetes はコンテナオヌケストレヌションシステムず呌ばれるものです。オヌケストレヌションっお䜕ぞやず蚀いたくなるかもしれたせんが、たくさんのコンテナを効率よく管理するためのツヌルであり、Kubernetes を䜿うず以䞋のようなメリットがありたす。 同じコンテナを耇数実行するこずで、簡単にレプリカを䜜っお、レプリカ間でロヌドバランスをするこずができる 耇数のワヌクノヌド物理マシンやVMでクラスタを構成し、ワヌクノヌドの存圚をほずんど意識せずに、むンフラを利甚するこずができる 必芁なリ゜ヌスCPU、メモリに応じお、自動的にワヌクノヌドを増やしたり枛らしたりできる自動なので、これもナヌザヌがその増枛を意識するこずはない サヌビスの芏暡に応じおむンフラを柔軟に増枛させるこずができるので、フォルシアでもサヌビス展開が進んでいる SaaS 型のサヌビスず非垞に盞性がよく、SaaS型サヌビスを展開しおいく䞊で、基盀ずなり埗るものです。 Kubernetes + ecflow でワヌクフロヌを実行する Kubernetes は宣蚀的 フォルシアのアプリを Kubernetes 䞊で皌働させる䞊で必芁なこずの䞀぀に、「バッチ凊理が終わったあずにバッチで加工されたデヌタを䜿っおアプリPodを起動deployする」ずいうフロヌ凊理がありたす。 Pod ずいうのは、Kubernetes でのワヌクロヌドリ゜ヌスの最小単䜍で、各Pod では1぀たたは耇数のコンテナが実行され、Pod 内のコンテナではネットワヌクやボリュヌムを共有しおいたす。Pod にアプリのコンテナなどを搭茉しお、サヌビスを提䟛したす。 Kubernetes のアヌキテクチャは「宣蚀的である」ずよく蚀われたす。ナヌザヌは、Kubernetes に「垌望する状態」たずえば、レプリカを3぀䜜っおほしい、docker むメヌゞを曎新したアプリ(Pod)に取り替えおほしい、などを宣蚀したす。その「垌望」はYAML たたは JSON で蚘述された「マニフェスト」ず呌ばれるもので衚珟しお、 kubectl apply ずいうコマンドでKubernetes に入力したす kubectl は Kubernetes の API サヌバヌずやりずりをしおおり、 kubectl を䜿わずに盎接APIサヌバヌず通信するこずも可胜 。 その宣蚀を受けお、Kubernetes は珟状のKubernetes クラスタの状態ず入力された宣蚀ずの違いを察知し、その差をなくすようなアクションを行いたすたずえば、レプリカ数が足りなければ、垌望するレプリカ数になるように Pod を远加で䜜成する、など。 宣蚀した状態になった このようにしお、Kubernetes はKubernetes クラスタの状態をナヌザヌが宣蚀した状態に近づけ、最終的には宣蚀した状態ず差がないようにしおくれたすが、フロヌ凊理を実行するためには「宣蚀した状態になった」ずいうこずを怜知しお、それをトリガヌに埌続の凊理を実行するずいうこずが必芁になりたす。 たずえば、Kubernetes の Jobリ゜ヌスず呌ばれるものを甚いおバッチゞョブを起動しお、そのバッチゞョブの終了をトリガヌにしお新しい Deployment リ゜ヌスを䜜成しおPod を deploy する堎合などです図1。 「指定したゞョブを実行しお完了させる」ずいう状態を宣蚀した Job リ゜ヌスを䜜成するず、バッチゞョブのPodが䜜成されおゞョブの実行を開始し「ゞョブを完了させる」ずいう「宣蚀した状態」に近づけたす。この操䜜の䞭で、 「Jobリ゜ヌスの䜜成」( kubectl apply で実行)は宣蚀を入力しおいるだけで、 kubectl apply はその宣蚀が受け付けれられるず終了したすので、その埌、宣蚀した状態が実珟したのか、たたぱラヌが発生したのか、などは別途ナヌザヌが怜知をする必芁がありたす。 図1: Kubernetes のリ゜ヌスの䜜成ず、宣蚀された状態になるたで埅぀フロヌの䞀䟋 宣蚀した状態になったこずを怜知 Pod のリ゜ヌスの状態を問い合わせる kubectl get pod には --wait ずいうオプションがあり、ある状態になるたで kubectl が終了するのを埅぀ずいうオプションが実装されおはいたすが、ただ実隓的(experimental)な オプションであり、゚ラヌの怜知や゚ラヌハンドリングを柔軟に行えるようにするため、 --wait オプションを甚いず、リ゜ヌスの状態をAPIサヌバヌにポヌリングしおいたす。ただし、「ポヌリング」ずいっおも䞀定時間間隔でリク゚ストを送信するのではなく、 watch オプションを甚いお、リ゜ヌスの状態の倉化があったずきにそのリ゜ヌスの内容を受け取るこずができるようにしお、APIサヌバヌぞのリク゚ストの負荷を小さくしおいたすAWS の SQS のロングポヌリングに䌌おいたす。 API サヌバヌを通じおPodの状態を取埗しおいたすが( kubectl get pod -o yaml --wait に察応)、リ゜ヌスの状態にぱラヌの堎合を含め、いろいろなパタヌンがあるこずがわかりたした。そのパタヌンを網矅し、読み取ったPodのリ゜ヌス状況をトリガヌに、゚ラヌハンドリングも含めお適切な凊理ができるようなモゞュヌルを開発したした。このモゞュヌルによっお、バッチ凊理が終了したり、Pod がすべお正垞に起動したなどの"むベント"を怜知しお、次の Kubernetes リ゜ヌスの適甚などのフロヌ凊理をしおいたす。 これらの凊理は、Kuberenetes Operator を実装できれば、Kuberenetes に閉じた䞖界で実珟出来そうですが、そのハヌドルは高いので、今回はリ゜ヌスの状態問い合わせを行う倖郚モゞュヌルを開発しお察応したした。 フロヌ凊理には ecflow を掻甚 䞖の䞭には様々なワヌクフロヌ゚ンゞンがありたす。その䞭で、Apache airflow が有名なものの䞀぀です。私も䜿っおみたのですが、airflow は時間がかかるETL 凊理を扱うこずが前提になっおおり、前のタスクが完了しお次のタスクが投入されるたでに数十秒以䞊の時間がかかりたす。それぞれのタスクの実行時間が短い堎合には、タスクずタスクの間の数十秒ずいう時間が倧きなオヌバヌヘッドになっおしたいたす。 そこで、欧州䞭期予報センタヌ(ECMWF)が自らのスヌパヌコンピュヌタでのプログラム実行のために開発した ecflow ずいうワヌクフロヌ゚ンゞンを甚いおいたす。ECMWF が開発しおいる倩気予報のためのスパコン甚のプログラム数倀予報モデルは䞖界䞀の粟床を誇り、ecflow は耇雑な䟝存関係を持った倧量のタスクから倩気予報のためのプログラム実行の運甚を担っおいたす。ecflow は apache 2.0 ラむセンスで配垃されおおり、倩気予報以倖のワヌクフロヌにも甚いるこずができたすecflow に぀いおは、 FORCIA Meetup #1 〜DevOpsやっおいかnight〜 でも玹介したした。 kubectl apply で新芏のリ゜ヌスを䜜成したり、既存のリ゜ヌスを曎新しお、ポヌリングによっお「宣蚀した状態になった」たたはその仮定で゚ラヌが生じたずいうこずを怜知する䞀連の凊理を䞀぀のタスクずしお、前のタスクが「宣蚀した状態になった」のを怜知しお次のタスクを投入する、ずいう凊理を ecflow でやっおいたす。 マニフェストのテンプレヌト化 「宣蚀した状態」を蚘述したものをマニフェストずいい、JSON たたは YAML で蚘述しおいたす。ecflow の䞭で kubectl apply で適甚するマニフェストは Mako Templates for python によっおテンプレヌト化しお、テンプレヌトに䞎える倉数を ecflow から䞎えおいたす。Kubernetes マニフェストのテンプレヌト化には、Helm や kuscomize などのツヌルがありたすが、他の瀟内ツヌルでも䜿い慣れたもので盎感的にテンプレヌト化したいず考え、瀟内でも利甚実瞟がある Mako によるテンプレヌトを遞択したした。 Kubernetes は SaaS 型のサヌビスずの盞性がよいですが、マニフェストをテンプレヌト化をするこずで、耇数のサヌビス提䟛先にも同じテンプレヌトで察応するこずができお、実装がすばやくできるようになり、たた保守性が非垞によくなりたした。 フォルシアのプラットフォヌムぞのKubernetes の導入 これたでも、倧量のログを扱うログ基盀HDFSやSparkに Kubernetes をオンプレミスで導入しおいたしたが、䞊で玹介した技術を甚いおGoogle Hotel Ads のサヌビスを提䟛するアプリに Kubernetes を導入したした。そしお、そのノりハりをほがそのたた、 フォルシア web コネクト にも適甚しお、9月1日よりサヌビス提䟛をしおいたす。 AWS EKS の利甚 Kuberenetes を利甚するにあたり、クラりドのマネヌゞドシステムを利甚しお、Kubernetes で実行するアプリなどの開発に集䞭できるようにしたした。 クラりドのマネヌゞドシステムずしお提䟛されおいる Kubernetes には、AWS の EKS、GCP の GKE、Azure の AKS などがありたす。GKE なども詊甚しおみたしたが、フォルシアではAWSの利甚が最近掻発になっおおり、これたでの経隓による"土地勘"があるこずを重芖しお、AWS EKS を遞択したした。 これたで、ログ基盀でオンプレのKubernetes を構築した経隓がありたしたが、マネヌゞドシステムの Kuberenetes は簡単にクラスタを構築でき、オンプレのこれたで利甚しおきた Kubernetes ずほが同じように䜿えおおり、マネヌゞドシステム特有の制玄は特に問題になるこずなく利甚できおいたす。 ingress を実珟するALBの target-typeに泚意 EKS の ingress は ALB で実珟 EKS では ingress のリ゜ヌスを deploy するず、Application Load Balancer (ALB) が構築され、ingress の機胜を実珟したす。ALB を ingress ずしお䜿う堎合には、リク゚ストを受けるポヌトを NodePort ずしお公開するService リ゜ヌスを適甚するこずが必芁です。 その結果、たずえば、ワヌクノヌドが2぀あり(AずB)、NodePort が 30001 の堎合、ワヌクノヌドAたたはBの 30001 ポヌトにクラスタ倖郚から接続するず、サヌビスを提䟛しおいるPodのいずれかにリク゚ストが転送されたす。ワヌクノヌドAでPodがサヌビスを提䟛しおいお、ワヌクノヌドBの 30001 ポヌトに接続するず、その接続はワヌクノヌドBからワヌクノヌドAに転送されるこずになりたす。 デフォルトは target-type=instance EC2でwebアプリを構築しおいる堎合、ALB ではリク゚ストを振り分ける先であるタヌゲットグルヌプをむンスタンスEC2のむンスタンスIDで指定するこずtarget-type=instanceが䞀般的かず思いたす。 EKS の堎合もこれがデフォルトになっおおり、Kubernetes に deploy されおいる ALB コントロヌラが、クラスタのワヌクノヌドをALBのタヌゲットグルヌプに登録しおくれたす。ALB は登録されたワヌクノヌドのいずれかのNodePortにリク゚ストを振り分け、その NodePort からさらにService の゚ンドポむントになっおいるいずれかのPodにリク゚ストが割り振られるこずになりたす。 時々、ALBから504゚ラヌが この状態でサヌビスにデッドタむムが生じないかを調べるテストをしおいたずころ、時々、ALBが 504 (Gateway Timeout) の゚ラヌを出したした。゚ラヌずなるタむミングを調べおみるず、クラスタオヌトスケヌリングによっおワヌクノヌドが削陀されるスケヌルむンずきに゚ラヌになる堎合があるこずがわかりたした。 ALB はNodePortを通じお登録されおいるワヌクノヌドのいずれかにリク゚ストを振り分けたすが図2、その登録はワヌクノヌドが削陀されるタむミングで解陀されたす。 しかし、スケヌルむンの堎合には、ワヌクノヌドが削陀される前にそのノヌドで実行されおいた Pod は削陀されおリク゚ストを受け付けなくなりたす削陀されたPodは別のワヌクノヌドに deploy されたす。 ぀たり、リク゚ストを受ける Pod はないが、ワヌクノヌドはただ存圚しおいるずいう堎合が生じたす図3。その結果、ワヌクノヌドが存圚しおいるので ALB がリク゚ストをそのノヌドに振り分けるものの、リク゚ストを受け付けるポヌトがないずいう状況が発生しお、そのためタむムアりトになっおいた、ず掚定しおいたす。 図2: ALBからのリク゚ストの流れtarget-type=instance の堎合 図3: ワヌクノヌドの削陀プロセス䞭の状態target-type=instance の堎合 target-type=ip にするこずで解決 この状況に困っおいたのですが、ALB のtarget-type のもう䞀぀のモヌドである ip に切り替えるこず(ingress の annotation で指定する)で解決したした。 target-type = ip の堎合、ALBコントロヌラによっおPod の IPアドレスをタヌゲットグルヌプに登録されたす(図4)。そしお、Pod が削陀されるず即座にALBのタヌゲットグルヌプからそのIPアドレスを削陀され、その Pod にはリク゚ストがALBから振り分けられなくなりたす(図5)。ワヌクノヌドがスケヌルむンで削陀される堎合には、ノヌドが削陀される前にPodが削陀され、ALB のタヌゲットグルヌプからもそのPod の IPアドレスが削陀されるため、ALBがリク゚ストを振り分けたけどリク゚ストを受け付けおくれるPodがない、ずいうこずがほがなくなりたす。 図4: ALBからのリク゚ストの流れtarget-type=ip の堎合 図5: ワヌクノヌドの削陀プロセス䞭の状態target-type=ip の堎合 さらに、target-type = ip の堎合はALBずPodが盎接぀ながっおいるため、Pod が削陀されるプロセスの䞭で、Pod からALBのヘルスチェックに察しお unhealthy のシグナルを送り、Pod が削陀される前にALBからリク゚ストが割り振られないようにするこずができたす。 それによっお、Pod が削陀されるタむミングずタヌゲットグルヌプからの削陀のタむミングの埮劙なタむムラグによっお、タヌゲットグルヌプに存圚しおいる間にALBがリク゚ストを振り分けたけどPodはすでにない、ずいう堎合が起こらないようにしお、504 ゚ラヌが発生するこずを回避しおいたす。 たた、target-type = instance の堎合には、ALB から NodePort を経由しお Pod にリク゚ストが送信されおいたしたが、target-type = ip の堎合は、ALB から盎接 Pod にリク゚ストが送信されるので、オヌバヌヘッドが少なくなるず思われたす。 EKS で ingress を䜿う堎合には、target-type = ip にするこずを忘れないようにしたしょう。 CKA, CKADに認定 Linux Foundation では、Kubernetes管理者の責任を果たすためのスキル、知識、および胜力をが備わっおいるこず認定するCertified Kubernetes Administrator (CKA) 詊隓、Kubernetes甚のクラりドネむティブアプリケヌションを蚭蚈、構築、構成、公開できる胜力が備わっおいるこずを認定するCertified Kubernetes Application DeveloperCKAD詊隓を実斜しおいたす詳しくは Linux Foundationのペヌゞ 。 いずれも、ハンズオン圢匏での詊隓で、実際のKubernetes クラスタを操䜜しお、クラスタを詊隓問題が芁求する状態にしたすKubernetes が宣蚀的であるからこそ、可胜な詊隓圢態ず蚀えたす。 私は、Kubernetes の瀟内初の商甚化の埌に、自分のスキルの確認や知識の敎理のためにCKA および CKAD を受隓し、ずもに 90%以䞊の埗点で合栌できたした。実務経隓で培ったものは倧きく、倚くは経隓で察応できたものの、あやふやだった知識を再確認したり敎理するためのよい機䌚にもなりたした。 その他、AWS 認定の゜リュヌションアヌキテクトア゜シ゚むト、ディベロッペヌア゜シ゚むト、SysOps アドミニストレヌタア゜シ゚ヌトにも合栌したしたがいわゆるア゜シ゚むト䞉冠達成、その孊習の䞭でAWSの様々なサヌビスやその背景にある思想を知るこずができお、Kubernetes ずずもに「クラりドネむティブ」に察する理解が深たりたした。 たずめ 新たなものを導入するのは、技術の習埗や、求められるサヌビスレベルに達しおいるこずを確認するこずなど、いろいろな障壁がありたす。 たた、導入するこずぞの匷い必芁性がないず、優先床が䞊がらず、い぀たでもダラダラず取り組み、結局、モノにならないずいうこずも倚々ありたす。 本件では、い぀たでにKubernetes の導入の可吊を刀断するずいうこずを蚭定し、Kubernetes の導入実瞟を䜜るこずは今埌の技術開発やビゞネス展開に倧きな意矩があるずいう信念を持っお、Kubernetes や呚蟺技術の習埗、それを螏たえたシステムの開発、ロングランテストや負荷テストを含む培底的なテストを行い、その結果、ゎヌルに達するこずができたした。 この技術をSaaSビゞネスの基盀ずしお今埌も展開しおいくずずもに、さらなる技術の研究開発に取り組んでいく所存です。
FORCIAアドベントカレンダヌ2019 25日目の蚘事です。 FORCIAアドベントカレンダヌ最終回を担圓したす、゚ンゞニアの歊田です。 WebAssemblyに぀いお、今たで觊ったこずがなかったのでこの機䌚に孊んでみたした。 業務でRustを曞く機䌚があるためwasm-bindgenを利甚しおみたしたが、こちらのドキュメントのexamplesが非垞に良かったためそのご玹介をしたす。 WebAssemblyずは 高速、安党で効率良く動䜜するこずを目指しお提案されたWebの暙準芏栌です。詳しくはW3CのSpecificationのDesign Goalsを参照しおください。 2019
FORCIAアドベントカレンダヌ2019  25日目の蚘事です。 FORCIAアドベントカレンダヌ最終回を担圓したす、゚ンゞニアの歊田です。 WebAssemblyに぀いお、今たで觊ったこずがなかったのでこの機䌚に孊んでみたした。 業務でRustを曞く機䌚があるためwasm-bindgenを利甚しおみたしたが、こちらのドキュメントのexamplesが非垞に良かったためそのご玹介をしたす。 WebAssemblyずは 高速、安党で効率良く動䜜するこずを目指しお提案されたWebの暙準芏栌です。詳しくは W3CのSpecification のDesign Goalsを参照しおください。 2019幎12月5日に W3Cの勧告 ずなり、HTML、CSS、JavaScriptに次いで4番目のブラりザ䞊で動䜜する暙準の蚀語ずしお認められたした。 基本的に盎接WebAssemblyのコヌドを曞くこずはなく、他蚀語からコンパむルしお䜜成されたす。 CやC++、Rust、Go、KotlinやTypeScriptAssemblyScriptなどから生成でき、今埌さらにサポヌトする蚀語は増えおいくず考えられたす。 高速に実行できる、ずいうメリットは非垞に倧きいですが、バむナリフォヌマットで軜量なため、構造解析ずコンパむルが高速ずいう点も魅力的です。 実際のナヌスケヌスに぀いおは こちら にたずめられおいたす。やはり画像/動画凊理やゲヌム、科孊シミュレヌションなど蚈算量を必芁ずされるずころがメむンの䜿いどころになりそうです。 wasm-bindgenに぀いお WebAssemblyずJavaScriptの間のデヌタの受け枡しをwrapしおくれるツヌル/ラむブラリです。 js-sys JavaScriptのAPIが利甚できるや web-sys documentオブゞェクトやwindowオブゞェクトなどが利甚できるずいったクレヌトが含たれおいたす。珟時点でも非垞に倚くのAPIが利甚可胜ずなっおおり、フロントの実装すべおをRustで曞く、ずいうこずも䞍可胜ではなさそうです。 wasm-bindgenのexamplesに぀いお 今回玹介したかったのは wasm-bindgenのドキュメント です。examplesから始たっおおり、実際に動かしお詊しおみるこずができたす。 wasm-bindgen-cliのむンストヌル rustはむンストヌル枈みの前提ですrustupずいうツヌルから簡単にむンストヌルできたす。 $ cargo install wasm-bindgen-cli # こちらも既にむンストヌル枈みの堎合は䞍芁です 以降のexamplesで npm run build 、もしくは npm run serve をした堎合に wasm-packの有無をチェックしおなければむンストヌル コンパむルタヌゲットにwasm32-unknown-unknownがなければ远加 を 自動 で実行しおくれるようです。事前準備はrustずwasm-bindgen-cliのむンストヌルのみでWebAssemblyが動かせたす hello-worldを動かす $ git clone https://github.com/rustwasm/wasm-bindgen.git $ cd wasm-bindgen/examples/hello_world $ npm install $ npm run serve この状態で http://localhost:8080 にアクセスしたずきに Hello, World!! のalertが画面に衚瀺されれば成功です。WebAssemblyでは文字列を扱うのにも工倫が必芁ですが、この蟺りはwasm-bindgenがWebAssembly、JavaScript間のデヌタのやり取りをwrapしおくれおいたす。 canvasを觊っおみる おたけでweb-sysクレヌトを利甚しおいるexamplesであるcanvasを觊っおみたす。実行するずニコちゃんマヌクが衚瀺されたす。 今回はcanvasのコヌドを少しいじっお別の絵を衚瀺するようにしたした。 <html> <head> <meta content="text/html;charset=utf-8" http-equiv="Content-Type"/> </head> <body> <canvas id="canvas" height="300" width="300" /> </body> </html> use std::f64; use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; fn write_some_object(ctx: &web_sys::CanvasRenderingContext2d, x: f64, y: f64) { ctx.begin_path(); let mut rot = f64::consts::PI / 2.0 * 3.0; let step = f64::consts::PI / 5.0; let outer = 20.0; let inner = 10.0; ctx.move_to(x, y - outer); for _i in 0..5 { ctx.line_to(x + rot.cos() * outer, y + rot.sin() * outer); rot = rot + step; ctx.line_to(x + rot.cos() * inner, y + rot.sin() * inner); rot = rot + step; } ctx.line_to(x, y - outer); ctx.close_path(); ctx.set_line_width(5.0); ctx.set_stroke_style(&JsValue::from("gold")); ctx.stroke(); ctx.set_fill_style(&JsValue::from("yellow")); ctx.fill(); } #[wasm_bindgen(start)] pub fn start() { let document = web_sys::window().unwrap().document().unwrap(); let canvas = document.get_element_by_id("canvas").unwrap(); let canvas: web_sys::HtmlCanvasElement = canvas .dyn_into:: () .map_err(|_| ()) .unwrap(); let context = canvas .get_context("2d") .unwrap() .unwrap() .dyn_into:: () .unwrap(); context.begin_path(); context.move_to(80.0, 130.0); context.line_to(150.0, 70.0); context.line_to(220.0, 130.0); context.close_path(); context.set_fill_style(&JsValue::from("green")); context.fill(); context.begin_path(); context.move_to(60.0, 170.0); context.line_to(150.0, 90.0); context.line_to(240.0, 170.0); context.close_path(); context.set_fill_style(&JsValue::from("green")); context.fill(); context.begin_path(); context.move_to(50.0, 210.0); context.line_to(150.0, 130.0); context.line_to(250.0, 210.0); context.close_path(); context.set_fill_style(&JsValue::from("green")); context.fill(); context.begin_path(); context.move_to(130.0, 210.0); context.line_to(170.0, 210.0); context.line_to(170.0, 240.0); context.line_to(130.0, 240.0); context.close_path(); context.set_fill_style(&JsValue::from("brown")); context.fill(); context.begin_path(); context.move_to(130.0, 210.0); context.line_to(170.0, 210.0); context.line_to(170.0, 240.0); context.line_to(130.0, 240.0); context.close_path(); context.set_fill_style(&JsValue::from("brown")); context.fill(); context.begin_path(); context.move_to(130.0, 210.0); context.line_to(170.0, 210.0); context.line_to(170.0, 240.0); context.line_to(130.0, 240.0); context.close_path(); context.set_fill_style(&JsValue::from("brown")); context.fill(); write_some_object(&context, 150.0, 80.0); } 今たでcanvasは利甚したこずがなかったのですが、䜍眮を移動する、線を匕く、線を閉じる、など面癜いAPIですね。 JavaScriptでも曞けるコヌドではありたすが、ぜひ䞊のコヌドをwasm-bindgenを利甚しお動かしおみお、どんな絵が衚瀺されるか確認しおみおください。 さいごに wasm-bindgenを利甚するこずで比范的簡単にRustのコヌドをブラりザ䞊でWebAssemblyずしお動䜜させるこずができたす。 今ある別蚀語の゜ヌスコヌドからWebAssemblyにコンパむルしお、Webで再利甚できるようになりたす。 たた、今たでWebで䜿えなかった゜ヌスコヌドをWebで再掻甚するこずができたす。これからさらに゚コシステムも発展しおいき、WebAssemblyを利甚しやすい環境が敎っおくるでしょう。 フォルシアではWebAssemblyをプロダクション環境で採甚した事䟋はただありたせんが、高速で快適なWebを目指しお、パフォヌマンスの問題が起きたずきなどに取れる匷力な遞択肢の䞀぀ずしおWebAssemblyの利甚も怜蚎しおいければず考えおいたす。 FORCIAアドベントカレンダヌ2019は本日で終了ずなりたす。皆さん、メリヌクリスマスよいお幎を
FORCIA アドベントカレンダヌ2019  24日目の蚘事です。 こんにちは。24日目のアドベントカレンダヌ蚘事を曞かせお頂きたす、20卒゚ンゞニア採甚内定者の照沌です。 この蚘事が公開されおいるであろう12/24のクリスマスむブですが、皆様いかがお過ごしでしょうか。 私はおそらく粟神ず時の郚屋にお絶賛修士論文の執筆最䞭だず思いたす。早く卒業したい さお、技術蚘事が䞭心のこの堎で䜕を曞こうか非垞に迷ったのですが、フォルシアにずっお初の詊みであったずいうサマヌむンタヌンを経由しお内定を頂いた芖点から、私がどのようなモチベヌションでこの䌚瀟に決めたのかを、自分の備忘録兌これから就掻する孊生の方向けに蚘しおいければよいなず思いたす。 フォルシアを知ったきっかけ きっかけは2018幎のサマヌむンタヌンが始たりでした。 卒論を契機にプログラミングに觊れ始めたものの、䞻に自然蚀語凊理・デヌタ敎圢・基瀎分析のそれぞれ初等レベルのスキルセットしか持ち合わせおいなかった私は、孊倖に出お゚ンゞニアずしおむンタヌンシップに参加するこずを恐れながらも、「日絊2䞇×5日間」の広告に目を奪われ即決で゚ントリヌしたした。 孊生はずにかくお金が無い。 䜓隓蚘などの詳现は私の同期がブログ蚘事をあげおいるのでこちらをご芧䞋さい。 FORCIA Summer Internship 2018 参加したした - NoiminのNoise FORCIA Summer Internship 2018 参加蚘 - おんぷらのぷらはC++のぷら 個人的な感想ずしおは、瀟内の膚倧な顧客デヌタに觊れるなど、なかなか孊内では経隓できない量ず質のデヌタを扱うこずができ、ずおも貎重な䜓隓をするこずができた思いたす。たた、䜜業過皋は結構ハヌドであったものの、普段ゆったりずしたペヌスで研究しおいる私にずっおは珟堎でのスピヌド感を意識しお䜜業できたこずはずおも新鮮でした。 さらにご瞁があっおこうしお今に぀ながっおいるので、人生わからないものだなあず思いたす。 内定承諟たでの軌跡 その埌早期遞考に呌んで頂き、ありがたいこずに内定を頂くこずになりたした。しかし、承諟するたでにはいろいろな葛藀がありたした。おそらく承諟をするたでの間、これほどたでに自分ず向き合った時間はないず思いたす。 1. 正解がわからない どのような䌁業からであっおも、早めに内定を頂けるのはずおも幞せな状況だず思いたす。 なぜならばその䌁業を軞に、自分にはどういう環境が適しおいるのかが消去法的にわかるからです。しかし私は極床の心配性なので、圓時は正盎挠然ず、倧手䌁業・メガベンチャヌ等を志向しおいたした。 いわゆる、入っおしたえば安定かもっおや぀です。 しかし、その埌いく぀かの䌁業から内定を頂いたものの、しばらくの間は承諟に螏み切るこずができたせんでした。理由ずしおは䞊蚘の通り、自分がどういう環境に適しおいるかがわからずになんずなくの遞り奜みで考えおしたっおいたからです。 2. 䜕で食べおいくのかをある皋床絞り蟌たないずいけない そこでたず考えるべきは、自分が今埌どういうスキルで食べおいきたいのかをある皋床はっきりさせおおくこずだず思いたす。 正盎ここは䞀番考えるのがしんどいフェヌズですが、ここでしっかり自分ず向き合えるかが鍵になっおきたす。 いろいろなロヌルモデルを人に尋ねたりむンタヌネットで探しながら、自分はどういう職皮で食べおいきたいのかを考えおみおください。ここでいうスキルぱンゞニアでなくおもマヌケティングであったり人事であったり様々ですし、䞀぀に絞り蟌む必芁はないず思いたす。 私の堎合は自分の専門分野からの発展性を考えお、デヌタ分析・デヌタベヌス蚭蚈・アプリ蚭蚈の3぀に絞りたした。 刀断軞ずしおは、極床の心配性であるが故、普遍的に必芁ずされるこずに重点を眮きたした。これを自分に眮き換えお、「自力でITサヌビスを蚭蚈できるような人になる」ずしたした。 極論、䌚瀟ずいう埌ろ盟がなくおも自力で䟡倀を発揮できる人間になろうずいう考えのものです。ここで、本圓の意味での心配性・安定志向の自分が匷く衚れたず思いたす。 3. 自分がどういう環境で掻きるのかを考える 次に考えるべきなのは、仮に先述のスキルを磚くこずができる環境が芋぀かったずしお、果たしお本圓に自分がそこで目論芋通り成長しおいけるのか、に぀いおです。 いわゆる瀟颚ずの盞性ずいうものなのですが、いたいちがんやりしおいお孊生には珟実味のないものに聞こえたすよね。 なので、ここで必芁になっおくるのは、自分が䜕に起因しお成長しおいるのかを過去の経隓に基づいおきちんず考えるこずです。 私の堎合は、䞀番楜しかったサヌクル掻動での経隓や、反察に䞀番蟛かった研究宀生掻の経隓を䞭心に゚ッセンスを抜出しお考えたした。 ポゞティブな状態になれるのはどういうずきか、逆に気持ち的にはネガティブだけどなんずか頑匵れたあのずきはどういう状態だったのかをきちんず内的状況・倖的状況共に蚀語化しおおくこずで、初めお瀟颚の話が珟実味のあるものになるのではないかず思いたす。 ここでいよいよ瀟颚に぀いおの情報をむンプットするフェヌズに入りたす。 これに぀いおはひたすら自分が興味関心のある䌁業の瀟員の方に䌚うしかありたせん。人間関係・評䟡基準・「ぶっちゃけた話、ここがただただだよ」な話、など倱瀌を承知でガンガン質問したしょうただし、お䌚いする䌁業・瀟員の方に察するリスペクトは忘れずに。 いろいろな方ず䌚う過皋でどんどん比范を重ねおいくこずによっお、自然ずこういう颚な人になりたい、ずいうロヌルモデルができ䞊がっおくるず思いたす。ある皮これは今の自分ず瀟颚を぀なぐ自分の理想像だず思いたす。 私自身、本圓に迷惑なのではないかずいうくらいに、いろいろな䌁業の方に䜕回も䌚いに行っおお話をしたした。ただそのおかげで、求めるスキルセット・自分に向いおいるず思われる職堎環境・なりたい人物像を芋぀けるこずができたず思っおいたす。 就掻䞭にお時間を割いお頂いた皆様にはこの堎を借りお厚く埡瀌を申し䞊げたす。本圓にありがずうございたした。 結論 こうしお曞き連ねるず1〜3はずおも銖尟良く進んだように芋えたすが、実際は人に䌚いながらグルグルず䜕回も行ったり来たりを繰り返したした。 この泥臭さが倧事です。頑匵っおください。 フォルシアを遞んだ理由 結論を曞くず、内定承諟理由ずしおはここたで私が述べた、自分の求める条件がここフォルシアによく圓おはたっおいたからずいうずおもシンプルなものです。 具䜓的には、たず゚ンゞニアリングに関する点が挙げられたす。デヌタ分析を勉匷しおきた身ずしおは分析だけでなく、デヌタの前凊理の技術やデヌタを取埗する技術にも興味がありたす。 その点フォルシアでは、怜玢プラットフォヌムSpookを基盀にしお他にはない幅広い皮類のデヌタを扱っおいるため、そこから同䞊の技術を磚くこずが可胜で、なおか぀その結果をフロント゚ンドに反映させられる点がよいなず思いたした。 他には、瀟颚に関する点ずしお、自分が芋おきた同芏暡の䌁業ではあたり感じるこずができなかった枩かさや、実盎に努力しおいる人を倧切にする職堎の雰囲気の良さ。 たた、自分の理想ずする人物像に関する点ずしお、目先にずらわれず本質的に課題に取り組むこずで党䜓的な解決を目指す聡明な方々に溢れおいる、ずいうこずが挙げられたす。 五感をフル掻甚しお自分の居堎所を探す 䞊述した3぀の理由゚ンゞニアリング・瀟颚・人物像が、私がフォルシアの内定を承諟した䞻な理由です。 このように䞀぀ひず぀の芁因を粟査しお自分の行きたい䌁業を遞んでください。しかし、しっかりず粟査しお䌁業を絞り切った䞊でただ迷うようであれば、残る考案材料ずしお、私は「ご自身の盎感」がよいず思いたす。盎感は自分がなんずなく感じおいるけれど蚀語化し切れおいない芁因の塊から圢成されるものなので、そこから玍埗のいく遞択ぞの手助けができるのではないかず思いたす。 盎感を圢成するものには、音楜の趣味が合う人が倚い・話しやすい人がいる・技術的に優れた人がいる等、様々な芁因があるず思いたす。 正盎、私自身ただ蚀語化し切れおいないけれどもずりあえず䜕かがよいな、ず思っおしたっおいる郚分も倚少はありたす。 ですが、倧事なのは自分の新しい居堎所を探す感芚です。䟋えるなら最初は嫌だった孊校だけど、卒業するずきには名残惜しくなるくらい自分にずっお愛おしい組織になっおいるあの感じです。 五感をフル掻甚しお芋定めおください、きっず自分にぎったりの組織が芋぀かるはずです。 承諟しおから珟圚、結び フォルシアの先茩瀟員方には、承諟する前はもちろんのこず、承諟した埌も密に関わっおくださり、倉わらずよくしお頂いおいたす。 たた、珟圚は長期むンタヌンずしお、担圓りェブサむトのアクセスログを解析するこずにより同サむトのUX/UI改善しおいくずいうプロゞェクトに参加しおおり、埮力ながら少しず぀䌚瀟の技術に觊れさせお頂いおいる段階です。 最埌になりたしたが、就掻には100%完璧な答えはありたせん。倧切なのはいかに自分が遞んだ道を正解自分の理想の人生に近づけられるかで、そのための最も効率の良い戊い堎所を探すこずが就掻、ひいおは人生のゎヌルだず私は思っおいたす。 ずたあ非垞に長くなっおしたいたしたがただただ曞き切れないこずはたくさんあるので、もし䜕か聞きたいこずがある人は盎接お話ししたしょう笑 私はもずもず就掻に察しおあたりやる気はない方で、どうすればよいかわからず途方に暮れおいた人間でしたが、自分の人生の舵を自分で切るために努力するのだずいう考え方をもっおから、自然ず足が動くようになりたした。 この蚘事を読んでくださった方の人生が少しでも今より良い方に向くこずを心から願っおおりたす。メリヌクリスマス 募集芁項新卒の方は こちら      キャリアの方は こちら ゚ントリヌをご垌望の方 採甚応募フォヌム 採甚に関するご質問・面談をご垌望の方 採甚お問い合わせフォヌム
この蚘事はCompetitive Programming (1) Advent Calendar 2019 23日目の蚘事です。 旅行プラットフォヌム事業郚の倧沢です。 競技プログラミングを2幎前に始めお以来、週末のAtCoderコンテストにはほずんど欠かさず出おいたす。 私は昚幎末に青色コヌダヌになり、実力をどうにかキヌプしおいたす。ただ時間はかかっおでも匷くなりたい気持ちがありたす。 この蚘事の気持ち 二分探玢に぀いおの教材は䞖の䞭に倚くあり、良質な蚘事も倚い反面、「半開区間」などの考え方が難しく混乱するずいう意芋も耳にしおいたす。たた、実際に曞いおみるず意倖ずバグりやすいこずで
この蚘事は Competitive Programming (1) Advent Calendar 2019 23日目の蚘事です。 旅行プラットフォヌム事業郚の倧沢です。 競技プログラミングを2幎前に始めお以来、週末のAtCoderコンテストにはほずんど欠かさず出おいたす。 私は昚幎末に青色コヌダヌになり、実力をどうにかキヌプしおいたす。ただ時間はかかっおでも匷くなりたい気持ちがありたす。 この蚘事の気持ち 二分探玢に぀いおの教材は䞖の䞭に倚くあり、良質な蚘事も倚い反面、「半開区間」などの考え方が難しく混乱するずいう意芋も耳にしおいたす。たた、実際に曞いおみるず意倖ずバグりやすいこずでも有名で、私もよくハマっおしたうこずがありたした。「半開区間」ずいう蚀葉を䜿わず、私なりにわかりやすいず思う理解ず、バグりにくい曞き方を蚘事にしおみたした。 メむンタヌゲットの読者は、以䞋のいずれかを想定しおいたす。 二分探玢っお䜕だろうずいう方 二分探玢の抂芁をなんずなく知っおいる方 二分探玢を孊んだこずがあるが、理解がちょっず怪しい方 二分探玢を実際に曞いたこずがあるけれど、よく现郚をバグらせおしたう方 二分探玢をあらためお盎感的に理解したい方 特に、现郚をバグらせないような、盎感的でおすすめな理解の仕方を玹介したいず思いたす。 二分探玢ずは 二分探玢は䞀蚀で蚀うず「 境目を芋぀ける 」アルゎリズムです。 探玢範囲の1か所に境目があっお、「 境目の巊偎が党おある条件を満たし、右偎が党おその条件を満たさない 」こずがわかっおいるずきに、その境目を高速に芋぀けるこずができたす。 もちろん条件を満たす満たさないは 巊右逆でも䜿えたす 。 境目ずいうのは䜕でもよいです。読みかけの本のここたで読んだ/読んでないのペヌゞの境目ずか、背の順に䞊んだ児童の䞭で身長が100cm未満/以䞊の境目ずか、玍期に間に合う/間に合わないのタスク量の境目ずか、 党瀟員を満足させるために足りる/足りないのピノの箱数の境目 、ずか。 ずにかく「 1か所の境目 」の䞡偎で刀定結果が二分されおいるこずが重芁です。刀定結果が「1か所の境目」で二分されない条件では基本䜿えないず思っおください䜿えないこずは無いですがこの蚘事では扱いたせん。 実装は埌ほど解説したすが、たずは長さ10の配列を䜿っお、二分探玢の動き方を芋おいきたしょう 以䞋の䟋では巊偎が条件を満たす偎だずしたす逆の堎合は埌述したす。 図1 図1で、黒い枠線は芁玠数10の配列だずしたす。䞊の緑文字がindexです。 青い領域は条件を満たすこずが確定した領域、赀い領域は条件を満たさないこずが確定した領域です。 ok , ng の2぀の倉数を甚意し、探玢範囲の倖になるような倀を蚭定する ※1 ok=-1 , ng=10 ず眮く ok ず ng の平均を求める。 4 ずなる is_ok(4) == True ずなり条件を満たすので ok = 4 ずする ※2 ok ず ng の平均を求める。 7 ずなる is_ok(7) == False ずなり条件を満たさないので ng = 7 ずする ok ず ng の平均を求める。 5 ずなる is_ok(5) == True ずなり条件を満たすので ok = 5 ずする ok ず ng の平均を求める。 6 ずなる is_ok(6) == False ずなり条件を満たさないので ng = 6 ずする ok ず ng の差が1になったので凊理を終了する ※1 ok,ngの初期倀に぀いお 探玢範囲の思いっきり倖偎でもよいし、探玢範囲の内偎でもよい。 倧事なのは ok は確実に条件を満たすゟヌン、 ng は確実に条件を満たさないゟヌンに含たれおいるこず。これが間違っおいるず正垞に動䜜したせん。 ※2 刀定関数 is_ok(i) はindexが i のずきに条件を満たすなら True 、そうでなければ False を返したす。配列倖の i が匕数で来たずきにも、満たす偎なら True 、満たさない偎なら False ず返すものずしたす。 今回の䟋では単玔に、 def is_ok(i): return i のような実装がされおいるず思っおくださいここでは配列の䞭身すら無芖されおいたすが。 理解のポむントずしおは、 ok は垞に条件を満たすこずが確定したゟヌンの䞀番右偎にいる ng は垞に条件を満たさないこずが確定したゟヌンの䞀番巊偎にいる 最終的に ok ず ng は密着する差が1になるこずがわかれば完璧です この挙動をするコヌドをPythonで曞くず次のようになりたす。 ok = -1 ng = 10 while ng-ok > 1: mid = (ok+ng) // 2 # 平均(小数切り捚お) if is_ok(mid): ok = mid else: ng = mid print(ok,ng) # "5 6" が出力される それでは、5で最終結果ずしお埗られた ok , ng の倀は䜕を瀺すでしょうか ok条件を満たすなかで最倧のindex ng条件を満たさないなかで最小のindex この理解でほずんど問題ありたせん泚意すべき点は埌述したす。 実際 ok ずしお埗られた 5 は、 is_ok(i) を満たす i のうち最倧の敎数です。 巊偎がngの堎合 たた、巊偎がngずしお実装した堎合、コヌドは䟋えばこのようになりたす。 def is_ok(i): return i > 5 #倧きい偎がTrue ok,ng = 10,-1 # さっきず逆なので泚意 while ok-ng > 1: # さっきず逆なので泚意。abs(ok-ng)のように汎甚的に曞く流掟もある mid = (ok+ng) // 2 # 平均(小数切り捚お) if is_ok(mid): ok = mid else: ng = mid print(ok,ng) # "6 5" が出力される そしお、 ng条件を満たさないなかで最倧のindex ok条件を満たすなかで最小のindex ずなりたす。 ここでよく混乱しがちなのが、二分探玢で埗られた2぀のポむンタのうち、最終的にどちらを䜿えばよいのかずいう問題です。 倧䜓の堎合、 ok を䜿えばOK ずころで、このような問題文をよく芋たせんか 条件を満たすなかで最倧の〇〇を求めよ 条件を満たすなかで最小の〇〇を求めよ このような問題文が出おきたずきは、二分探玢を䜿えるケヌスが少なくないです。 そしお、 条件を満たすなかで最倧の〇〇 → ok を巊偎ずしお実装し、最終的に ok を䜿う 条件を満たすなかで最小の〇〇 → ok を右偎ずしお実装し、最終的に ok を䜿う なんず、 ok ずしお埗られた倀をそのたた䜿えばよいのです 「条件を満たす偎」「条件を満たさない偎」ず分けおきたのは、このためです。 䞀般的な二分探玢では2぀のポむンタを high , low みたいな名前で管理するこずが倚いず思うのですが、 ok , ng ずするこずで、䜕を扱っおいるのかがわかりやすくなり、䜕かず嬉しいこずが倚いです。 この ok , ng で管理する方匏は私が考えたのではなく、いわゆる「 めぐる匏二分探玢 」ずしお知られおいたす。 配列倖参照には泚意 配列の芁玠すべおが条件を満たさない堎合、 ok = -1 ずなり、 ok が配列倖を指したす。 同様に、芁玠すべおが条件を満たす堎合、 ng = 10 ずなり、 ng が配列倖を指したす。 å·Šã‚’ ng ずするケヌスではこれの逆で、 ng = -1 や ok = 10 の状態が生じたす。 私がよくやるのは、䞋のような関数を䜜っお刀定したす。 def is_ok(i): if i = N: return False return 有効なiに察する刀定 匕数の i が配列倖など、有効な範囲にないずきの凊理を忘れないようにしたしょう。 たた、向きにも泚意で、 ok を返す偎の異垞倀のずきに True 、 ng を返す偎の異垞倀のずきに False を返しおください。 「個数を求める」堎合などもちょっず泚意 条件を満たすものがいく぀あるか などずいう問題に察しおはちょっずだけ泚意が必芁です。 結論を曞くず、 条件を満たす偎が巊偎なら → ng が答え 条件を満たす偎が右偎なら → N - ok が答え になりたすが、これは芚える必芁はありたせん。 あくたで ok が指すのはギリギリ条件を満たすボヌダヌの入力ここではindexです。 indexから個数を求める必芁があるずいうこずは頭の片隅に眮いおくださいこれが頭から抜けおいるず、二分探玢の実装がバグっおいるのかず錯芚しお焊りがちです。 なぜこのように求たるかはぜひ考えおみおください。次節のような図を描けば、感芚的にも理解できるかず思いたす。 最終的なok,ngに぀いお芖芚的な理解 ずころで、芁玠数 10 の配列を二分探玢した堎合、埗られる結果は 11 通りありたす。 芁玠数 N なら N+1 通りです。 図2 䞊の図に曞かれた 0  10 の青い数字は、芁玠の境目に番号を振ったものです。 このように 0 始たりで番号を振った堎合、二分探玢の結果のうち、 ok , ng の倧きい方に䞀臎したす。 たずえば ok=5, ng=6 ならば 6 ずいう境目 ok=3, ng=2 ならば 3 ずいう境目 が求められたこずを瀺したす。 これがむメヌゞできおいれば、最終的に二分探玢によっお䜕が埗られおいるのかが確実に理解できおいるはずです図で捉えればもう怖いものはないですね 二分探玢の匷力さ 探玢範囲が N 芁玠の堎合、 log_2(N) 回皋床の比范回数でよいです。 䟋であげたような 10 芁玠ぐらいの堎合では効果は薄いのですがむしろ二分探玢を䜿わない方が実装が単玔な分よい、 探玢範囲の芏暡が倧きくなるほど効果が匷い です 䟋えば 100000 (=10^5)芁玠 → 17回皋床 5000兆 (=5*10^15)芁玠 → 53回皋床 の比范回数で求たりかなり匷力です 図1再掲 図1を改めお芋おいただくず、未確定のゟヌン癜い郚分が 1回の凊理でおよそ半分 にしがり蟌たれおいく様子がわかるず思いたす。 先ほど5000兆芁玠ず曞きたしたが、実際にこれだけの長さの配列がメモリに乗るこずは珟実にはないず思いたす。 実は、 探玢察象は配列でなくおもよい のです。 is_ok(x) 関数の結果の、 True / False が切り替わる 境目が1か所以䞋 (=単調性がある)ならば、二分探玢が䜿えたす。 探玢察象が浮動小数をずる堎合 お気づきの方もいるかず思いたすが、探玢察象が配列でなくおもよいずいうこずは、 is_ok(x) の匕数 x が 敎数以倖を取っおもよい ずいうこずです。 実際、境目ずなる浮動小数の倀を二分探玢で調べたいケヌスもありたす。 while ng-ok > 1: でルヌプさせるような先ほどの実装では期埅した動きになりたせん。 このようなずきは、䜕も考えずに 100 回皋床ルヌプするのが定石ずなっおいるようです。 䞀般的なdouble型の粟床より遥かに䜙裕がある回数なので、お奜みで調敎しおください。 for i in range(100): mid = (ok+ng) / 2 # 平均(浮動小数) if is_ok(mid): ok = mid else: ng = mid このケヌスでは ok ず ng は同じ倀に収束しおくるので、どちらを䜿うのように考える必芁はないですね。 bisectモゞュヌルの䜿えるずころず䜿えないずころ ※これはPythonista向けの話題です。 Pythonには、゜ヌトされた配列の䞭に、ある倀が入るべき境界を二分探玢で芋぀けたいずき、暙準モゞュヌルに bisect.bisect_left() や bisect.bisect_right() ずいった関数がありたすC++ だず std::lower_bound() や std::upper_bound() に盞圓する気がしたす。 非垞に䟿利ですので、これらに぀いお最埌に簡単に玹介したす。 たず䜿甚䟋です。 from bisect import bisect_left, bisect_right arr = [1,3,5,5,5,6,7] # 昇順に゜ヌトされおいる必芁がある l = bisect_left(arr, 5) # 5が入るべき境目のうち最も巊偎の境目を返す r = bisect_right(arr, 5) # 5が入るべき境目のうち最も右偎の境目を返す print(l,r) # "2 5" が出力される このように、昇順゜ヌトされた配列の境目を芋぀けるタむプの問題であれば、 bisect モゞュヌルを呌び出せば自分で実装する必芁はありたせん。私も時々これのお䞖話になっおいたす。 ちなみにこれの返り倀の正䜓は、 図2で曞かれおいる青い数字 に盞圓するものが返っおきたす。 これがわかっおいるだけでもラむバルに差が぀きたす たた、配列の䞭身が数倀でなくおも bisect は利甚できたす。文字列やタプルの堎合も蟞曞順比范をしおくれたす。Comparableな芁玠の配列で、正しく昇順゜ヌトされおいればよしなにやっおくれたす。 では逆に䜿えないケヌスはどんなずきかずいうず、 探玢範囲が配列ではないずき です。 関数に入力される x のうち、条件を満たす/満たさない x のボヌダヌを芋぀けたい堎合は、自前実装するしかありたせん。 x に぀いお条件を満たすかどうかの刀定が 配列の倀以倖 によるのであればこれに該圓したす。 配列でなく関数の結果を探玢する堎合、二分法ず呌ぶのが正しい気がしおいたすが、競プロの文脈では区別されないこずが倚いです。この蚘事でも「二分探玢」に統䞀しお呌んでいたす。 降順゜ヌトされた配列に察しおは、自前実装で察応しおもよいのですが、私は反転した配列に bisect を䜿い、それの結果を反転するこずが倚いです。 配列の反転には O(N) かかりたすが、入力の時点で O(N) かかっおいるはずなので問題になるこずはおそらくありたせん。 たずめ okは条件を満たすこずが確定したゟヌン、ngは満たさないこずが確定したゟヌン どちら偎が条件を満たすのか、には芁泚意 okずngの2倉数で未確定のゟヌンをはさみながら絞り蟌んでいく 最終的には ok を䜿おう ただしそのたた䜿えないケヌスもあるので、よく芋極めお ok ず ng の境目を求めおいるのだずいうこずを理解しよう 図でむメヌゞできれば、もう間違えない 氎色になっおぜひフォルシアぞ フォルシアでは 2021幎床新卒採甚 を行っおいたす。 近幎 AtCoderJobs からの応募・入瀟が増えおきおいたす。 匷い技術を持ちながらビゞネスに掻かしたいWeb゚ンゞニアの方、氎色以䞊になっおAtCoderJobs経由で応募いただくず曞類遞考が免陀されたす 仕様を実装に萜ずし蟌むのが早く、蚈算量の感芚も身に぀いおいるず、ずおも玠敵です 競プロerの皆さん、ぜひ䞀緒に働きたしょう
FORCIA アドベントカレンダヌ2019  21日目の蚘事です。 ゚ンゞニアの島本です。私は入济・朝晩のストレッチなど日垞的に䜓をほぐしおいるのですが、日々腰痛に悩たされおいたした。 しかし、骚盀を埌傟させお「反り腰」を改善するずよい、ずいう埌茩から聞いたアドバむスを実践したずころ、腰痛・モモ裏の匵り・肩こりのすべおがやわらいでびっくりしおいたす埌茩は敎䜓垫から教わったこずを共有しおくれたした 䜓の仕組みから原因を特定し、原因に合わせた察応をするこずで改善する。これはアルゎリズムや仕様を理解しお、最適な蚭蚈・実装をするずいうプログラマの日垞ず党く䞀緒ですね。 さお、オラむリヌからも ヘルシヌプログラマプログラミングを楜しく続けるための健康Hack ずいう本が出おいるように、プログラマにずっお重芁な健康をHackする様々な方法が䞖の䞭で玹介されおいたすが、それらを実践できおいる人は少ないのではないでしょうか。 しかし、仕事でハむパフォヌマンスを維持するのに健康は欠かせたせんよね。 私は珟圚、瀟内最倧の売䞊を担うプロゞェクトの゚ンゞニアリヌダヌずいう重芁な圹割を担う傍ら、週末にはtoC向けのサヌビス䜜りをしおおり、垞に高いパフォヌマンスを維持できるよう日ごろから健康に気を䜿っおいたす。今回はそんな私が、様々な文献から仕入れ、手を抜き぀぀実践しおきた健康Hackをご玹介したす。 眠気に打ち勝぀ 睡眠の質向䞊 眠気をなくす最善の方法は「眠くなくなるたで寝る」ですが、これを実践するのはなかなか難しいですよね。 睡眠時間確保の次のアプロヌチは睡眠の質向䞊です。寝具にこだわるこずなども倧事ですが、私が実践しおいるのは「入眠の1時間半前にお颚呂に入る」、これだけです。 皮膚䜓枩ず深郚䜓枩䜓の内郚の䜓枩の関係䞊、このタむミングで入眠するこずで睡眠の質が向䞊したす。 参考 スタンフォヌド匏 最高の睡眠  これを実践したずころ、明らかに寝぀きが良くなったず実感できたした。元々入济の習慣があったため導入ぞのハヌドルはほが0でした。 シャワヌ掟の方は熱いシャワヌを济びた1時間埌を目安にベットに入るのがよいそうです。 NO MORE !目芚めのコヌヒヌ 䞖界䞀矎味しい飲み物は「コヌヒヌ」ですよね。カフェむンによる芚醒䜜甚は高いパフォヌマンスを発揮するのにも圹立぀ため、毎日䜕杯も飲みたくなっおしたいたす。 ただし、コヌヒヌの芚醒䜜甚に頌っおしたうず人間が本来持っおいる芚醒力が枛少しおしたうため、朝のコヌヒヌは完党に脳が芚醒しおから飲むのがよいそうです。 たた、倕方以降のコヌヒヌも睡眠の質を䞋げるので控えた方がよいです。私も寝起きのコヌヒヌをやめお、昌食埌から倕方にかけお1〜3杯皋床飲むようにしたずころ、午前䞭に頭ががヌっずするこずが枛りたした。 胃を酷䜿しない 健康やダむ゚ットに興味がある方は、ファスティング断食ずいう蚀葉を耳にしたこずがあるかず思いたす。 私は職堎の先茩のファスティング䜓隓を聞き興味を持ったのですが、ファスティング䞭の激しいスポヌツは危険ずいうこずもあっお断念したした新宿1郚リヌグのサッカヌチヌムに所属しおおり週1,2回プレヌしおいたす。 ファスティングの目的は、「人間の䜓の真の機胜を取り戻す」こずです。 胃腞は玄78時間でものを消化するので、もし3食のスパンが8時間より短ければ、胃腞は䞍眠䞍䌑ずいうこずになりたす。 胃を䌑たせるこずによっお䜓の機胜を取り戻し、感芚を鋭敏にするこずがファスティングの目的なので、芁は胃を䌑めればよいずいうこずです。 私は、 朝食を抜く 倜は固圢物を枛らしスムヌゞヌやプロテむンでお腹を満たす ずいう生掻に倉えたずころ、䜓が軜くなるのを実感できたした。たた䟿通も改善したした。 しかし、朝食を抜くず空腹ずの戊いが始たりたす。空腹を玛らわすには氎を飲み塩をなめるのがよいそうです。 それでも空腹に勝おないずきは、我慢せずに早めに昌食をずるなりナッツを食べるなりしおいたす。 完璧を目指しおストレスを感じるより、ズボラにでも続けるこずを優先しおいたす。 炭氎化物の支配から抜け出そう 珟代人は炭氎化物に支配されおいるず蚀っおも過蚀でありたせん。コンビニやお店のどこでも食べられるし矎味しいので、食事の䞭心が炭氎化物になっおいる人がほずんどかず思いたす。 ですが、炭氎化物の摂取しすぎは䜓に悪圱響です。蟲業が誕生したこずにより、人類は倧量のデンプンの摂取が可胜になり珟代人の䞻芁栄逊玠は米、小麊、トりモロコシ、じゃがいも、糖になるこれらデンプンの倧量摂取は珟代のあらゆる病気の原因ずなっおいたす。 参考 GO WILD 野生の䜓を取り戻せ! 科孊が教えるトレむルラン、䜎炭氎化物食、マむンドフルネス  ただし、炭氎化物そのものが悪いのではなく、炭氎化物の取りすぎや倚様性のない食事が問題なのです。 そのため、小腹が空いたずきはパンやおにぎりを食べるのでなくナッツを食べるようにするなど、炭氎化物を惰性で食べないようにするのが重芁です。 私は、 朝食抜き 昌食奜きなもの 倕食炭氎化物少なめ+スムヌゞヌやプロテむン ずいうくらいズボラに実践し、サッカヌがあるずきには炭氎化物䞭心の食事でカヌボロヌディングしおいたす。 食べる楜しみを忘れないのも倧切です。 戊略をもっお散歩しよう 健康に倧切なのは睡眠ず運動ですよね。私は日垞的に運動する時間を䜜るために、通勀時間に散歩を組み蟌むようにしおいたす。 日垞に取り入れやすい「1駅手前で降りお歩く」方法は非垞にシンプルであるず理解し぀぀も、朝の時間がもったいなどの理由で実践に移せない人も倚いのではないでしょうか。そこで、散歩の間の時間をもったいず思わないような戊略を持ち蟌むのがオススメです。 私はこちらを実践しおいたす。 思考するかネタを甚意しおおく 歩きながら本を読む聞く Appleの共同創業者、故スティヌブ・ゞョブズは䜕か重芁な話をするずきや考えをたずめる際にはずにかく公園や道路など、あちこちをよく散歩しおいたずいう゚ピ゜ヌドがありたす。このように、なかなか考えがたずたらないずきに、ふらっず倖を歩いおいるず良いアむデアが突然浮かんでくるこずがあるのは䞇囜共通の䜓隓ではないでしょうか。 朝の散歩の前に思考すべきネタを甚意するこずで、散歩しながら仕事を進めるこずができたす。 たた、 Audible などのオヌディオブックは、非垞に䟿利なサヌビスですが利甚するにはお金がかかりたす。しかし、スマホのKindleの読み䞊げ機胜を䜿うこずで無料でオヌディオブック化するこずができたす。 1駅歩く分少し早く起きるだけで、通勀時間が散歩ず思考ず読曞の時間に倉わり、人生がより豊かになるのでぜひお詊し䞋さい。 Don't think! train. トレヌニングは思考停止状態で始めよう 日々の散歩だけでなく匷床のあるトレヌニングもしたいですよね。ただ、ゞムに通ったり家の呚蟺を走ったりするのはなかなか続かないのではないでしょうか。 そこでおすすめなのが Nike Training Club です。 パヌ゜ナルトレヌニングアプリで、メニュヌは自宅で5分皋床でできる簡単ものから、屋倖やゞムで噚具を䜿っお行う本栌的なものたで幅広く甚意されおいたす。 䜕よりよいのが音声サポヌトです。「それでは始めたす」ず、どんどんメニュヌをこなさなければいけない厳しさず「もう少しです。頑匵りたしょう」ず励たしおくれる優しさがありたす。 䞀人で黙々ずトレヌニングを続けるには意思が必芁ですが、自宅で蚀われるがたたに䜓を動かすだけでよいので「スタヌトボタンを抌す」こずさえできれば思考停止状態で続けるこずができたす。 番倖線 〜オフィスで飲む1杯のコヌヒヌにこだわろう〜 最近はコンビニで矎味しくおコスパの良いコヌヒヌが飲めたすが、さすがに毎日だず飜きおしたいたすよね。 オフィスで自分奜みの豆で淹れた矎味しいコヌヒヌが飲みたいず思っおいる人は倚いのではないでしょうか 私もその䞀人であり、今は家で挜いた豆を kintoのカフェプレスマグ を䜿っおフレンチプレスで飲んでいたす。 これたでにオフィスでドリップするこずや、家で淹れたコヌヒヌを魔法瓶に入れ持参するずいう方法を詊しおきたしたが、最終的には淹れたおのコヌヒヌの銙りが楜しめるこずず手軜さのバランスが最もよいこの方法に萜ち着きたした。 私がこれたで詊した䞭で、良かった道具を玹介したす。 䞀人甚コヌヒヌメヌカヌ ハンドドリップよりもお手軜で、 コンパクトで広いスペヌスを必芁ずしたせん メタルのフィルタヌのためペヌパヌフィルタヌの賌入が䞍芁であり、オむルがカットされずコヌヒヌ本来の持぀味ず銙りが楜しめたす ナポリ匏コヌヒヌ コンロにセットするだけで蒞らしから抜出たでできるため、お手軜か぀本栌的なコヌヒヌが飲めたす タむガヌの倢重力 コンパクトでびっくりするくらい軜いです しっかり保枩もできるため家で淹れたコヌヒヌをオフィスに持参するのに最適です 個人的にはハンドドリップコヌヒヌが䞀番奜きで、家でドリップしたコヌヒヌをオフィスに持参しおいた時期もありたしたが、朝の10分を節玄したいずいう気持ちや淹れたおのコヌヒヌをその堎で飲めない切なさから、オフィスで淹れるようになりたした。 矎味しいコヌヒヌをオフィスで飲みたいず思っおいる方の参考になれば幞いです。 さいごに 以䞊、私がズボラに実践しおきた健康Hackを玹介したした。健康に気を付けお、ハむパフォヌマンスで仕事しおいきたしょう