マイクロサービス、WebAPI、設計の初歩的なメモ

マイクロサービスとか WebAPI とか、相変わらず1周2周遅れで取り組んでいるわけですが、やっとなんかちょっと分かったような気がしたのでだいぶ初歩的なメモ。

サービスをどう分けるか

すごく簡単なところなんだけど「境界で隔てた独立したサービスがお互いのリリースを阻害しない」というところがなるほどなと思った。

いや、実際、自分の中では「複数のサービスが連携して動く」くらいの理解でしかなくて、一つのサービスが他のサービスに依存しているんだったら「どんどん開発環境の準備面倒くさくなるよね?」と思ってたんだけど、「リリースを阻害しない」ことが大事なら当然開発環境の準備も依存関係が面倒を起こしたらダメだなということが急にピンときた。

例えばすごく素朴な例で言うとサービスA とサービスB の二つのサービスがあったとして、サービスB でサービスA のデータを JSON で GET して表示

+---------+             +---------+
|Service A| JSON -> GET |Service B|
+---------+             +---------+

なんてことを想像していたのだけど、これは「サービスBの開発時に完全なサービスAの動作を必要」としており、リリースどころか開発プロセスまで重くしてしまっている。

そうではなくて、例えばサービスAのデータのうち「サービスBに必要なものを必要な形式で送り込んでおく」ようにすれば、サービスBはサービスBで独立して開発を進めることができる。1

+---------+             +---------+
|Service A| PUT -> JSON |Service B|
+---------+             +---------+

この場合、ごく素朴な例では恐らく GET のパターンより PUT のパターンの方が実装量は多くなる。それでも独立性は高く保たれ、両サービスの開発、リリースはお互いを阻害しない。もちろんサービス B に引きずられて A の負荷が上がってしまうということもない。

恐らくマイクロサービスについてはまず境界の分け方が話題になると思われるが、自分にとっては開発環境の再現しやすさがものすごく気になっており、それを考慮したうえで分けるとすれば GET 型よりは PUT 型で連携するようにした方が、初期の実装量は多くなってしまうが、のちのちの開発、リリースのペースを落としにくいのではないかというのが現在の理解。

※ もちろんサービスの連携方法としてこれが合う場合と合わない場合があるとは思うけど、リリースを阻害しないことがマイクロサービスの要件なのであれば、そもそも依存したサービスなしに開発できないのはマイクロサービスとして分割するのに適していないところで分割しようとしているのではないかという気がする。

マイクロサービスとWebAPI開発サイクル

WebAPI | The Good Parts という本によれば Web API は大きく

  • LSUDs ( Large Set of Unknown Developers )
  • SSKDs ( Small Set of Known Developers )

の2つに分けられるとある。

マイクロサービスという文脈で WebAPI を考える場合は後者の SSKDs 限定で考えてよい。

このマイクロサービス前提の WebAPI を当初から考えていた際に、どうしても納得いかなかったのが Swagger, API Blueprint などの仕様がクローズアップされる手法。

これについては

に書いた通り Pact を中心に置くと決めるのでよさそう

マイクロサービス的WebAPIの設計

WebAPI の設計については、「単に DB アクセスの wrapper みたいなのじゃ意味ないよね」というのは分かるんだけど、じゃあどうすればいいかはやっぱりよく分からなかった。ちょっと実際にやってみて分かったのは、

そうは言っても特に PUT 前提で考えるとデータストアの特性に API 設計は引っ張られざるをえない、という点。

例えば一気に書き込まざるを得ないファイルベースのデータストアのようなものを利用するとなった場合、PUT の API も一気に送る方式になる。そうすると個別に送る場合とデータ構造も異なってくる。特定のデータだけの UPDATE は難しいので、DELETE ALL と PUT のみ、みたいな形になる。

もちろん将来的にその方法はまずいというのが最初から分かっているのであればそれに適したデータストアを用意すべきだ。だが、まだしばらくそんなに本格的なデータストアは要らないな、ということであればこの判断もアリだろう。

今回、API ばかりを意識して設計を進めてしまった結果、実装しながら何回も設計をやり直すことが起きてしまった。これまで通常の Web サイト開発においては DB 設計と URI 設計を優先的に考えていたのだけれど、マイクロサービス的な WebAPI 開発においてもやはりそこら辺はあまり変えずにいけばよいのかなという気がしている。

少なくとも最後の Model での処理がちゃんと終わらないようなインターフェイスだけ「綺麗だから」とか「書きやすいから」ということで設計しても意味がない。GrapeだーSwaggerだーPactだーみたいなツールに振り回されているのは適切な設計作業じゃない。まぁ、ふりかえってみれば「そりゃそうだ」としか言いようがないんだけど、改めてそこを押さえつつ、ちゃんとインターフェイスとして使いやすくないとダメだね、と反省したのでした。

でも、そこら辺の見極めがつくようになれば、マイクロサービスというのは決して大げさな言葉ではなく、大規模サービスだからとかそういうことでもなく、力を抜いて自然とそういう設計ができるようになるんじゃないかな、ということがなんとなく想像できるようになってきた今日この頃でした。

結局大切なことは最終的に何が欲しいのか?であって、そこは外しちゃダメ。API だけを見て API 設計はできない。 1) 本来 DB 設計はどんなデータを「取得」したいかによって決まる。ダメなデータ構造がプログラムを複雑化するのと同様に、ダメなテーブル設計が DB の性能を殺す。だから画面で欲しい情報を整理して、DB 設計に落とし込む。2 2) URI 設計はユーザーとのインタラクションの設計と同時にアクセス解析のルール設定。 3) API 設計も最終的にそのサービス間のインタラクションはどこにキクのか?から逆方向に設計を進めていく。API は最後に決まる。もちろん、ここで決めたことしかできないとなるとこの API は汎用性が足りなくて不便ということになりかねないが、そこはそれ。マイクロサービス向け API は CDC を武器にどんどん変えていけばよい。YAGNI であり、そのための Pact だ。

そんな感じかな。

昨今では Web アプリはフレームワークに従うことで初心者に近い人でもある程度のものができるようになっている。それを一歩抜け出るきっかけになりそうな、そんな期待がある。

おしまい。

  1. 『マイクロサービスアーキテクチャ』の中の言葉を借りれば「データポンプ」 

  2. ということは全部の画面の欲しい情報が揃っていないと完全な DB 設計はできないので、実装と設計は本来不可分 

git checkout 分かってなかった

ずっとずっと git で svn revert したかった。git revert は意図していた機能と違った。Emacs の vc-mode がうまく動いている場合は vc-revert-buffer を使っていた。でも SCM を混ぜてるときとかうまく動かないし、そもそもバックエンドで何が起きてるか分かってないのってちょっと気持ち悪い。

実はこのネタは断続的につぶやいてたんだけど、今回お返事がもらえました。わーい。

12:14:04 >wtnabe< そういえば git で一部のファイルだけ svn 的に revert
する方法が未だに分からないな
12:28:49 <mumumu> @wtnabe git checkout -- foo
http://www.kernel.org/pub/software/scm/git/docs/git-checkout.html

git checkout …。使ってる! てゆーかめっちゃメモ書いてる!

何やってんだ><

branch を指定することしかできないと思い込んでいたらしい。恥ずかしい…。

PHPのオブジェクトIDを取得…できるのは5.2以降らしい

PHP のオブジェクトの同一性をチェックしたくなって、そういや PHP 5 からはオブジェクト ID を確認できるんじゃないか?と思い出して使ってみることにした。のだけど、PHP 5.1 までは

オブジェクト ID は目視できるだけで値として取得する方法がない

っぽい。

11:56:03 >wtnabe< PHP はオブジェクトの ID を取得する汎用の方法ってない
んだっけか
12:00:57 >wtnabe< もしかして : var_export からテキスト処理?
12:03:17 >wtnabe< あ、var_export() は var_dump() と違って ID が出ないな。
やっぱ取得する方法ないんか?
12:04:11 >wtnabe< もしかして : var_dump() して出力する前に cache を捕ま
えてゴニョゴニョ? やっとれません。

5.2 以降だと spl_object_hash が使えるらしい。

12:19:48 <shimooka> @wtnabe PHP5.2以降ですが、spl_object_hashとかどうで
しょう
12:22:22 >wtnabe< @shimooka spl … さっきまで sql だと思ってスルーして
ましたw
12:24:20 >wtnabe< @shimooka 結局今回は同一かどうかさえ分かればよかった
のでID要らなかったです。すいません。
12:25:48 <shimooka> @wtnabe w

PHP: spl_object_hash - Manual

なんだっけ。ちゃんと singleton になってるかどうか確認したかったのかな。よく覚えてない。

LLSpirit 宿おさえました

現場の雰囲気がよく分かっていませんが、カンファレンスですから、やはりスーツに名刺持参が礼儀ですよね!とベタなボケをかましてみる。

名刺はあった方がいいんだろうけどなぁ。挨拶しようにも誰も知らないっつーんだから名刺も役に立たない可能性も高い。うーぬ。

QRコードを作成して携帯に保存していくっつーのが簡単か? 楽しすぎ? MiniCards 勉強しろ?

MacPorts は PCC 10.3 にはやはり厳しそう

ビルドに失敗するものがちらほらと。それより何よりコンパイルが遅いので必要なツールを揃えるにも一苦労。PPC G4 1GHz ではもうダメですか。クライアント PC で何から何までコンパイルして揃えるのはやっぱちとキツイんだよなぁ。

かと言ってコンパイル以外には不満はないから、別に機械そのものを Intel にしようなんて気にもならねーしなぁ。

awk のハマりどころ

awk と言っても gawk ね。あとは知らない。

  • 文字列をついシングルクォーテーションで囲んで怒られる
  • 「改行コード取らなきゃ」と思っちゃう
  • 文字列をつい . で連結した気になって怒られる

gawk は Fink で入れた gawk 3.1.4 を使っている。3.1.x は gettext で国際化なんだよねー、gettext よく分からないんだよねーと思ってたんだけど、LANG をきっちり設定するかあるいは何も設定しなければなんかそれでオッケーっぽい。jXXX 関数はないけど別にいいや。1

ところで gawk の 3.1 系統は TCP/IP が扱えたりかなり野心的で面白そうなのに、この日本語を扱う際の最初の一歩でつまづいてる人が多いような気がする。Windows の場合はこれをやる、Linux の場合はこれをチェックしろとかっていう最低限のノウハウがないまま「なんとなく国際化してるらしいけど今までと使い勝手違うからいやなんだよね」という層を作ってしまっているような。

2ch なんかでも gawk3.0.4+mb の方が 3.1.x よりウケはいい2。でもメンテナはもうやる気ないわけですよ。本家が国際化してんだから無理に独自実装のマルチバイト化やる必要ないじゃんと。だったら 3.1.x についていくしかないと思うし、強力になってるんだから、どうせ使うなら 3.1.x 以降を使えた方が幸せになれると思う。

え、全部 Ruby か Python でいいじゃん? んー。なんかねぇ、使っちゃうんですよねぇ。使い続けるスクリプトを作るためには使わない方がいいと思うけど、フィルタとしてはやっぱ使いやすいのよね。

※ 凝り始めると結局 Ruby とかで書き換えちゃうんだけど。

  1. ただし「3.1.5 以降は」国際化のスイッチが入るとすべて jXXX() 相当になるらしい。 

  2. マルチバイト対応のほかに cmd.exe が対応していないシングルクォートに独自に対応しているってのもある。これは cmd.exe のことを考えていないドキュメントの方に問題があるんだよなぁ。 

最近もっともだなぁと思ったこと

  • むしろ (サマータイム、実は好評? @ /.-j)

確かに夏は朝の涼しい時間に寝ていられる方が特に灼熱の都会に住んでいる人の健康にはよさげ。つか朝って結構涼しいよね。びっくりする。もう8月も目の前だってのに。

偽サマータイムをサマータイムと読んでしまうことで本物の邪魔臭いサマータイムの浸透を妨げるというアイディアは秀逸だなと思った。

ピークシフトはいいと思うよぉ。土曜出勤すると妙に仕事がはかどるのと同じようなもんだと言えば身にしみて分かっちゃう人もそれなりにいるんじゃないかな。

何もこんなに遅れてサマータイムネタじゃなくたっていいじゃないか? これがピークシフトですよ!(嘘

名付けて mailread_ar.rb かな?

Ruby には mailread.rb というライブラリが標準で添付されている。これはヘッダをハッシュに、本文を配列に収めてくれるもので、凝ったメールを扱わなければ結構便利。

しかし複数ある、例えば Received ヘッダが一つのハッシュのうえで上書きされまくって最後の(Received の時系列で言うと最初の)ものしか残らないので、ちょっと不便。

そこですべてのヘッダ情報を配列を値に持つハッシュに収めることにした。

16c16,19
<         @header[attr] = $2
---
>           if ( !@header.has_key?( attr ) )
>               @header[attr] = Array.new()
>           end
>           @header[attr].push( $2 )
19c22,24
<         @header[attr] += "\n" + line
---
>           last = @header[attr].last
>           last += "\n" + line
>           @header[attr][@header[attr].size-1] = last

値を取り出すときは全部配列になっちゃってるから一手間増えるけど、まぁそれは仕方ないってことで。

※ これが PHP の場合は配列を扱う一手間がばかにならないから、もうちょっとなんか工夫しなきゃって気になるんだけど、Ruby なら楽だから。

UltraVNC いつの間にか 1.0

http://ultravnc.sourceforge.net/

RC 取れたの知らずに昨日も RC のものをセットアップしちゃったorz しかもリリースされたの一ヶ月以上も前だし。

今度は RAA が繋がらない

Ruby Application Archive

Bad Gateway

The proxy server received an invalid response from an upstream server.

と言わはる。3つほどのネットワークのどこからでもエラーになるので、ここで言う proxy は reverse proxy さんだと思うんだけど、どうだろう。

[16:45 追記] 繋がるようになったみたい。

Gentoo は wheel グループしか su できない

どうして一般ユーザから root に su できないのですか? (Gentoo FAQ)

Gnu su は wheel グループに制限する機能をサポートしないはずなのでこれは Gentoo 独自の su なのか?

パソコン授業できる先生は6割…公立校調査

from YOMIURI ON-LINE

そんなに居る?

つーか中高は忙しいし新しいことを習得しにくいって、なんか小学校教員ばかにしとらんかえ? まぁ中高の方が生徒の拘束時間が長いから、必然的に教員の拘束時間も長くなっちゃうんだけど。

Dolphin Pulse クライアントアンインストール

Switch したので Windows でしか使えない Pulse クライアントでは自分の本当のタイプ量は分からない。ということで Windows マシンからも Pulse をアンインストール。

最終順位 2357位

7ヶ月間で3万位くらいからここまでこれた。思ったより上位に入れたが、Pulse に失敗する時期がままあったりして、なんかもうどうでもよくなってしまった。1年半に渡って Orca と Dolphin をやってきて分かったのは、

自分はとりあえずやたらとキーボードを叩いているんだな

って程度のことだった。やり始めた時期が 2万[打鍵/日]くらいだったのに、最近は 3万[打鍵/日] も珍しくなかった。本人の感覚としては前よりそんなに頑張っているつもりはないんだけど、こうして日記を書いたりなんだりでどかどか上がっていったんだなあ。まさか自分がこんなに日記を書くようになるとも思わなかったが、書きやすい環境さえできれば案外やれるもんだと思った。あとで検索できるってのが手書きの日記と違い自分のメリットになるし、HTML 手書きでちまっと書いていた頃よりはるかに楽で内容に集中できるようになったのもでかい。

Firefox に鍵マーク偽装の脆弱性

SecuLog 経由

げへー。なんか 0.9 はあれこれ出てくるなぁ。まぁ今のうちにどんどん出してもらいましょう。

About

例によって個人のなんちゃらです

Recent Posts

Categories

Tool 日々 Web Biz Net Apple MS ことば News Unix howto Food PHP Movie Edu Community Book Security Text TV Perl Ruby Music Pdoc 生き方 RDoc ViewCVS CVS Rsync Disk Mail FreeBSD Cygwin PDF Photo Zebedee Debian OSX Comic Cron Sysadmin Font Analog iCal Sunbird DNS Linux Wiki Emacs Thunderbird Sitecopy Terminal Drawing tDiary AppleScript Life Money Omni PukiWiki Xen XREA Zsh Screen CASL Firefox Fink zsh haXe Ecmascript PATH_INFO SQLite PEAR Lighttpd FastCGI Subversion au prototype.js jsUnit Apache Trac Template Java Rhino Mochikit Feed Bloglines CSS del.icio.us SBS qwikWeb gettext Ajax JSDoc Rails HTML CHM EPWING NDTP EB IE CLI ck ThinkPad Toy WSH RFC readline rlwrap ImageMagick epeg Frenzy sysprep Ubuntu MeCab DTP ERD DBMS eclipse Eclipse Awk RD Diigo XAMPP RubyGems PHPDoc iCab DOM YAML Camino Geekmonkey w3m Scheme Gauche Lisp JSAN Google VMware DSL SLAX Safari Markdown Textile IRC Jabber Fastladder MacPorts LLSpirit CPAN Mozilla Twitter OpenFL Rswatch ITS NTP GUI Pragger Yapra XML Mobile Git Study JSON VirtualBox Samba Pear Growl Mercurial Rack Capistrano Rake Win RSS Mechanize Sitemaps Android JavaScript Python RTM OOo iPod Yahoo Unicode Github iTunes God SBM friendfeed Friendfeed HokuUn Sinatra TDD Test Project Evernote iPad Geohash Location Map Search Simplenote Image WebKit RSpec Phone CSV WiMAX USB Chrome RubyKaigi RubyKaigi2011 Space CoffeeScript Nokogiri Hpricot Rubygems jQuery Node GTD CI UX Design VCS Kanazawa.rb Kindle Amazon Agile Vagrant Chef Windows Composer Dotenv PaaS Itamae SaaS Docker Swagger Grape WebAPI Microservices OmniAuth HTTP 分析基盤 CDN Terraform IaaS HCL Webpack Vue.js BigQuery Middleman CMS AWS PNG Laravel Selenium OAuth OpenAPI GitHub UML GCP TypeScript SQL Hanami Document SVG AsciiDoc Pandoc DocBook Develop Jekyll macOS Node.js Vite Heroku Transformer AI Data Cloud Wasm