今回の内容について メドレー開発本部の 田中 です。 先日、Proxy 層を Elastic Beanstalk 上の Nginx で、App 層を EC2 インスタンスで構築する機会がありました。ここだけ見るととても普通に見えますが、後述する制約から苦労した点もあり、制約を乗り越えるための工夫も含めてお話できる限り共有させていただきます(先にお伝えしておくと、特殊な事情がなければ今回のようなケースでは ALB で対応する ECS サービスに Path Based Routing してやるのが良いと思います)。 技術要素として、Nginx(OpenResty)/ Route53 Private DNS / EC2 / Systems Manager パラメータストア あたりに触れたいと思います。(Beanstalk は Multicontainer Docker を使用し、それも慣れるまでちょっとクセあったなぁと思ったのですが分量が多くなりそうなのでまた別の機会に共有させて頂きます) まず前編として Proxy 層、主に Nginx を使用した Dynamic Path Based Routing についてお話して、 後編は App 層 について、EC2 と Systems Manager パラメータストアあたりについて共有させていただければと思います。 設計/構築する上での前提と方針 対象となる案件を進める上での要件・制限内容は諸事情あり、ざっとまとめるとこのような感じです。 環境は AWS を使用する サーバアプリケーション、クライアントアプリケーションはユーザ毎で、サーバアプリケーションは共用できない(ユーザが増える度にクライアント/サーバのセットが増えるイメージ) ただし、クライアントからの接続先となる Endpoint は同じだが、Host Based Routing は訳あって利用できない クライアント認証を使用する 上記から、以下の設計方針で進める事にしました。 Proxy 層でクライアント認証を行い、Path Based Routing で対象となるサーバにリクエストを proxy する。Path 部分にクライアント別の識別 ID を含め、その値を元に Private DNS で名前解決する 例) https://example.com/a-client/api => https://a-client.local/api App 層は個別 EC2 インスタンスとする 設計する上で悩んだ点 主に 2 点ありますが、まずは Proxy 層です。出来るだけ AWS のマネージド・サービスで済ませたかったので、クライアント認証と Path Based Routing が可能でやりたい事に合うかどうか調べましたが以下の理由で断念し、普通(?)に ELB + Nginx を利用することにしました。 ALB: クライアント認証に非対応。また SSL 終端となるので Nginx 側でクライアント認証が出来ない API GW: クライアント認証は対応しており Routing 部分もがんばればいけるかも?、と思ったが Proxy 先が動的に増えたリするので管理ふくめ難しそうであった 次に App 層の構成をどうするかでした。集積度を高めるためにコンテナ利用も検討したのですが、使用するアプリケーションの必要スペックや要件などからいまいちフィットせず、個別の EC2 インスタンスにすることにしました(今でももっと良い方法がないか悩んでたりします) 全体構成 出来上がった全体構成のイメージは以下となります。なお台数は実環境と異なり、今回の内容と関係ない部分などは省略しています。 次に、今回の本題となる Proxy 層の構成について触れたいと思います。 Proxy 層の構成 Proxy 層の方針等はまとめると以下の通りで、proxy 先の動的判定と名前解決する箇所がキモとなります。 App 層のインスタンスは、起動時に自身の内部 IP と Tag に設定したクライアント識別 ID を元に Route53 の PrivateDNS に登録する クライアント識別 ID が a-client の場合、a-client.local のように登録 Proxy 層の Nginx はクライアント認証を行い、リクエストパスから取り出したクライアント識別 ID を元に転送先 Endpoint を生成し、backend に proxy する App 層のインスタンスは動的に増えるため、リクエスト時に名前解決したい(インスタンスが増える度に自動で Nginx の conf を編集することも検討したが追加数が読めず、conf がふくれあがるのもなぁ、、、という思いがあり止めました) Nginx は backend が増えても起動しっぱなしで動的に名前解決して動作させたかったため、lua-nginx-module を導入し balancer_by_lua ディレクティブと lua-resty-dns モジュールを使用することとし、構築の手間の関係から OpenResty を導入することにしました。 lua-nginx-module を使用した conf ファイル conf ファイル全体としては以下となります(関係ない箇所は省いています)。ポイントと記載した部分についての説明は後述します。 http { upstream app { # ポイント 1. # Private DNS で設定した IP(CNAME に設定)を元に動的 Routing balancer_by_lua_block { local balancer = require "ngx.balancer" local host = ngx . ctx . upstream_server . cname local port = '8888' local ok , err = balancer . set_current_peer ( host , port ) if not ok then return ngx . exit ( 500 ) end } } server { listen 443 ssl; set $ proxy_upstream_host '' ; set $ proxy_upstream_domain '.local' ; location ^~ /api/ { rewrite_by_lua_block { -- path からクライアント識別 ID を取得し、Private DNS に設定したドメインを生成 -- https://example.com/<id>/api という形式のリクエストから、<id>.local というドメインを生成して -- ngx.var.proxy_upstream_host 変数に格納 local ngx_re = require "ngx.re" local res , err = ngx_re . split ( ngx . var . request_uri , "/" , nil , { pos = 0 }) local id = res[3] ngx.var. proxy_upstream_host = id..ngx.var.proxy_upstream_domain; -- resolver 設定 local resolver = require "resty.dns.resolver" local r, err = resolver:new{ nameservers = {{ "x.x.x.x" , 53}}, -- 使用する nameserver } if not r then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end -- ポイント 2. -- 生成したドメイン名(<id>.local)を元に名前解決し、取得した結果を ngx.ctx にセット -- (balancer_by_lua_block で使用する) local answers, err = r:query(ngx.var.proxy_upstream_host, { qtype = r.TYPE_CNAME }) if not answers then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end if answers.errcode then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end ngx.ctx.upstream_server = answers[1] } proxy_set_header Host $ host ; proxy_set_header X-Real-IP $ remote_addr ; proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for ; proxy_set_header X-Forwarded-Proto $ scheme ; -- https://<id>.local/api に proxy rewrite ^/api/(.+)$ /api/ break; proxy_pass https://app; } } } ポイント 1. 動的 Routing balancer.set_current_peer にて proxy 先を動的に設定します。 host 部分にはドメインを直接指定することができないため、ポイント 2. で ngx.ctx にセットした DNS の値から IP(Route53 に CNAME レコードとして設定している)を指定しています。 balancer_by_lua_block { local balancer = require "ngx.balancer" -- ngx.ctx にセットしていた、Private DNS から取得した内部 IP をセット local host = ngx . ctx . upstream_server . cname local port = '8888' -- proxy 先セット。host にドメインは直接指定できない local ok , err = balancer . set_current_peer ( host , port ) if not ok then return ngx . exit ( 500 ) end } 詳細については OpenResty の ドキュメント を参照してください ポイント 2. 動的名前解決 r:query にて、生成したドメイン名( <id>.local )を問い合わせます。 r 部分は resolver:new で nameserver を指定した resolver となります。 なお、nameserver に指定する IP は今回は Route53 の Private DNS を指定するため、外部 nameserver ではなくローカルの nameserver(10.0.0.2 など)を指定することになります。 問い合わせ結果の answers 部分は Lua table 形式の配列となります。今回の例でいうと対象は 1 件となるので、その値を balancer_by_lua_block で使用するために ngx.ctx にセットしています。 local answers , err = r : query ( ngx . var . proxy_upstream_host , { qtype = r . TYPE_CNAME }) if not answers then ngx . exit ( ngx . HTTP_INTERNAL_SERVER_ERROR ) end if answers . errcode then ngx . exit ( ngx . HTTP_INTERNAL_SERVER_ERROR ) end ngx . ctx . upstream_server = answers [ 1 ] 詳細については OpenResty の ドキュメント を参照してください 今回のまとめ upstream 先を動的に判定して proxy するという要件はそうそう無いかもしれませんし、途中までは複雑な構成になりそうだなぁとドキドキしてしましたが、結果としてはそれなりにシンプルになったかなと思います。今更ながら Nginx(と lua module)は柔軟で良く出来てるなぁという感想でした。 後編は App 層について、EC2 と Systems Manager パラメータストアあたりについて共有させていただければと思います。 https://developer.medley.jp/entry/2017/08/24/120000_02 参考リンク 構築にあたり、下記記事を参考にさせていただきました。ありがとうございます。 https://qiita.com/toritori0318/items/a9305d528b52936c0573 お知らせ メドレーでは、医師たちがつくるオンライン医療事典「 MEDLEY 」、オンライン診療アプリ「 CLINICS 」、医療介護の求人サイト「 ジョブメドレー 」、口コミで探せる介護施設の検索サイト「 介護のほんね 」などのプロダクトを提供しています。これらのサービスの拡大を受けて、その成長を支えるエンジニア・デザイナーを募集しています。 メドレーで一緒に医療体験を変えるプロダクト作りに関わりたい方のご連絡お待ちしております。 https://www.medley.jp/recruit/creative.html
今回の内容について メドレー開発本部の 田中 です。 先日、Proxy 層を Elastic Beanstalk 上の Nginx で、App 層を EC2 インスタンスで構築する機会がありました。ここだけ見るととても普通に見えますが、後述する制約から苦労した点もあり、制約を乗り越えるための工夫も含めてお話できる限り共有させていただきます(先にお伝えしておくと、特殊な事情がなければ今回のようなケースでは ALB で対応する ECS サービスに Path Based Routing してやるのが良いと思います)。 技術要素として、Nginx(OpenResty)/ Route53 Private DNS / EC2 / Systems Manager パラメータストア あたりに触れたいと思います。(Beanstalk は Multicontainer Docker を使用し、それも慣れるまでちょっとクセあったなぁと思ったのですが分量が多くなりそうなのでまた別の機会に共有させて頂きます) まず前編として Proxy 層、主に Nginx を使用した Dynamic Path Based Routing についてお話して、 後編は App 層 について、EC2 と Systems Manager パラメータストアあたりについて共有させていただければと思います。 設計/構築する上での前提と方針 対象となる案件を進める上での要件・制限内容は諸事情あり、ざっとまとめるとこのような感じです。 環境は AWS を使用する サーバアプリケーション、クライアントアプリケーションはユーザ毎で、サーバアプリケーションは共用できない(ユーザが増える度にクライアント/サーバのセットが増えるイメージ) ただし、クライアントからの接続先となる Endpoint は同じだが、Host Based Routing は訳あって利用できない クライアント認証を使用する 上記から、以下の設計方針で進める事にしました。 Proxy 層でクライアント認証を行い、Path Based Routing で対象となるサーバにリクエストを proxy する。Path 部分にクライアント別の識別 ID を含め、その値を元に Private DNS で名前解決する 例) https://example.com/a-client/api => https://a-client.local/api App 層は個別 EC2 インスタンスとする 設計する上で悩んだ点 主に 2 点ありますが、まずは Proxy 層です。出来るだけ AWS のマネージド・サービスで済ませたかったので、クライアント認証と Path Based Routing が可能でやりたい事に合うかどうか調べましたが以下の理由で断念し、普通(?)に ELB + Nginx を利用することにしました。 ALB: クライアント認証に非対応。また SSL 終端となるので Nginx 側でクライアント認証が出来ない API GW: クライアント認証は対応しており Routing 部分もがんばればいけるかも?、と思ったが Proxy 先が動的に増えたリするので管理ふくめ難しそうであった 次に App 層の構成をどうするかでした。集積度を高めるためにコンテナ利用も検討したのですが、使用するアプリケーションの必要スペックや要件などからいまいちフィットせず、個別の EC2 インスタンスにすることにしました(今でももっと良い方法がないか悩んでたりします) 全体構成 出来上がった全体構成のイメージは以下となります。なお台数は実環境と異なり、今回の内容と関係ない部分などは省略しています。 次に、今回の本題となる Proxy 層の構成について触れたいと思います。 Proxy 層の構成 Proxy 層の方針等はまとめると以下の通りで、proxy 先の動的判定と名前解決する箇所がキモとなります。 App 層のインスタンスは、起動時に自身の内部 IP と Tag に設定したクライアント識別 ID を元に Route53 の PrivateDNS に登録する クライアント識別 ID が a-client の場合、a-client.local のように登録 Proxy 層の Nginx はクライアント認証を行い、リクエストパスから取り出したクライアント識別 ID を元に転送先 Endpoint を生成し、backend に proxy する App 層のインスタンスは動的に増えるため、リクエスト時に名前解決したい(インスタンスが増える度に自動で Nginx の conf を編集することも検討したが追加数が読めず、conf がふくれあがるのもなぁ、、、という思いがあり止めました) Nginx は backend が増えても起動しっぱなしで動的に名前解決して動作させたかったため、lua-nginx-module を導入し balancer_by_lua ディレクティブと lua-resty-dns モジュールを使用することとし、構築の手間の関係から OpenResty を導入することにしました。 lua-nginx-module を使用した conf ファイル conf ファイル全体としては以下となります(関係ない箇所は省いています)。ポイントと記載した部分についての説明は後述します。 http { upstream app { # ポイント 1. # Private DNS で設定した IP(CNAME に設定)を元に動的 Routing balancer_by_lua_block { local balancer = require "ngx.balancer" local host = ngx . ctx . upstream_server . cname local port = '8888' local ok , err = balancer . set_current_peer ( host , port ) if not ok then return ngx . exit ( 500 ) end } } server { listen 443 ssl; set $ proxy_upstream_host '' ; set $ proxy_upstream_domain '.local' ; location ^~ /api/ { rewrite_by_lua_block { -- path からクライアント識別 ID を取得し、Private DNS に設定したドメインを生成 -- https://example.com/<id>/api という形式のリクエストから、<id>.local というドメインを生成して -- ngx.var.proxy_upstream_host 変数に格納 local ngx_re = require "ngx.re" local res , err = ngx_re . split ( ngx . var . request_uri , "/" , nil , { pos = 0 }) local id = res[3] ngx.var. proxy_upstream_host = id..ngx.var.proxy_upstream_domain; -- resolver 設定 local resolver = require "resty.dns.resolver" local r, err = resolver:new{ nameservers = {{ "x.x.x.x" , 53}}, -- 使用する nameserver } if not r then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end -- ポイント 2. -- 生成したドメイン名(<id>.local)を元に名前解決し、取得した結果を ngx.ctx にセット -- (balancer_by_lua_block で使用する) local answers, err = r:query(ngx.var.proxy_upstream_host, { qtype = r.TYPE_CNAME }) if not answers then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end if answers.errcode then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end ngx.ctx.upstream_server = answers[1] } proxy_set_header Host $ host ; proxy_set_header X-Real-IP $ remote_addr ; proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for ; proxy_set_header X-Forwarded-Proto $ scheme ; -- https://<id>.local/api に proxy rewrite ^/api/(.+)$ /api/ break; proxy_pass https://app; } } } ポイント 1. 動的 Routing balancer.set_current_peer にて proxy 先を動的に設定します。 host 部分にはドメインを直接指定することができないため、ポイント 2. で ngx.ctx にセットした DNS の値から IP(Route53 に CNAME レコードとして設定している)を指定しています。 balancer_by_lua_block { local balancer = require "ngx.balancer" -- ngx.ctx にセットしていた、Private DNS から取得した内部 IP をセット local host = ngx . ctx . upstream_server . cname local port = '8888' -- proxy 先セット。host にドメインは直接指定できない local ok , err = balancer . set_current_peer ( host , port ) if not ok then return ngx . exit ( 500 ) end } 詳細については OpenResty の ドキュメント を参照してください ポイント 2. 動的名前解決 r:query にて、生成したドメイン名( <id>.local )を問い合わせます。 r 部分は resolver:new で nameserver を指定した resolver となります。 なお、nameserver に指定する IP は今回は Route53 の Private DNS を指定するため、外部 nameserver ではなくローカルの nameserver(10.0.0.2 など)を指定することになります。 問い合わせ結果の answers 部分は Lua table 形式の配列となります。今回の例でいうと対象は 1 件となるので、その値を balancer_by_lua_block で使用するために ngx.ctx にセットしています。 local answers , err = r : query ( ngx . var . proxy_upstream_host , { qtype = r . TYPE_CNAME }) if not answers then ngx . exit ( ngx . HTTP_INTERNAL_SERVER_ERROR ) end if answers . errcode then ngx . exit ( ngx . HTTP_INTERNAL_SERVER_ERROR ) end ngx . ctx . upstream_server = answers [ 1 ] 詳細については OpenResty の ドキュメント を参照してください 今回のまとめ upstream 先を動的に判定して proxy するという要件はそうそう無いかもしれませんし、途中までは複雑な構成になりそうだなぁとドキドキしてしましたが、結果としてはそれなりにシンプルになったかなと思います。今更ながら Nginx(と lua module)は柔軟で良く出来てるなぁという感想でした。 後編は App 層について、EC2 と Systems Manager パラメータストアあたりについて共有させていただければと思います。 クライアント認証と Path Based Routing が必要なサーバを AWS で構築(後編:App 層) | MEDLEY Developer Portal 今回の内容について メドレー開発本部の田中です。 先日、Proxy 層を Elastic Beanstalk 上の Nginx で、App 層を EC2 インスタンスで構築する機会がありました。ここだけ見るととても普通に見えますが、制約があ... developer.medley.jp 参考リンク 構築にあたり、下記記事を参考にさせていただきました。ありがとうございます。 Nginx balancer_by_luaの話とupstream名前解決の話 - Qiita balancer_by_lua_xxxxxいつの間にやら[^1] lua-nginx-module に balancer_by_lua_xxx という新しいディレクティブが増えていました。以下ド… qiita.com お知らせ メドレーでは、医師たちがつくるオンライン医療事典「 MEDLEY 」、オンライン診療アプリ「 CLINICS 」、医療介護の求人サイト「 ジョブメドレー 」、口コミで探せる介護施設の検索サイト「 介護のほんね 」などのプロダクトを提供しています。これらのサービスの拡大を受けて、その成長を支えるエンジニア・デザイナーを募集しています。 メドレーで一緒に医療体験を変えるプロダクト作りに関わりたい方のご連絡お待ちしております。 メンバーのストーリー | 株式会社メドレー メンバーのストーリー 家族や友人が病気になった時に救いの手を差しのべる医療の力。... www.medley.jp
今回の内容について メドレー開発本部の 田中 です。 先日、Proxy 層を Elastic Beanstalk 上の Nginx で、App 層を EC2 インスタンスで構築する機会がありました。ここだけ見るととても普通に見えますが、後述する制約から苦労した点もあり、制約を乗り越えるための工夫も含めてお話できる限り共有させていただきます(先にお伝えしておくと、特殊な事情がなければ今回のようなケースでは ALB で対応する ECS サービスに Path Based Routing してやるのが良いと思います)。 技術要素として、Nginx(OpenResty)/ Route53 Private DNS / EC2 / Systems Manager パラメータストア あたりに触れたいと思います。(Beanstalk は Multicontainer Docker を使用し、それも慣れるまでちょっとクセあったなぁと思ったのですが分量が多くなりそうなのでまた別の機会に共有させて頂きます) まず前編として Proxy 層、主に Nginx を使用した Dynamic Path Based Routing についてお話して、 後編は App 層 について、EC2 と Systems Manager パラメータストアあたりについて共有させていただければと思います。 設計/構築する上での前提と方針 対象となる案件を進める上での要件・制限内容は諸事情あり、ざっとまとめるとこのような感じです。 環境は AWS を使用する サーバアプリケーション、クライアントアプリケーションはユーザ毎で、サーバアプリケーションは共用できない(ユーザが増える度にクライアント/サーバのセットが増えるイメージ) ただし、クライアントからの接続先となる Endpoint は同じだが、Host Based Routing は訳あって利用できない クライアント認証を使用する 上記から、以下の設計方針で進める事にしました。 Proxy 層でクライアント認証を行い、Path Based Routing で対象となるサーバにリクエストを proxy する。Path 部分にクライアント別の識別 ID を含め、その値を元に Private DNS で名前解決する 例) https://example.com/a-client/api => https://a-client.local/api App 層は個別 EC2 インスタンスとする 設計する上で悩んだ点 主に 2 点ありますが、まずは Proxy 層です。出来るだけ AWS のマネージド・サービスで済ませたかったので、クライアント認証と Path Based Routing が可能でやりたい事に合うかどうか調べましたが以下の理由で断念し、普通(?)に ELB + Nginx を利用することにしました。 ALB: クライアント認証に非対応。また SSL 終端となるので Nginx 側でクライアント認証が出来ない API GW: クライアント認証は対応しており Routing 部分もがんばればいけるかも?、と思ったが Proxy 先が動的に増えたリするので管理ふくめ難しそうであった 次に App 層の構成をどうするかでした。集積度を高めるためにコンテナ利用も検討したのですが、使用するアプリケーションの必要スペックや要件などからいまいちフィットせず、個別の EC2 インスタンスにすることにしました(今でももっと良い方法がないか悩んでたりします) 全体構成 出来上がった全体構成のイメージは以下となります。なお台数は実環境と異なり、今回の内容と関係ない部分などは省略しています。 次に、今回の本題となる Proxy 層の構成について触れたいと思います。 Proxy 層の構成 Proxy 層の方針等はまとめると以下の通りで、proxy 先の動的判定と名前解決する箇所がキモとなります。 App 層のインスタンスは、起動時に自身の内部 IP と Tag に設定したクライアント識別 ID を元に Route53 の PrivateDNS に登録する クライアント識別 ID が a-client の場合、a-client.local のように登録 Proxy 層の Nginx はクライアント認証を行い、リクエストパスから取り出したクライアント識別 ID を元に転送先 Endpoint を生成し、backend に proxy する App 層のインスタンスは動的に増えるため、リクエスト時に名前解決したい(インスタンスが増える度に自動で Nginx の conf を編集することも検討したが追加数が読めず、conf がふくれあがるのもなぁ、、、という思いがあり止めました) Nginx は backend が増えても起動しっぱなしで動的に名前解決して動作させたかったため、lua-nginx-module を導入し balancer_by_lua ディレクティブと lua-resty-dns モジュールを使用することとし、構築の手間の関係から OpenResty を導入することにしました。 lua-nginx-module を使用した conf ファイル conf ファイル全体としては以下となります(関係ない箇所は省いています)。ポイントと記載した部分についての説明は後述します。 http { upstream app { # ポイント 1. # Private DNS で設定した IP(CNAME に設定)を元に動的 Routing balancer_by_lua_block { local balancer = require "ngx.balancer" local host = ngx . ctx . upstream_server . cname local port = '8888' local ok , err = balancer . set_current_peer ( host , port ) if not ok then return ngx . exit ( 500 ) end } } server { listen 443 ssl; set $ proxy_upstream_host '' ; set $ proxy_upstream_domain '.local' ; location ^~ /api/ { rewrite_by_lua_block { -- path からクライアント識別 ID を取得し、Private DNS に設定したドメインを生成 -- https://example.com/<id>/api という形式のリクエストから、<id>.local というドメインを生成して -- ngx.var.proxy_upstream_host 変数に格納 local ngx_re = require "ngx.re" local res , err = ngx_re . split ( ngx . var . request_uri , "/" , nil , { pos = 0 }) local id = res[3] ngx.var. proxy_upstream_host = id..ngx.var.proxy_upstream_domain; -- resolver 設定 local resolver = require "resty.dns.resolver" local r, err = resolver:new{ nameservers = {{ "x.x.x.x" , 53}}, -- 使用する nameserver } if not r then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end -- ポイント 2. -- 生成したドメイン名(<id>.local)を元に名前解決し、取得した結果を ngx.ctx にセット -- (balancer_by_lua_block で使用する) local answers, err = r:query(ngx.var.proxy_upstream_host, { qtype = r.TYPE_CNAME }) if not answers then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end if answers.errcode then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end ngx.ctx.upstream_server = answers[1] } proxy_set_header Host $ host ; proxy_set_header X-Real-IP $ remote_addr ; proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for ; proxy_set_header X-Forwarded-Proto $ scheme ; -- https://<id>.local/api に proxy rewrite ^/api/(.+)$ /api/ break; proxy_pass https://app; } } } ポイント 1. 動的 Routing balancer.set_current_peer にて proxy 先を動的に設定します。 host 部分にはドメインを直接指定することができないため、ポイント 2. で ngx.ctx にセットした DNS の値から IP(Route53 に CNAME レコードとして設定している)を指定しています。 balancer_by_lua_block { local balancer = require "ngx.balancer" -- ngx.ctx にセットしていた、Private DNS から取得した内部 IP をセット local host = ngx . ctx . upstream_server . cname local port = '8888' -- proxy 先セット。host にドメインは直接指定できない local ok , err = balancer . set_current_peer ( host , port ) if not ok then return ngx . exit ( 500 ) end } 詳細については OpenResty の ドキュメント を参照してください ポイント 2. 動的名前解決 r:query にて、生成したドメイン名( <id>.local )を問い合わせます。 r 部分は resolver:new で nameserver を指定した resolver となります。 なお、nameserver に指定する IP は今回は Route53 の Private DNS を指定するため、外部 nameserver ではなくローカルの nameserver(10.0.0.2 など)を指定することになります。 問い合わせ結果の answers 部分は Lua table 形式の配列となります。今回の例でいうと対象は 1 件となるので、その値を balancer_by_lua_block で使用するために ngx.ctx にセットしています。 local answers , err = r : query ( ngx . var . proxy_upstream_host , { qtype = r . TYPE_CNAME }) if not answers then ngx . exit ( ngx . HTTP_INTERNAL_SERVER_ERROR ) end if answers . errcode then ngx . exit ( ngx . HTTP_INTERNAL_SERVER_ERROR ) end ngx . ctx . upstream_server = answers [ 1 ] 詳細については OpenResty の ドキュメント を参照してください 今回のまとめ upstream 先を動的に判定して proxy するという要件はそうそう無いかもしれませんし、途中までは複雑な構成になりそうだなぁとドキドキしてしましたが、結果としてはそれなりにシンプルになったかなと思います。今更ながら Nginx(と lua module)は柔軟で良く出来てるなぁという感想でした。 後編は App 層について、EC2 と Systems Manager パラメータストアあたりについて共有させていただければと思います。 クライアント認証と Path Based Routing が必要なサーバを AWS で構築(後編:App 層) | MEDLEY Developer Portal 今回の内容について メドレー開発本部の田中です。 先日、Proxy 層を Elastic Beanstalk 上の Nginx で、App 層を EC2 インスタンスで構築する機会がありました。ここだけ見るととても普通に見えますが、制約があ... developer.medley.jp 参考リンク 構築にあたり、下記記事を参考にさせていただきました。ありがとうございます。 Nginx balancer_by_luaの話とupstream名前解決の話 - Qiita balancer_by_lua_xxxxxいつの間にやら[^1] lua-nginx-module に balancer_by_lua_xxx という新しいディレクティブが増えていました。以下ド… qiita.com お知らせ メドレーでは、医師たちがつくるオンライン医療事典「 MEDLEY 」、オンライン診療アプリ「 CLINICS 」、医療介護の求人サイト「 ジョブメドレー 」、口コミで探せる介護施設の検索サイト「 介護のほんね 」などのプロダクトを提供しています。これらのサービスの拡大を受けて、その成長を支えるエンジニア・デザイナーを募集しています。 メドレーで一緒に医療体験を変えるプロダクト作りに関わりたい方のご連絡お待ちしております。 メンバーのストーリー | 株式会社メドレー メンバーのストーリー 家族や友人が病気になった時に救いの手を差しのべる医療の力。... www.medley.jp
今回の内容について メドレー開発本部の 田中 です。 先日、Proxy 層を Elastic Beanstalk 上の Nginx で、App 層を EC2 インスタンスで構築する機会がありました。ここだけ見るととても普通に見えますが、後述する制約から苦労した点もあり、制約を乗り越えるための工夫も含めてお話できる限り共有させていただきます(先にお伝えしておくと、特殊な事情がなければ今回のようなケースでは ALB で対応する ECS サービスに Path Based Routing してやるのが良いと思います)。 技術要素として、Nginx(OpenResty)/ Route53 Private DNS / EC2 / Systems Manager パラメータストア あたりに触れたいと思います。(Beanstalk は Multicontainer Docker を使用し、それも慣れるまでちょっとクセあったなぁと思ったのですが分量が多くなりそうなのでまた別の機会に共有させて頂きます) まず前編として Proxy 層、主に Nginx を使用した Dynamic Path Based Routing についてお話して、 後編は App 層 について、EC2 と Systems Manager パラメータストアあたりについて共有させていただければと思います。 設計/構築する上での前提と方針 対象となる案件を進める上での要件・制限内容は諸事情あり、ざっとまとめるとこのような感じです。 環境は AWS を使用する サーバアプリケーション、クライアントアプリケーションはユーザ毎で、サーバアプリケーションは共用できない(ユーザが増える度にクライアント/サーバのセットが増えるイメージ) ただし、クライアントからの接続先となる Endpoint は同じだが、Host Based Routing は訳あって利用できない クライアント認証を使用する 上記から、以下の設計方針で進める事にしました。 Proxy 層でクライアント認証を行い、Path Based Routing で対象となるサーバにリクエストを proxy する。Path 部分にクライアント別の識別 ID を含め、その値を元に Private DNS で名前解決する 例) https://example.com/a-client/api => https://a-client.local/api App 層は個別 EC2 インスタンスとする 設計する上で悩んだ点 主に 2 点ありますが、まずは Proxy 層です。出来るだけ AWS のマネージド・サービスで済ませたかったので、クライアント認証と Path Based Routing が可能でやりたい事に合うかどうか調べましたが以下の理由で断念し、普通(?)に ELB + Nginx を利用することにしました。 ALB: クライアント認証に非対応。また SSL 終端となるので Nginx 側でクライアント認証が出来ない API GW: クライアント認証は対応しており Routing 部分もがんばればいけるかも?、と思ったが Proxy 先が動的に増えたリするので管理ふくめ難しそうであった 次に App 層の構成をどうするかでした。集積度を高めるためにコンテナ利用も検討したのですが、使用するアプリケーションの必要スペックや要件などからいまいちフィットせず、個別の EC2 インスタンスにすることにしました(今でももっと良い方法がないか悩んでたりします) 全体構成 出来上がった全体構成のイメージは以下となります。なお台数は実環境と異なり、今回の内容と関係ない部分などは省略しています。 次に、今回の本題となる Proxy 層の構成について触れたいと思います。 Proxy 層の構成 Proxy 層の方針等はまとめると以下の通りで、proxy 先の動的判定と名前解決する箇所がキモとなります。 App 層のインスタンスは、起動時に自身の内部 IP と Tag に設定したクライアント識別 ID を元に Route53 の PrivateDNS に登録する クライアント識別 ID が a-client の場合、a-client.local のように登録 Proxy 層の Nginx はクライアント認証を行い、リクエストパスから取り出したクライアント識別 ID を元に転送先 Endpoint を生成し、backend に proxy する App 層のインスタンスは動的に増えるため、リクエスト時に名前解決したい(インスタンスが増える度に自動で Nginx の conf を編集することも検討したが追加数が読めず、conf がふくれあがるのもなぁ、、、という思いがあり止めました) Nginx は backend が増えても起動しっぱなしで動的に名前解決して動作させたかったため、lua-nginx-module を導入し balancer_by_lua ディレクティブと lua-resty-dns モジュールを使用することとし、構築の手間の関係から OpenResty を導入することにしました。 lua-nginx-module を使用した conf ファイル conf ファイル全体としては以下となります(関係ない箇所は省いています)。ポイントと記載した部分についての説明は後述します。 http { upstream app { # ポイント 1. # Private DNS で設定した IP(CNAME に設定)を元に動的 Routing balancer_by_lua_block { local balancer = require "ngx.balancer" local host = ngx . ctx . upstream_server . cname local port = '8888' local ok , err = balancer . set_current_peer ( host , port ) if not ok then return ngx . exit ( 500 ) end } } server { listen 443 ssl; set $ proxy_upstream_host '' ; set $ proxy_upstream_domain '.local' ; location ^~ /api/ { rewrite_by_lua_block { -- path からクライアント識別 ID を取得し、Private DNS に設定したドメインを生成 -- https://example.com/<id>/api という形式のリクエストから、<id>.local というドメインを生成して -- ngx.var.proxy_upstream_host 変数に格納 local ngx_re = require "ngx.re" local res , err = ngx_re . split ( ngx . var . request_uri , "/" , nil , { pos = 0 }) local id = res[3] ngx.var. proxy_upstream_host = id..ngx.var.proxy_upstream_domain; -- resolver 設定 local resolver = require "resty.dns.resolver" local r, err = resolver:new{ nameservers = {{ "x.x.x.x" , 53}}, -- 使用する nameserver } if not r then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end -- ポイント 2. -- 生成したドメイン名(<id>.local)を元に名前解決し、取得した結果を ngx.ctx にセット -- (balancer_by_lua_block で使用する) local answers, err = r:query(ngx.var.proxy_upstream_host, { qtype = r.TYPE_CNAME }) if not answers then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end if answers.errcode then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end ngx.ctx.upstream_server = answers[1] } proxy_set_header Host $ host ; proxy_set_header X-Real-IP $ remote_addr ; proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for ; proxy_set_header X-Forwarded-Proto $ scheme ; -- https://<id>.local/api に proxy rewrite ^/api/(.+)$ /api/ break; proxy_pass https://app; } } } ポイント 1. 動的 Routing balancer.set_current_peer にて proxy 先を動的に設定します。 host 部分にはドメインを直接指定することができないため、ポイント 2. で ngx.ctx にセットした DNS の値から IP(Route53 に CNAME レコードとして設定している)を指定しています。 balancer_by_lua_block { local balancer = require "ngx.balancer" -- ngx.ctx にセットしていた、Private DNS から取得した内部 IP をセット local host = ngx . ctx . upstream_server . cname local port = '8888' -- proxy 先セット。host にドメインは直接指定できない local ok , err = balancer . set_current_peer ( host , port ) if not ok then return ngx . exit ( 500 ) end } 詳細については OpenResty の ドキュメント を参照してください ポイント 2. 動的名前解決 r:query にて、生成したドメイン名( <id>.local )を問い合わせます。 r 部分は resolver:new で nameserver を指定した resolver となります。 なお、nameserver に指定する IP は今回は Route53 の Private DNS を指定するため、外部 nameserver ではなくローカルの nameserver(10.0.0.2 など)を指定することになります。 問い合わせ結果の answers 部分は Lua table 形式の配列となります。今回の例でいうと対象は 1 件となるので、その値を balancer_by_lua_block で使用するために ngx.ctx にセットしています。 local answers , err = r : query ( ngx . var . proxy_upstream_host , { qtype = r . TYPE_CNAME }) if not answers then ngx . exit ( ngx . HTTP_INTERNAL_SERVER_ERROR ) end if answers . errcode then ngx . exit ( ngx . HTTP_INTERNAL_SERVER_ERROR ) end ngx . ctx . upstream_server = answers [ 1 ] 詳細については OpenResty の ドキュメント を参照してください 今回のまとめ upstream 先を動的に判定して proxy するという要件はそうそう無いかもしれませんし、途中までは複雑な構成になりそうだなぁとドキドキしてしましたが、結果としてはそれなりにシンプルになったかなと思います。今更ながら Nginx(と lua module)は柔軟で良く出来てるなぁという感想でした。 後編は App 層について、EC2 と Systems Manager パラメータストアあたりについて共有させていただければと思います。 クライアント認証と Path Based Routing が必要なサーバを AWS で構築(後編:App 層) | MEDLEY Developer Portal 今回の内容について メドレー開発本部の田中です。 先日、Proxy 層を Elastic Beanstalk 上の Nginx で、App 層を EC2 インスタンスで構築する機会がありました。ここだけ見るととても普通に見えますが、制約があ... developer.medley.jp 参考リンク 構築にあたり、下記記事を参考にさせていただきました。ありがとうございます。 Nginx balancer_by_luaの話とupstream名前解決の話 - Qiita balancer_by_lua_xxxxx いつの間にやら1 lua-nginx-module に balancer_by_lua_xxx という新しいディレクティブが増えていました。 以下ドキュメントより抜粋。 http { upstream backend {... qiita.com お知らせ メドレーでは、医師たちがつくるオンライン医療事典「 MEDLEY 」、オンライン診療アプリ「 CLINICS 」、医療介護の求人サイト「 ジョブメドレー 」、口コミで探せる介護施設の検索サイト「 介護のほんね 」などのプロダクトを提供しています。これらのサービスの拡大を受けて、その成長を支えるエンジニア・デザイナーを募集しています。 メドレーで一緒に医療体験を変えるプロダクト作りに関わりたい方のご連絡お待ちしております。 メンバーのストーリー | 株式会社メドレー メンバーのストーリー 家族や友人が病気になった時に救いの手を差しのべる医療の力。... www.medley.jp
今回の内容について メドレー開発本部の 田中 です。 先日、Proxy 層を Elastic Beanstalk 上の Nginx で、App 層を EC2 インスタンスで構築する機会がありました。ここだけ見るととても普通に見えますが、後述する制約から苦労した点もあり、制約を乗り越えるための工夫も含めてお話できる限り共有させていただきます(先にお伝えしておくと、特殊な事情がなければ今回のようなケースでは ALB で対応する ECS サービスに Path Based Routing してやるのが良いと思います)。 技術要素として、Nginx(OpenResty)/ Route53 Private DNS / EC2 / Systems Manager パラメータストア あたりに触れたいと思います。(Beanstalk は Multicontainer Docker を使用し、それも慣れるまでちょっとクセあったなぁと思ったのですが分量が多くなりそうなのでまた別の機会に共有させて頂きます) まず前編として Proxy 層、主に Nginx を使用した Dynamic Path Based Routing についてお話して、 後編は App 層 について、EC2 と Systems Manager パラメータストアあたりについて共有させていただければと思います。 設計/構築する上での前提と方針 対象となる案件を進める上での要件・制限内容は諸事情あり、ざっとまとめるとこのような感じです。 環境は AWS を使用する サーバアプリケーション、クライアントアプリケーションはユーザ毎で、サーバアプリケーションは共用できない(ユーザが増える度にクライアント/サーバのセットが増えるイメージ) ただし、クライアントからの接続先となる Endpoint は同じだが、Host Based Routing は訳あって利用できない クライアント認証を使用する 上記から、以下の設計方針で進める事にしました。 Proxy 層でクライアント認証を行い、Path Based Routing で対象となるサーバにリクエストを proxy する。Path 部分にクライアント別の識別 ID を含め、その値を元に Private DNS で名前解決する 例) https://example.com/a-client/api => https://a-client.local/api App 層は個別 EC2 インスタンスとする 設計する上で悩んだ点 主に 2 点ありますが、まずは Proxy 層です。出来るだけ AWS のマネージド・サービスで済ませたかったので、クライアント認証と Path Based Routing が可能でやりたい事に合うかどうか調べましたが以下の理由で断念し、普通(?)に ELB + Nginx を利用することにしました。 ALB: クライアント認証に非対応。また SSL 終端となるので Nginx 側でクライアント認証が出来ない API GW: クライアント認証は対応しており Routing 部分もがんばればいけるかも?、と思ったが Proxy 先が動的に増えたリするので管理ふくめ難しそうであった 次に App 層の構成をどうするかでした。集積度を高めるためにコンテナ利用も検討したのですが、使用するアプリケーションの必要スペックや要件などからいまいちフィットせず、個別の EC2 インスタンスにすることにしました(今でももっと良い方法がないか悩んでたりします) 全体構成 出来上がった全体構成のイメージは以下となります。なお台数は実環境と異なり、今回の内容と関係ない部分などは省略しています。 次に、今回の本題となる Proxy 層の構成について触れたいと思います。 Proxy 層の構成 Proxy 層の方針等はまとめると以下の通りで、proxy 先の動的判定と名前解決する箇所がキモとなります。 App 層のインスタンスは、起動時に自身の内部 IP と Tag に設定したクライアント識別 ID を元に Route53 の PrivateDNS に登録する クライアント識別 ID が a-client の場合、a-client.local のように登録 Proxy 層の Nginx はクライアント認証を行い、リクエストパスから取り出したクライアント識別 ID を元に転送先 Endpoint を生成し、backend に proxy する App 層のインスタンスは動的に増えるため、リクエスト時に名前解決したい(インスタンスが増える度に自動で Nginx の conf を編集することも検討したが追加数が読めず、conf がふくれあがるのもなぁ、、、という思いがあり止めました) Nginx は backend が増えても起動しっぱなしで動的に名前解決して動作させたかったため、lua-nginx-module を導入し balancer_by_lua ディレクティブと lua-resty-dns モジュールを使用することとし、構築の手間の関係から OpenResty を導入することにしました。 lua-nginx-module を使用した conf ファイル conf ファイル全体としては以下となります(関係ない箇所は省いています)。ポイントと記載した部分についての説明は後述します。 http { upstream app { # ポイント 1. # Private DNS で設定した IP(CNAME に設定)を元に動的 Routing balancer_by_lua_block { local balancer = require "ngx.balancer" local host = ngx . ctx . upstream_server . cname local port = '8888' local ok , err = balancer . set_current_peer ( host , port ) if not ok then return ngx . exit ( 500 ) end } } server { listen 443 ssl; set $ proxy_upstream_host '' ; set $ proxy_upstream_domain '.local' ; location ^~ /api/ { rewrite_by_lua_block { -- path からクライアント識別 ID を取得し、Private DNS に設定したドメインを生成 -- https://example.com/<id>/api という形式のリクエストから、<id>.local というドメインを生成して -- ngx.var.proxy_upstream_host 変数に格納 local ngx_re = require "ngx.re" local res , err = ngx_re . split ( ngx . var . request_uri , "/" , nil , { pos = 0 }) local id = res[3] ngx.var. proxy_upstream_host = id..ngx.var.proxy_upstream_domain; -- resolver 設定 local resolver = require "resty.dns.resolver" local r, err = resolver:new{ nameservers = {{ "x.x.x.x" , 53}}, -- 使用する nameserver } if not r then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end -- ポイント 2. -- 生成したドメイン名(<id>.local)を元に名前解決し、取得した結果を ngx.ctx にセット -- (balancer_by_lua_block で使用する) local answers, err = r:query(ngx.var.proxy_upstream_host, { qtype = r.TYPE_CNAME }) if not answers then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end if answers.errcode then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end ngx.ctx.upstream_server = answers[1] } proxy_set_header Host $ host ; proxy_set_header X-Real-IP $ remote_addr ; proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for ; proxy_set_header X-Forwarded-Proto $ scheme ; -- https://<id>.local/api に proxy rewrite ^/api/(.+)$ /api/ break; proxy_pass https://app; } } } ポイント 1. 動的 Routing balancer.set_current_peer にて proxy 先を動的に設定します。 host 部分にはドメインを直接指定することができないため、ポイント 2. で ngx.ctx にセットした DNS の値から IP(Route53 に CNAME レコードとして設定している)を指定しています。 balancer_by_lua_block { local balancer = require "ngx.balancer" -- ngx.ctx にセットしていた、Private DNS から取得した内部 IP をセット local host = ngx . ctx . upstream_server . cname local port = '8888' -- proxy 先セット。host にドメインは直接指定できない local ok , err = balancer . set_current_peer ( host , port ) if not ok then return ngx . exit ( 500 ) end } 詳細については OpenResty の ドキュメント を参照してください ポイント 2. 動的名前解決 r:query にて、生成したドメイン名( <id>.local )を問い合わせます。 r 部分は resolver:new で nameserver を指定した resolver となります。 なお、nameserver に指定する IP は今回は Route53 の Private DNS を指定するため、外部 nameserver ではなくローカルの nameserver(10.0.0.2 など)を指定することになります。 問い合わせ結果の answers 部分は Lua table 形式の配列となります。今回の例でいうと対象は 1 件となるので、その値を balancer_by_lua_block で使用するために ngx.ctx にセットしています。 local answers , err = r : query ( ngx . var . proxy_upstream_host , { qtype = r . TYPE_CNAME }) if not answers then ngx . exit ( ngx . HTTP_INTERNAL_SERVER_ERROR ) end if answers . errcode then ngx . exit ( ngx . HTTP_INTERNAL_SERVER_ERROR ) end ngx . ctx . upstream_server = answers [ 1 ] 詳細については OpenResty の ドキュメント を参照してください 今回のまとめ upstream 先を動的に判定して proxy するという要件はそうそう無いかもしれませんし、途中までは複雑な構成になりそうだなぁとドキドキしてしましたが、結果としてはそれなりにシンプルになったかなと思います。今更ながら Nginx(と lua module)は柔軟で良く出来てるなぁという感想でした。 後編は App 層について、EC2 と Systems Manager パラメータストアあたりについて共有させていただければと思います。 クライアント認証と Path Based Routing が必要なサーバを AWS で構築(後編:App 層) | MEDLEY Developer Portal 今回の内容について メドレー開発本部の田中です。 先日、Proxy 層を Elastic Beanstalk 上の Nginx で、App 層を EC2 インスタンスで構築する機会がありました。ここだけ見るととても普通に見えますが、制約があ... developer.medley.jp 参考リンク 構築にあたり、下記記事を参考にさせていただきました。ありがとうございます。 Nginx balancer_by_luaの話とupstream名前解決の話 - Qiita balancer_by_lua_xxxxx いつの間にやら1 lua-nginx-module に balancer_by_lua_xxx という新しいディレクティブが増えていました。 以下ドキュメントより抜粋。 http { upstream backend {... qiita.com お知らせ メドレーでは、医師たちがつくるオンライン医療事典「 MEDLEY 」、オンライン診療アプリ「 CLINICS 」、医療介護の求人サイト「 ジョブメドレー 」、口コミで探せる介護施設の検索サイト「 介護のほんね 」などのプロダクトを提供しています。これらのサービスの拡大を受けて、その成長を支えるエンジニア・デザイナーを募集しています。 メドレーで一緒に医療体験を変えるプロダクト作りに関わりたい方のご連絡お待ちしております。 メンバーのストーリー | 株式会社メドレー メンバーのストーリー 家族や友人が病気になった時に救いの手を差しのべる医療の力。... www.medley.jp
今回の内容について メドレー開発本部の 田中 です。 先日、Proxy 層を Elastic Beanstalk 上の Nginx で、App 層を EC2 インスタンスで構築する機会がありました。ここだけ見るととても普通に見えますが、後述する制約から苦労した点もあり、制約を乗り越えるための工夫も含めてお話できる限り共有させていただきます(先にお伝えしておくと、特殊な事情がなければ今回のようなケースでは ALB で対応する ECS サービスに Path Based Routing してやるのが良いと思います)。 技術要素として、Nginx(OpenResty)/ Route53 Private DNS / EC2 / Systems Manager パラメータストア あたりに触れたいと思います。(Beanstalk は Multicontainer Docker を使用し、それも慣れるまでちょっとクセあったなぁと思ったのですが分量が多くなりそうなのでまた別の機会に共有させて頂きます) まず前編として Proxy 層、主に Nginx を使用した Dynamic Path Based Routing についてお話して、 後編は App 層 について、EC2 と Systems Manager パラメータストアあたりについて共有させていただければと思います。 設計/構築する上での前提と方針 対象となる案件を進める上での要件・制限内容は諸事情あり、ざっとまとめるとこのような感じです。 環境は AWS を使用する サーバアプリケーション、クライアントアプリケーションはユーザ毎で、サーバアプリケーションは共用できない(ユーザが増える度にクライアント/サーバのセットが増えるイメージ) ただし、クライアントからの接続先となる Endpoint は同じだが、Host Based Routing は訳あって利用できない クライアント認証を使用する 上記から、以下の設計方針で進める事にしました。 Proxy 層でクライアント認証を行い、Path Based Routing で対象となるサーバにリクエストを proxy する。Path 部分にクライアント別の識別 ID を含め、その値を元に Private DNS で名前解決する 例) https://example.com/a-client/api => https://a-client.local/api App 層は個別 EC2 インスタンスとする 設計する上で悩んだ点 主に 2 点ありますが、まずは Proxy 層です。出来るだけ AWS のマネージド・サービスで済ませたかったので、クライアント認証と Path Based Routing が可能でやりたい事に合うかどうか調べましたが以下の理由で断念し、普通(?)に ELB + Nginx を利用することにしました。 ALB: クライアント認証に非対応。また SSL 終端となるので Nginx 側でクライアント認証が出来ない API GW: クライアント認証は対応しており Routing 部分もがんばればいけるかも?、と思ったが Proxy 先が動的に増えたリするので管理ふくめ難しそうであった 次に App 層の構成をどうするかでした。集積度を高めるためにコンテナ利用も検討したのですが、使用するアプリケーションの必要スペックや要件などからいまいちフィットせず、個別の EC2 インスタンスにすることにしました(今でももっと良い方法がないか悩んでたりします) 全体構成 出来上がった全体構成のイメージは以下となります。なお台数は実環境と異なり、今回の内容と関係ない部分などは省略しています。 次に、今回の本題となる Proxy 層の構成について触れたいと思います。 Proxy 層の構成 Proxy 層の方針等はまとめると以下の通りで、proxy 先の動的判定と名前解決する箇所がキモとなります。 App 層のインスタンスは、起動時に自身の内部 IP と Tag に設定したクライアント識別 ID を元に Route53 の PrivateDNS に登録する クライアント識別 ID が a-client の場合、a-client.local のように登録 Proxy 層の Nginx はクライアント認証を行い、リクエストパスから取り出したクライアント識別 ID を元に転送先 Endpoint を生成し、backend に proxy する App 層のインスタンスは動的に増えるため、リクエスト時に名前解決したい(インスタンスが増える度に自動で Nginx の conf を編集することも検討したが追加数が読めず、conf がふくれあがるのもなぁ、、、という思いがあり止めました) Nginx は backend が増えても起動しっぱなしで動的に名前解決して動作させたかったため、lua-nginx-module を導入し balancer_by_lua ディレクティブと lua-resty-dns モジュールを使用することとし、構築の手間の関係から OpenResty を導入することにしました。 lua-nginx-module を使用した conf ファイル conf ファイル全体としては以下となります(関係ない箇所は省いています)。ポイントと記載した部分についての説明は後述します。 http { upstream app { # ポイント 1. # Private DNS で設定した IP(CNAME に設定)を元に動的 Routing balancer_by_lua_block { local balancer = require "ngx.balancer" local host = ngx . ctx . upstream_server . cname local port = '8888' local ok , err = balancer . set_current_peer ( host , port ) if not ok then return ngx . exit ( 500 ) end } } server { listen 443 ssl; set $ proxy_upstream_host '' ; set $ proxy_upstream_domain '.local' ; location ^~ /api/ { rewrite_by_lua_block { -- path からクライアント識別 ID を取得し、Private DNS に設定したドメインを生成 -- https://example.com/<id>/api という形式のリクエストから、<id>.local というドメインを生成して -- ngx.var.proxy_upstream_host 変数に格納 local ngx_re = require "ngx.re" local res , err = ngx_re . split ( ngx . var . request_uri , "/" , nil , { pos = 0 }) local id = res[3] ngx.var. proxy_upstream_host = id..ngx.var.proxy_upstream_domain; -- resolver 設定 local resolver = require "resty.dns.resolver" local r, err = resolver:new{ nameservers = {{ "x.x.x.x" , 53}}, -- 使用する nameserver } if not r then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end -- ポイント 2. -- 生成したドメイン名(<id>.local)を元に名前解決し、取得した結果を ngx.ctx にセット -- (balancer_by_lua_block で使用する) local answers, err = r:query(ngx.var.proxy_upstream_host, { qtype = r.TYPE_CNAME }) if not answers then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end if answers.errcode then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end ngx.ctx.upstream_server = answers[1] } proxy_set_header Host $ host ; proxy_set_header X-Real-IP $ remote_addr ; proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for ; proxy_set_header X-Forwarded-Proto $ scheme ; -- https://<id>.local/api に proxy rewrite ^/api/(.+)$ /api/ break; proxy_pass https://app; } } } ポイント 1. 動的 Routing balancer.set_current_peer にて proxy 先を動的に設定します。 host 部分にはドメインを直接指定することができないため、ポイント 2. で ngx.ctx にセットした DNS の値から IP(Route53 に CNAME レコードとして設定している)を指定しています。 balancer_by_lua_block { local balancer = require "ngx.balancer" -- ngx.ctx にセットしていた、Private DNS から取得した内部 IP をセット local host = ngx . ctx . upstream_server . cname local port = '8888' -- proxy 先セット。host にドメインは直接指定できない local ok , err = balancer . set_current_peer ( host , port ) if not ok then return ngx . exit ( 500 ) end } 詳細については OpenResty の ドキュメント を参照してください ポイント 2. 動的名前解決 r:query にて、生成したドメイン名( <id>.local )を問い合わせます。 r 部分は resolver:new で nameserver を指定した resolver となります。 なお、nameserver に指定する IP は今回は Route53 の Private DNS を指定するため、外部 nameserver ではなくローカルの nameserver(10.0.0.2 など)を指定することになります。 問い合わせ結果の answers 部分は Lua table 形式の配列となります。今回の例でいうと対象は 1 件となるので、その値を balancer_by_lua_block で使用するために ngx.ctx にセットしています。 local answers , err = r : query ( ngx . var . proxy_upstream_host , { qtype = r . TYPE_CNAME }) if not answers then ngx . exit ( ngx . HTTP_INTERNAL_SERVER_ERROR ) end if answers . errcode then ngx . exit ( ngx . HTTP_INTERNAL_SERVER_ERROR ) end ngx . ctx . upstream_server = answers [ 1 ] 詳細については OpenResty の ドキュメント を参照してください 今回のまとめ upstream 先を動的に判定して proxy するという要件はそうそう無いかもしれませんし、途中までは複雑な構成になりそうだなぁとドキドキしてしましたが、結果としてはそれなりにシンプルになったかなと思います。今更ながら Nginx(と lua module)は柔軟で良く出来てるなぁという感想でした。 後編は App 層について、EC2 と Systems Manager パラメータストアあたりについて共有させていただければと思います。 クライアント認証と Path Based Routing が必要なサーバを AWS で構築(後編:App 層) | MEDLEY Developer Portal 今回の内容について メドレー開発本部の田中です。 先日、Proxy 層を Elastic Beanstalk 上の Nginx で、App 層を EC2 インスタンスで構築する機会がありました。ここだけ見るととても普通に見えますが、制約があ... developer.medley.jp 参考リンク 構築にあたり、下記記事を参考にさせていただきました。ありがとうございます。 Nginx balancer_by_luaの話とupstream名前解決の話 - Qiita balancer_by_lua_xxxxx いつの間にやら1 lua-nginx-module に balancer_by_lua_xxx という新しいディレクティブが増えていました。 以下ドキュメントより抜粋。 http { upstream backend {... qiita.com お知らせ メドレーでは、医師たちがつくるオンライン医療事典「 MEDLEY 」、オンライン診療アプリ「 CLINICS 」、医療介護の求人サイト「 ジョブメドレー 」、口コミで探せる介護施設の検索サイト「 介護のほんね 」などのプロダクトを提供しています。これらのサービスの拡大を受けて、その成長を支えるエンジニア・デザイナーを募集しています。 メドレーで一緒に医療体験を変えるプロダクト作りに関わりたい方のご連絡お待ちしております。 メンバーのストーリー | 株式会社メドレー メンバーのストーリー 家族や友人が病気になった時に救いの手を差しのべる医療の力。... www.medley.jp
今回の内容について メドレー開発本部の 田中 です。 先日、Proxy 層を Elastic Beanstalk 上の Nginx で、App 層を EC2 インスタンスで構築する機会がありました。ここだけ見るととても普通に見えますが、後述する制約から苦労した点もあり、制約を乗り越えるための工夫も含めてお話できる限り共有させていただきます(先にお伝えしておくと、特殊な事情がなければ今回のようなケースでは ALB で対応する ECS サービスに Path Based Routing してやるのが良いと思います)。 技術要素として、Nginx(OpenResty)/ Route53 Private DNS / EC2 / Systems Manager パラメータストア あたりに触れたいと思います。(Beanstalk は Multicontainer Docker を使用し、それも慣れるまでちょっとクセあったなぁと思ったのですが分量が多くなりそうなのでまた別の機会に共有させて頂きます) まず前編として Proxy 層、主に Nginx を使用した Dynamic Path Based Routing についてお話して、 後編は App 層 について、EC2 と Systems Manager パラメータストアあたりについて共有させていただければと思います。 設計/構築する上での前提と方針 対象となる案件を進める上での要件・制限内容は諸事情あり、ざっとまとめるとこのような感じです。 環境は AWS を使用する サーバアプリケーション、クライアントアプリケーションはユーザ毎で、サーバアプリケーションは共用できない(ユーザが増える度にクライアント/サーバのセットが増えるイメージ) ただし、クライアントからの接続先となる Endpoint は同じだが、Host Based Routing は訳あって利用できない クライアント認証を使用する 上記から、以下の設計方針で進める事にしました。 Proxy 層でクライアント認証を行い、Path Based Routing で対象となるサーバにリクエストを proxy する。Path 部分にクライアント別の識別 ID を含め、その値を元に Private DNS で名前解決する 例) https://example.com/a-client/api => https://a-client.local/api App 層は個別 EC2 インスタンスとする 設計する上で悩んだ点 主に 2 点ありますが、まずは Proxy 層です。出来るだけ AWS のマネージド・サービスで済ませたかったので、クライアント認証と Path Based Routing が可能でやりたい事に合うかどうか調べましたが以下の理由で断念し、普通(?)に ELB + Nginx を利用することにしました。 ALB: クライアント認証に非対応。また SSL 終端となるので Nginx 側でクライアント認証が出来ない API GW: クライアント認証は対応しており Routing 部分もがんばればいけるかも?、と思ったが Proxy 先が動的に増えたリするので管理ふくめ難しそうであった 次に App 層の構成をどうするかでした。集積度を高めるためにコンテナ利用も検討したのですが、使用するアプリケーションの必要スペックや要件などからいまいちフィットせず、個別の EC2 インスタンスにすることにしました(今でももっと良い方法がないか悩んでたりします) 全体構成 出来上がった全体構成のイメージは以下となります。なお台数は実環境と異なり、今回の内容と関係ない部分などは省略しています。 次に、今回の本題となる Proxy 層の構成について触れたいと思います。 Proxy 層の構成 Proxy 層の方針等はまとめると以下の通りで、proxy 先の動的判定と名前解決する箇所がキモとなります。 App 層のインスタンスは、起動時に自身の内部 IP と Tag に設定したクライアント識別 ID を元に Route53 の PrivateDNS に登録する クライアント識別 ID が a-client の場合、a-client.local のように登録 Proxy 層の Nginx はクライアント認証を行い、リクエストパスから取り出したクライアント識別 ID を元に転送先 Endpoint を生成し、backend に proxy する App 層のインスタンスは動的に増えるため、リクエスト時に名前解決したい(インスタンスが増える度に自動で Nginx の conf を編集することも検討したが追加数が読めず、conf がふくれあがるのもなぁ、、、という思いがあり止めました) Nginx は backend が増えても起動しっぱなしで動的に名前解決して動作させたかったため、lua-nginx-module を導入し balancer_by_lua ディレクティブと lua-resty-dns モジュールを使用することとし、構築の手間の関係から OpenResty を導入することにしました。 lua-nginx-module を使用した conf ファイル conf ファイル全体としては以下となります(関係ない箇所は省いています)。ポイントと記載した部分についての説明は後述します。 http { upstream app { # ポイント 1. # Private DNS で設定した IP(CNAME に設定)を元に動的 Routing balancer_by_lua_block { local balancer = require "ngx.balancer" local host = ngx . ctx . upstream_server . cname local port = '8888' local ok , err = balancer . set_current_peer ( host , port ) if not ok then return ngx . exit ( 500 ) end } } server { listen 443 ssl; set $ proxy_upstream_host '' ; set $ proxy_upstream_domain '.local' ; location ^~ /api/ { rewrite_by_lua_block { -- path からクライアント識別 ID を取得し、Private DNS に設定したドメインを生成 -- https://example.com/<id>/api という形式のリクエストから、<id>.local というドメインを生成して -- ngx.var.proxy_upstream_host 変数に格納 local ngx_re = require "ngx.re" local res , err = ngx_re . split ( ngx . var . request_uri , "/" , nil , { pos = 0 }) local id = res[3] ngx.var. proxy_upstream_host = id..ngx.var.proxy_upstream_domain; -- resolver 設定 local resolver = require "resty.dns.resolver" local r, err = resolver:new{ nameservers = {{ "x.x.x.x" , 53}}, -- 使用する nameserver } if not r then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end -- ポイント 2. -- 生成したドメイン名(<id>.local)を元に名前解決し、取得した結果を ngx.ctx にセット -- (balancer_by_lua_block で使用する) local answers, err = r:query(ngx.var.proxy_upstream_host, { qtype = r.TYPE_CNAME }) if not answers then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end if answers.errcode then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end ngx.ctx.upstream_server = answers[1] } proxy_set_header Host $ host ; proxy_set_header X-Real-IP $ remote_addr ; proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for ; proxy_set_header X-Forwarded-Proto $ scheme ; -- https://<id>.local/api に proxy rewrite ^/api/(.+)$ /api/ break; proxy_pass https://app; } } } ポイント 1. 動的 Routing balancer.set_current_peer にて proxy 先を動的に設定します。 host 部分にはドメインを直接指定することができないため、ポイント 2. で ngx.ctx にセットした DNS の値から IP(Route53 に CNAME レコードとして設定している)を指定しています。 balancer_by_lua_block { local balancer = require "ngx.balancer" -- ngx.ctx にセットしていた、Private DNS から取得した内部 IP をセット local host = ngx . ctx . upstream_server . cname local port = '8888' -- proxy 先セット。host にドメインは直接指定できない local ok , err = balancer . set_current_peer ( host , port ) if not ok then return ngx . exit ( 500 ) end } 詳細については OpenResty の ドキュメント を参照してください ポイント 2. 動的名前解決 r:query にて、生成したドメイン名( <id>.local )を問い合わせます。 r 部分は resolver:new で nameserver を指定した resolver となります。 なお、nameserver に指定する IP は今回は Route53 の Private DNS を指定するため、外部 nameserver ではなくローカルの nameserver(10.0.0.2 など)を指定することになります。 問い合わせ結果の answers 部分は Lua table 形式の配列となります。今回の例でいうと対象は 1 件となるので、その値を balancer_by_lua_block で使用するために ngx.ctx にセットしています。 local answers , err = r : query ( ngx . var . proxy_upstream_host , { qtype = r . TYPE_CNAME }) if not answers then ngx . exit ( ngx . HTTP_INTERNAL_SERVER_ERROR ) end if answers . errcode then ngx . exit ( ngx . HTTP_INTERNAL_SERVER_ERROR ) end ngx . ctx . upstream_server = answers [ 1 ] 詳細については OpenResty の ドキュメント を参照してください 今回のまとめ upstream 先を動的に判定して proxy するという要件はそうそう無いかもしれませんし、途中までは複雑な構成になりそうだなぁとドキドキしてしましたが、結果としてはそれなりにシンプルになったかなと思います。今更ながら Nginx(と lua module)は柔軟で良く出来てるなぁという感想でした。 後編は App 層について、EC2 と Systems Manager パラメータストアあたりについて共有させていただければと思います。 クライアント認証と Path Based Routing が必要なサーバを AWS で構築(後編:App 層) | MEDLEY Developer Portal 今回の内容について メドレー開発本部の田中です。 先日、Proxy 層を Elastic Beanstalk 上の Nginx で、App 層を EC2 インスタンスで構築する機会がありました。ここだけ見るととても普通に見えますが、制約があ... developer.medley.jp 参考リンク 構築にあたり、下記記事を参考にさせていただきました。ありがとうございます。 Nginx balancer_by_luaの話とupstream名前解決の話 - Qiita balancer_by_lua_xxxxx いつの間にやら1 lua-nginx-module に balancer_by_lua_xxx という新しいディレクティブが増えていました。 以下ドキュメントより抜粋。 http { upstream backend {... qiita.com お知らせ メドレーでは、医師たちがつくるオンライン医療事典「 MEDLEY 」、オンライン診療アプリ「 CLINICS 」、医療介護の求人サイト「 ジョブメドレー 」、口コミで探せる介護施設の検索サイト「 介護のほんね 」などのプロダクトを提供しています。これらのサービスの拡大を受けて、その成長を支えるエンジニア・デザイナーを募集しています。 メドレーで一緒に医療体験を変えるプロダクト作りに関わりたい方のご連絡お待ちしております。 メンバーのストーリー | 株式会社メドレー メンバーのストーリー 家族や友人が病気になった時に救いの手を差しのべる医療の力。... www.medley.jp
開発本部の平山です。先日、社内勉強会「TechLunch」にて社外に公開できない内容の発表をしてしまいましたので、その代わりとして、厚生労働省が提供する「NDB オープンデータ」をオープン化した話について、ブログを書こうと思います。 NDB オープンデータとは? www.mhlw.go.jp 作成の背景 ◆ レセプト情報・特定健診等情報データベース(NDB)は、悉皆性が高いレセプト情報、および検査値などの詳細な情報を有する特定健診等情報が含まれており、国民の医療動向を評価するうえで有用なデータだと考えられている。 ◆ 2011 年度より、医療費適正化計画策定に資する目的以外での NDB データの利用が認められたが、NDB データの機微性の高さに鑑み、利用者に対しては高いレベルのセキュリティ要件を課したうえで、データ提供が行われてきた。 ◆ 一方で、多くの研究者が必ずしも詳細な個票データを必要とするわけではないため、多くの人々が使用できるような、あらかじめ定式化された集計データを NDB データをもとに整備することが重要ではないか、という議論が有識者会議等でなされてきた。 ◆ NDB の民間提供に関する議論でも、「レセプト情報等の提供に関するワーキンググループ」からの報告では、汎用性が高く様々なニーズに一定程度応えうる基礎的な集計表を作成し、公表していくことがむしろ適当である、という指摘がみられた。 作成の目的 ◆ 多くの人々が NDB データに基づいた保健医療に関する知見に接することが出来るよう、NDB データを用いて基礎的な集計表を作成したうえで、公表する。 ◆ NDB データに基づき、医療の提供実態や特定健診等の結果をわかりやすく示す。 要は皆さんが、病院に行った時にもらう明細書に記載されている初診〇〇点、外来診療料〇〇点のようなデータが個人情報が匿名化された状態で収集しその統計データを一般に公開する、といったところでしょうか。 このようなデータがオープンになっていることはとても意義のあることだと思いますし、公開にまでこぎつけた関係者の苦労が想像されます。しかし、このような画期的なデータ提供ではありますが、Excel ファイルでの提供となっており、かつ加工がしづらいデータ構造になっているため、データを細かくみてみようとすると非常に手間がかかるという問題があります。 NDB オープンデータのオープン化 そこで NDB オープンデータとして公開されている Excel ファイルを加工し、DB に格納し BI ツール( Redash )から参照させるようにしてみました。 1. データ加工 & DB 取り込み 公開サイト にある医科診療行為に関する Excel ファイルを取得し、ログテーブルとしてよくあるフォーマットに変換し DB に取り込む。 変換前 変換後 *************************** 1. row *************************** id: 1 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: all revision: 2014 prefecture: sex: age: score: 251700771 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 *************************** 2. row *************************** id: 2 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: sex_age revision: 2014 prefecture: sex: 男性 age: 0~4 歳 score: 13158090 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 *************************** 3. row *************************** id: 3 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: sex_age revision: 2014 prefecture: sex: 男性 age: 5~9 歳 score: 12444947 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 2. データの参照 変換したデータを取り込んだ DB を Redash から参照。分析したいデータを取得するためのクエリを書いてダッシュボード化。 NDB オープンデータの活用例 以下に簡単なデータ活用のサンプルを載せました。医薬診療行為だけでなく特定健診や薬剤のデータを使うともう少し面白い気付きがあるかもしれません。 いずれにせよ、このように加工可能な形でのデータ提供こそがオープンデータ提供の価値だと思うので、このような仕組みが加速すれば良いなと思います。 0-4 歳 男性 診療行為点数 90 歳以上 男性 診療行為点数 140023350 胃瘻より流動食点滴注入 都道府県別 150086210 角膜移植術 年齡別 まとめ 以上、NDB オープンデータをオープン化してみた話について書いてみました。 このように.go.jp から提供されるデータは一般的に Excel や PDF でのファイル提供が基本で、インターネットサービスのように API のような形で提供されることはありません。せっかく貴重なデータが提供されているにも関わらず、それが IT システムと連動しづらいことで、活用されない状況になっているのはとても残念なことに思います。 Code for America の事例ではないですが、もっとインターネット系の人材がこのような取り組みに入り込んでいくようになれば、より合理的でスマートな仕組みが加速し、業界全体の IT 化も加速するのではないでしょうか。 お知らせ メドレーでは、医師たちがつくるオンライン医療事典「 MEDLEY 」、オンライン診療アプリ「 CLINICS 」、医療介護の求人サイト「 ジョブメドレー 」、口コミで探せる介護施設の検索サイト「 介護のほんね 」などのプロダクトを提供しています。これらのサービスの拡大を受けて、その成長を支えるエンジニア・デザイナーを募集しています。 メドレーで一緒に医療体験を変えるプロダクト作りに関わりたい方のご連絡お待ちしております。 www.medley.jp
開発本部の平山です。先日、社内勉強会「TechLunch」にて社外に公開できない内容の発表をしてしまいましたので、その代わりとして、厚生労働省が提供する「NDB オープンデータ」をオープン化した話について、ブログを書こうと思います。 NDB オープンデータとは? www.mhlw.go.jp 作成の背景 ◆ レセプト情報・特定健診等情報データベース(NDB)は、悉皆性が高いレセプト情報、および検査値などの詳細な情報を有する特定健診等情報が含まれており、国民の医療動向を評価するうえで有用なデータだと考えられている。 ◆ 2011 年度より、医療費適正化計画策定に資する目的以外での NDB データの利用が認められたが、NDB データの機微性の高さに鑑み、利用者に対しては高いレベルのセキュリティ要件を課したうえで、データ提供が行われてきた。 ◆ 一方で、多くの研究者が必ずしも詳細な個票データを必要とするわけではないため、多くの人々が使用できるような、あらかじめ定式化された集計データを NDB データをもとに整備することが重要ではないか、という議論が有識者会議等でなされてきた。 ◆ NDB の民間提供に関する議論でも、「レセプト情報等の提供に関するワーキンググループ」からの報告では、汎用性が高く様々なニーズに一定程度応えうる基礎的な集計表を作成し、公表していくことがむしろ適当である、という指摘がみられた。 作成の目的 ◆ 多くの人々が NDB データに基づいた保健医療に関する知見に接することが出来るよう、NDB データを用いて基礎的な集計表を作成したうえで、公表する。 ◆ NDB データに基づき、医療の提供実態や特定健診等の結果をわかりやすく示す。 要は皆さんが、病院に行った時にもらう明細書に記載されている初診〇〇点、外来診療料〇〇点のようなデータが個人情報が匿名化された状態で収集しその統計データを一般に公開する、といったところでしょうか。 このようなデータがオープンになっていることはとても意義のあることだと思いますし、公開にまでこぎつけた関係者の苦労が想像されます。しかし、このような画期的なデータ提供ではありますが、Excel ファイルでの提供となっており、かつ加工がしづらいデータ構造になっているため、データを細かくみてみようとすると非常に手間がかかるという問題があります。 NDB オープンデータのオープン化 そこで NDB オープンデータとして公開されている Excel ファイルを加工し、DB に格納し BI ツール( Redash )から参照させるようにしてみました。 1. データ加工 & DB 取り込み 公開サイト にある医科診療行為に関する Excel ファイルを取得し、ログテーブルとしてよくあるフォーマットに変換し DB に取り込む。 変換前 変換後 *************************** 1. row *************************** id: 1 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: all revision: 2014 prefecture: sex: age: score: 251700771 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 *************************** 2. row *************************** id: 2 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: sex_age revision: 2014 prefecture: sex: 男性 age: 0~4 歳 score: 13158090 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 *************************** 3. row *************************** id: 3 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: sex_age revision: 2014 prefecture: sex: 男性 age: 5~9 歳 score: 12444947 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 2. データの参照 変換したデータを取り込んだ DB を Redash から参照。分析したいデータを取得するためのクエリを書いてダッシュボード化。 NDB オープンデータの活用例 以下に簡単なデータ活用のサンプルを載せました。医薬診療行為だけでなく特定健診や薬剤のデータを使うともう少し面白い気付きがあるかもしれません。 いずれにせよ、このように加工可能な形でのデータ提供こそがオープンデータ提供の価値だと思うので、このような仕組みが加速すれば良いなと思います。 0-4 歳 男性 診療行為点数 90 歳以上 男性 診療行為点数 140023350 胃瘻より流動食点滴注入 都道府県別 150086210 角膜移植術 年齡別 まとめ 以上、NDB オープンデータをオープン化してみた話について書いてみました。 このように.go.jp から提供されるデータは一般的に Excel や PDF でのファイル提供が基本で、インターネットサービスのように API のような形で提供されることはありません。せっかく貴重なデータが提供されているにも関わらず、それが IT システムと連動しづらいことで、活用されない状況になっているのはとても残念なことに思います。 Code for America の事例ではないですが、もっとインターネット系の人材がこのような取り組みに入り込んでいくようになれば、より合理的でスマートな仕組みが加速し、業界全体の IT 化も加速するのではないでしょうか。 お知らせ メドレーでは、医師たちがつくるオンライン医療事典「 MEDLEY 」、オンライン診療アプリ「 CLINICS 」、医療介護の求人サイト「 ジョブメドレー 」、口コミで探せる介護施設の検索サイト「 介護のほんね 」などのプロダクトを提供しています。これらのサービスの拡大を受けて、その成長を支えるエンジニア・デザイナーを募集しています。 メドレーで一緒に医療体験を変えるプロダクト作りに関わりたい方のご連絡お待ちしております。 www.medley.jp
開発本部の平山です。先日、社内勉強会「TechLunch」にて社外に公開できない内容の発表をしてしまいましたので、その代わりとして、厚生労働省が提供する「NDB オープンデータ」をオープン化した話について、ブログを書こうと思います。 NDB オープンデータとは? www.mhlw.go.jp 作成の背景 ◆ レセプト情報・特定健診等情報データベース(NDB)は、悉皆性が高いレセプト情報、および検査値などの詳細な情報を有する特定健診等情報が含まれており、国民の医療動向を評価するうえで有用なデータだと考えられている。 ◆ 2011 年度より、医療費適正化計画策定に資する目的以外での NDB データの利用が認められたが、NDB データの機微性の高さに鑑み、利用者に対しては高いレベルのセキュリティ要件を課したうえで、データ提供が行われてきた。 ◆ 一方で、多くの研究者が必ずしも詳細な個票データを必要とするわけではないため、多くの人々が使用できるような、あらかじめ定式化された集計データを NDB データをもとに整備することが重要ではないか、という議論が有識者会議等でなされてきた。 ◆ NDB の民間提供に関する議論でも、「レセプト情報等の提供に関するワーキンググループ」からの報告では、汎用性が高く様々なニーズに一定程度応えうる基礎的な集計表を作成し、公表していくことがむしろ適当である、という指摘がみられた。 作成の目的 ◆ 多くの人々が NDB データに基づいた保健医療に関する知見に接することが出来るよう、NDB データを用いて基礎的な集計表を作成したうえで、公表する。 ◆ NDB データに基づき、医療の提供実態や特定健診等の結果をわかりやすく示す。 要は皆さんが、病院に行った時にもらう明細書に記載されている初診〇〇点、外来診療料〇〇点のようなデータが個人情報が匿名化された状態で収集しその統計データを一般に公開する、といったところでしょうか。 このようなデータがオープンになっていることはとても意義のあることだと思いますし、公開にまでこぎつけた関係者の苦労が想像されます。しかし、このような画期的なデータ提供ではありますが、Excel ファイルでの提供となっており、かつ加工がしづらいデータ構造になっているため、データを細かくみてみようとすると非常に手間がかかるという問題があります。 NDB オープンデータのオープン化 そこで NDB オープンデータとして公開されている Excel ファイルを加工し、DB に格納し BI ツール( Redash )から参照させるようにしてみました。 1. データ加工 & DB 取り込み 公開サイト にある医科診療行為に関する Excel ファイルを取得し、ログテーブルとしてよくあるフォーマットに変換し DB に取り込む。 変換前 変換後 *************************** 1. row *************************** id: 1 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: all revision: 2014 prefecture: sex: age: score: 251700771 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 *************************** 2. row *************************** id: 2 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: sex_age revision: 2014 prefecture: sex: 男性 age: 0~4 歳 score: 13158090 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 *************************** 3. row *************************** id: 3 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: sex_age revision: 2014 prefecture: sex: 男性 age: 5~9 歳 score: 12444947 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 2. データの参照 変換したデータを取り込んだ DB を Redash から参照。分析したいデータを取得するためのクエリを書いてダッシュボード化。 NDB オープンデータの活用例 以下に簡単なデータ活用のサンプルを載せました。医薬診療行為だけでなく特定健診や薬剤のデータを使うともう少し面白い気付きがあるかもしれません。 いずれにせよ、このように加工可能な形でのデータ提供こそがオープンデータ提供の価値だと思うので、このような仕組みが加速すれば良いなと思います。 0-4 歳 男性 診療行為点数 90 歳以上 男性 診療行為点数 140023350 胃瘻より流動食点滴注入 都道府県別 150086210 角膜移植術 年齡別 まとめ 以上、NDB オープンデータをオープン化してみた話について書いてみました。 このように.go.jp から提供されるデータは一般的に Excel や PDF でのファイル提供が基本で、インターネットサービスのように API のような形で提供されることはありません。せっかく貴重なデータが提供されているにも関わらず、それが IT システムと連動しづらいことで、活用されない状況になっているのはとても残念なことに思います。 Code for America の事例ではないですが、もっとインターネット系の人材がこのような取り組みに入り込んでいくようになれば、より合理的でスマートな仕組みが加速し、業界全体の IT 化も加速するのではないでしょうか。 お知らせ メドレーでは、医師たちがつくるオンライン医療事典「 MEDLEY 」、オンライン診療アプリ「 CLINICS 」、医療介護の求人サイト「 ジョブメドレー 」、口コミで探せる介護施設の検索サイト「 介護のほんね 」などのプロダクトを提供しています。これらのサービスの拡大を受けて、その成長を支えるエンジニア・デザイナーを募集しています。 メドレーで一緒に医療体験を変えるプロダクト作りに関わりたい方のご連絡お待ちしております。 www.medley.jp
開発本部の平山です。先日、社内勉強会「TechLunch」にて社外に公開できない内容の発表をしてしまいましたので、その代わりとして、厚生労働省が提供する「NDB オープンデータ」をオープン化した話について、ブログを書こうと思います。 NDB オープンデータとは? www.mhlw.go.jp 作成の背景 ◆ レセプト情報・特定健診等情報データベース(NDB)は、悉皆性が高いレセプト情報、および検査値などの詳細な情報を有する特定健診等情報が含まれており、国民の医療動向を評価するうえで有用なデータだと考えられている。 ◆ 2011 年度より、医療費適正化計画策定に資する目的以外での NDB データの利用が認められたが、NDB データの機微性の高さに鑑み、利用者に対しては高いレベルのセキュリティ要件を課したうえで、データ提供が行われてきた。 ◆ 一方で、多くの研究者が必ずしも詳細な個票データを必要とするわけではないため、多くの人々が使用できるような、あらかじめ定式化された集計データを NDB データをもとに整備することが重要ではないか、という議論が有識者会議等でなされてきた。 ◆ NDB の民間提供に関する議論でも、「レセプト情報等の提供に関するワーキンググループ」からの報告では、汎用性が高く様々なニーズに一定程度応えうる基礎的な集計表を作成し、公表していくことがむしろ適当である、という指摘がみられた。 作成の目的 ◆ 多くの人々が NDB データに基づいた保健医療に関する知見に接することが出来るよう、NDB データを用いて基礎的な集計表を作成したうえで、公表する。 ◆ NDB データに基づき、医療の提供実態や特定健診等の結果をわかりやすく示す。 要は皆さんが、病院に行った時にもらう明細書に記載されている初診〇〇点、外来診療料〇〇点のようなデータが個人情報が匿名化された状態で収集しその統計データを一般に公開する、といったところでしょうか。 このようなデータがオープンになっていることはとても意義のあることだと思いますし、公開にまでこぎつけた関係者の苦労が想像されます。しかし、このような画期的なデータ提供ではありますが、Excel ファイルでの提供となっており、かつ加工がしづらいデータ構造になっているため、データを細かくみてみようとすると非常に手間がかかるという問題があります。 NDB オープンデータのオープン化 そこで NDB オープンデータとして公開されている Excel ファイルを加工し、DB に格納し BI ツール( Redash )から参照させるようにしてみました。 1. データ加工 & DB 取り込み 公開サイト にある医科診療行為に関する Excel ファイルを取得し、ログテーブルとしてよくあるフォーマットに変換し DB に取り込む。 変換前 変換後 *************************** 1. row *************************** id: 1 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: all revision: 2014 prefecture: sex: age: score: 251700771 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 *************************** 2. row *************************** id: 2 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: sex_age revision: 2014 prefecture: sex: 男性 age: 0~4 歳 score: 13158090 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 *************************** 3. row *************************** id: 3 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: sex_age revision: 2014 prefecture: sex: 男性 age: 5~9 歳 score: 12444947 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 2. データの参照 変換したデータを取り込んだ DB を Redash から参照。分析したいデータを取得するためのクエリを書いてダッシュボード化。 NDB オープンデータの活用例 以下に簡単なデータ活用のサンプルを載せました。医薬診療行為だけでなく特定健診や薬剤のデータを使うともう少し面白い気付きがあるかもしれません。 いずれにせよ、このように加工可能な形でのデータ提供こそがオープンデータ提供の価値だと思うので、このような仕組みが加速すれば良いなと思います。 0-4 歳 男性 診療行為点数 90 歳以上 男性 診療行為点数 140023350 胃瘻より流動食点滴注入 都道府県別 150086210 角膜移植術 年齡別 まとめ 以上、NDB オープンデータをオープン化してみた話について書いてみました。 このように.go.jp から提供されるデータは一般的に Excel や PDF でのファイル提供が基本で、インターネットサービスのように API のような形で提供されることはありません。せっかく貴重なデータが提供されているにも関わらず、それが IT システムと連動しづらいことで、活用されない状況になっているのはとても残念なことに思います。 Code for America の事例ではないですが、もっとインターネット系の人材がこのような取り組みに入り込んでいくようになれば、より合理的でスマートな仕組みが加速し、業界全体の IT 化も加速するのではないでしょうか。 お知らせ メドレーでは、医師たちがつくるオンライン医療事典「 MEDLEY 」、オンライン診療アプリ「 CLINICS 」、医療介護の求人サイト「 ジョブメドレー 」、口コミで探せる介護施設の検索サイト「 介護のほんね 」などのプロダクトを提供しています。これらのサービスの拡大を受けて、その成長を支えるエンジニア・デザイナーを募集しています。 メドレーで一緒に医療体験を変えるプロダクト作りに関わりたい方のご連絡お待ちしております。 www.medley.jp
開発本部の平山です。先日、社内勉強会「TechLunch」にて社外に公開できない内容の発表をしてしまいましたので、その代わりとして、厚生労働省が提供する「NDB オープンデータ」をオープン化した話について、ブログを書こうと思います。 NDB オープンデータとは? www.mhlw.go.jp 作成の背景 ◆ レセプト情報・特定健診等情報データベース(NDB)は、悉皆性が高いレセプト情報、および検査値などの詳細な情報を有する特定健診等情報が含まれており、国民の医療動向を評価するうえで有用なデータだと考えられている。 ◆ 2011 年度より、医療費適正化計画策定に資する目的以外での NDB データの利用が認められたが、NDB データの機微性の高さに鑑み、利用者に対しては高いレベルのセキュリティ要件を課したうえで、データ提供が行われてきた。 ◆ 一方で、多くの研究者が必ずしも詳細な個票データを必要とするわけではないため、多くの人々が使用できるような、あらかじめ定式化された集計データを NDB データをもとに整備することが重要ではないか、という議論が有識者会議等でなされてきた。 ◆ NDB の民間提供に関する議論でも、「レセプト情報等の提供に関するワーキンググループ」からの報告では、汎用性が高く様々なニーズに一定程度応えうる基礎的な集計表を作成し、公表していくことがむしろ適当である、という指摘がみられた。 作成の目的 ◆ 多くの人々が NDB データに基づいた保健医療に関する知見に接することが出来るよう、NDB データを用いて基礎的な集計表を作成したうえで、公表する。 ◆ NDB データに基づき、医療の提供実態や特定健診等の結果をわかりやすく示す。 要は皆さんが、病院に行った時にもらう明細書に記載されている初診〇〇点、外来診療料〇〇点のようなデータが個人情報が匿名化された状態で収集しその統計データを一般に公開する、といったところでしょうか。 このようなデータがオープンになっていることはとても意義のあることだと思いますし、公開にまでこぎつけた関係者の苦労が想像されます。しかし、このような画期的なデータ提供ではありますが、Excel ファイルでの提供となっており、かつ加工がしづらいデータ構造になっているため、データを細かくみてみようとすると非常に手間がかかるという問題があります。 NDB オープンデータのオープン化 そこで NDB オープンデータとして公開されている Excel ファイルを加工し、DB に格納し BI ツール( Redash )から参照させるようにしてみました。 1. データ加工 & DB 取り込み 公開サイト にある医科診療行為に関する Excel ファイルを取得し、ログテーブルとしてよくあるフォーマットに変換し DB に取り込む。 変換前 変換後 *************************** 1. row *************************** id: 1 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: all revision: 2014 prefecture: sex: age: score: 251700771 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 *************************** 2. row *************************** id: 2 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: sex_age revision: 2014 prefecture: sex: 男性 age: 0~4 歳 score: 13158090 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 *************************** 3. row *************************** id: 3 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: sex_age revision: 2014 prefecture: sex: 男性 age: 5~9 歳 score: 12444947 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 2. データの参照 変換したデータを取り込んだ DB を Redash から参照。分析したいデータを取得するためのクエリを書いてダッシュボード化。 NDB オープンデータの活用例 以下に簡単なデータ活用のサンプルを載せました。医薬診療行為だけでなく特定健診や薬剤のデータを使うともう少し面白い気付きがあるかもしれません。 いずれにせよ、このように加工可能な形でのデータ提供こそがオープンデータ提供の価値だと思うので、このような仕組みが加速すれば良いなと思います。 0-4 歳 男性 診療行為点数 90 歳以上 男性 診療行為点数 140023350 胃瘻より流動食点滴注入 都道府県別 150086210 角膜移植術 年齡別 まとめ 以上、NDB オープンデータをオープン化してみた話について書いてみました。 このように.go.jp から提供されるデータは一般的に Excel や PDF でのファイル提供が基本で、インターネットサービスのように API のような形で提供されることはありません。せっかく貴重なデータが提供されているにも関わらず、それが IT システムと連動しづらいことで、活用されない状況になっているのはとても残念なことに思います。 Code for America の事例ではないですが、もっとインターネット系の人材がこのような取り組みに入り込んでいくようになれば、より合理的でスマートな仕組みが加速し、業界全体の IT 化も加速するのではないでしょうか。 お知らせ メドレーでは、医師たちがつくるオンライン医療事典「 MEDLEY 」、オンライン診療アプリ「 CLINICS 」、医療介護の求人サイト「 ジョブメドレー 」、口コミで探せる介護施設の検索サイト「 介護のほんね 」などのプロダクトを提供しています。これらのサービスの拡大を受けて、その成長を支えるエンジニア・デザイナーを募集しています。 メドレーで一緒に医療体験を変えるプロダクト作りに関わりたい方のご連絡お待ちしております。 www.medley.jp
開発本部の平山です。先日、社内勉強会「TechLunch」にて社外に公開できない内容の発表をしてしまいましたので、その代わりとして、厚生労働省が提供する「NDB オープンデータ」をオープン化した話について、ブログを書こうと思います。 NDB オープンデータとは? www.mhlw.go.jp 作成の背景 ◆ レセプト情報・特定健診等情報データベース(NDB)は、悉皆性が高いレセプト情報、および検査値などの詳細な情報を有する特定健診等情報が含まれており、国民の医療動向を評価するうえで有用なデータだと考えられている。 ◆ 2011 年度より、医療費適正化計画策定に資する目的以外での NDB データの利用が認められたが、NDB データの機微性の高さに鑑み、利用者に対しては高いレベルのセキュリティ要件を課したうえで、データ提供が行われてきた。 ◆ 一方で、多くの研究者が必ずしも詳細な個票データを必要とするわけではないため、多くの人々が使用できるような、あらかじめ定式化された集計データを NDB データをもとに整備することが重要ではないか、という議論が有識者会議等でなされてきた。 ◆ NDB の民間提供に関する議論でも、「レセプト情報等の提供に関するワーキンググループ」からの報告では、汎用性が高く様々なニーズに一定程度応えうる基礎的な集計表を作成し、公表していくことがむしろ適当である、という指摘がみられた。 作成の目的 ◆ 多くの人々が NDB データに基づいた保健医療に関する知見に接することが出来るよう、NDB データを用いて基礎的な集計表を作成したうえで、公表する。 ◆ NDB データに基づき、医療の提供実態や特定健診等の結果をわかりやすく示す。 要は皆さんが、病院に行った時にもらう明細書に記載されている初診〇〇点、外来診療料〇〇点のようなデータが個人情報が匿名化された状態で収集しその統計データを一般に公開する、といったところでしょうか。 このようなデータがオープンになっていることはとても意義のあることだと思いますし、公開にまでこぎつけた関係者の苦労が想像されます。しかし、このような画期的なデータ提供ではありますが、Excel ファイルでの提供となっており、かつ加工がしづらいデータ構造になっているため、データを細かくみてみようとすると非常に手間がかかるという問題があります。 NDB オープンデータのオープン化 そこで NDB オープンデータとして公開されている Excel ファイルを加工し、DB に格納し BI ツール( Redash )から参照させるようにしてみました。 1. データ加工 & DB 取り込み 公開サイト にある医科診療行為に関する Excel ファイルを取得し、ログテーブルとしてよくあるフォーマットに変換し DB に取り込む。 変換前 変換後 *************************** 1. row *************************** id: 1 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: all revision: 2014 prefecture: sex: age: score: 251700771 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 *************************** 2. row *************************** id: 2 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: sex_age revision: 2014 prefecture: sex: 男性 age: 0~4 歳 score: 13158090 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 *************************** 3. row *************************** id: 3 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: sex_age revision: 2014 prefecture: sex: 男性 age: 5~9 歳 score: 12444947 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 2. データの参照 変換したデータを取り込んだ DB を Redash から参照。分析したいデータを取得するためのクエリを書いてダッシュボード化。 NDB オープンデータの活用例 以下に簡単なデータ活用のサンプルを載せました。医薬診療行為だけでなく特定健診や薬剤のデータを使うともう少し面白い気付きがあるかもしれません。 いずれにせよ、このように加工可能な形でのデータ提供こそがオープンデータ提供の価値だと思うので、このような仕組みが加速すれば良いなと思います。 0-4 歳 男性 診療行為点数 90 歳以上 男性 診療行為点数 140023350 胃瘻より流動食点滴注入 都道府県別 150086210 角膜移植術 年齡別 まとめ 以上、NDB オープンデータをオープン化してみた話について書いてみました。 このように.go.jp から提供されるデータは一般的に Excel や PDF でのファイル提供が基本で、インターネットサービスのように API のような形で提供されることはありません。せっかく貴重なデータが提供されているにも関わらず、それが IT システムと連動しづらいことで、活用されない状況になっているのはとても残念なことに思います。 Code for America の事例ではないですが、もっとインターネット系の人材がこのような取り組みに入り込んでいくようになれば、より合理的でスマートな仕組みが加速し、業界全体の IT 化も加速するのではないでしょうか。 お知らせ メドレーでは、医師たちがつくるオンライン医療事典「 MEDLEY 」、オンライン診療アプリ「 CLINICS 」、医療介護の求人サイト「 ジョブメドレー 」、口コミで探せる介護施設の検索サイト「 介護のほんね 」などのプロダクトを提供しています。これらのサービスの拡大を受けて、その成長を支えるエンジニア・デザイナーを募集しています。 メドレーで一緒に医療体験を変えるプロダクト作りに関わりたい方のご連絡お待ちしております。 www.medley.jp
開発本部の平山です。先日、社内勉強会「TechLunch」にて社外に公開できない内容の発表をしてしまいましたので、その代わりとして、厚生労働省が提供する「NDB オープンデータ」をオープン化した話について、ブログを書こうと思います。 NDB オープンデータとは? www.mhlw.go.jp 作成の背景 ◆ レセプト情報・特定健診等情報データベース(NDB)は、悉皆性が高いレセプト情報、および検査値などの詳細な情報を有する特定健診等情報が含まれており、国民の医療動向を評価するうえで有用なデータだと考えられている。 ◆ 2011 年度より、医療費適正化計画策定に資する目的以外での NDB データの利用が認められたが、NDB データの機微性の高さに鑑み、利用者に対しては高いレベルのセキュリティ要件を課したうえで、データ提供が行われてきた。 ◆ 一方で、多くの研究者が必ずしも詳細な個票データを必要とするわけではないため、多くの人々が使用できるような、あらかじめ定式化された集計データを NDB データをもとに整備することが重要ではないか、という議論が有識者会議等でなされてきた。 ◆ NDB の民間提供に関する議論でも、「レセプト情報等の提供に関するワーキンググループ」からの報告では、汎用性が高く様々なニーズに一定程度応えうる基礎的な集計表を作成し、公表していくことがむしろ適当である、という指摘がみられた。 作成の目的 ◆ 多くの人々が NDB データに基づいた保健医療に関する知見に接することが出来るよう、NDB データを用いて基礎的な集計表を作成したうえで、公表する。 ◆ NDB データに基づき、医療の提供実態や特定健診等の結果をわかりやすく示す。 要は皆さんが、病院に行った時にもらう明細書に記載されている初診〇〇点、外来診療料〇〇点のようなデータが個人情報が匿名化された状態で収集しその統計データを一般に公開する、といったところでしょうか。 このようなデータがオープンになっていることはとても意義のあることだと思いますし、公開にまでこぎつけた関係者の苦労が想像されます。しかし、このような画期的なデータ提供ではありますが、Excel ファイルでの提供となっており、かつ加工がしづらいデータ構造になっているため、データを細かくみてみようとすると非常に手間がかかるという問題があります。 NDB オープンデータのオープン化 そこで NDB オープンデータとして公開されている Excel ファイルを加工し、DB に格納し BI ツール( Redash )から参照させるようにしてみました。 1. データ加工 & DB 取り込み 公開サイト にある医科診療行為に関する Excel ファイルを取得し、ログテーブルとしてよくあるフォーマットに変換し DB に取り込む。 変換前 変換後 *************************** 1. row *************************** id: 1 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: all revision: 2014 prefecture: sex: age: score: 251700771 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 *************************** 2. row *************************** id: 2 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: sex_age revision: 2014 prefecture: sex: 男性 age: 0~4 歳 score: 13158090 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 *************************** 3. row *************************** id: 3 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: sex_age revision: 2014 prefecture: sex: 男性 age: 5~9 歳 score: 12444947 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 2. データの参照 変換したデータを取り込んだ DB を Redash から参照。分析したいデータを取得するためのクエリを書いてダッシュボード化。 NDB オープンデータの活用例 以下に簡単なデータ活用のサンプルを載せました。医薬診療行為だけでなく特定健診や薬剤のデータを使うともう少し面白い気付きがあるかもしれません。 いずれにせよ、このように加工可能な形でのデータ提供こそがオープンデータ提供の価値だと思うので、このような仕組みが加速すれば良いなと思います。 0-4 歳 男性 診療行為点数 90 歳以上 男性 診療行為点数 140023350 胃瘻より流動食点滴注入 都道府県別 150086210 角膜移植術 年齡別 まとめ 以上、NDB オープンデータをオープン化してみた話について書いてみました。 このように.go.jp から提供されるデータは一般的に Excel や PDF でのファイル提供が基本で、インターネットサービスのように API のような形で提供されることはありません。せっかく貴重なデータが提供されているにも関わらず、それが IT システムと連動しづらいことで、活用されない状況になっているのはとても残念なことに思います。 Code for America の事例ではないですが、もっとインターネット系の人材がこのような取り組みに入り込んでいくようになれば、より合理的でスマートな仕組みが加速し、業界全体の IT 化も加速するのではないでしょうか。 お知らせ メドレーでは、医師たちがつくるオンライン医療事典「 MEDLEY 」、オンライン診療アプリ「 CLINICS 」、医療介護の求人サイト「 ジョブメドレー 」、口コミで探せる介護施設の検索サイト「 介護のほんね 」などのプロダクトを提供しています。これらのサービスの拡大を受けて、その成長を支えるエンジニア・デザイナーを募集しています。 メドレーで一緒に医療体験を変えるプロダクト作りに関わりたい方のご連絡お待ちしております。 www.medley.jp
開発本部の平山です。先日、社内勉強会「TechLunch」にて社外に公開できない内容の発表をしてしまいましたので、その代わりとして、厚生労働省が提供する「NDB オープンデータ」をオープン化した話について、ブログを書こうと思います。 NDB オープンデータとは? www.mhlw.go.jp 作成の背景 ◆ レセプト情報・特定健診等情報データベース(NDB)は、悉皆性が高いレセプト情報、および検査値などの詳細な情報を有する特定健診等情報が含まれており、国民の医療動向を評価するうえで有用なデータだと考えられている。 ◆ 2011 年度より、医療費適正化計画策定に資する目的以外での NDB データの利用が認められたが、NDB データの機微性の高さに鑑み、利用者に対しては高いレベルのセキュリティ要件を課したうえで、データ提供が行われてきた。 ◆ 一方で、多くの研究者が必ずしも詳細な個票データを必要とするわけではないため、多くの人々が使用できるような、あらかじめ定式化された集計データを NDB データをもとに整備することが重要ではないか、という議論が有識者会議等でなされてきた。 ◆ NDB の民間提供に関する議論でも、「レセプト情報等の提供に関するワーキンググループ」からの報告では、汎用性が高く様々なニーズに一定程度応えうる基礎的な集計表を作成し、公表していくことがむしろ適当である、という指摘がみられた。 作成の目的 ◆ 多くの人々が NDB データに基づいた保健医療に関する知見に接することが出来るよう、NDB データを用いて基礎的な集計表を作成したうえで、公表する。 ◆ NDB データに基づき、医療の提供実態や特定健診等の結果をわかりやすく示す。 要は皆さんが、病院に行った時にもらう明細書に記載されている初診〇〇点、外来診療料〇〇点のようなデータが個人情報が匿名化された状態で収集しその統計データを一般に公開する、といったところでしょうか。 このようなデータがオープンになっていることはとても意義のあることだと思いますし、公開にまでこぎつけた関係者の苦労が想像されます。しかし、このような画期的なデータ提供ではありますが、Excel ファイルでの提供となっており、かつ加工がしづらいデータ構造になっているため、データを細かくみてみようとすると非常に手間がかかるという問題があります。 NDB オープンデータのオープン化 そこで NDB オープンデータとして公開されている Excel ファイルを加工し、DB に格納し BI ツール( Redash )から参照させるようにしてみました。 1. データ加工 & DB 取り込み 公開サイト にある医科診療行為に関する Excel ファイルを取得し、ログテーブルとしてよくあるフォーマットに変換し DB に取り込む。 変換前 変換後 *************************** 1. row *************************** id: 1 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: all revision: 2014 prefecture: sex: age: score: 251700771 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 *************************** 2. row *************************** id: 2 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: sex_age revision: 2014 prefecture: sex: 男性 age: 0~4 歳 score: 13158090 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 *************************** 3. row *************************** id: 3 practice_category_code: A000 practice_category_name: 初診料 practice_code: 111000110 practice_name: 初診 practice_type: 外来 target: sex_age revision: 2014 prefecture: sex: 男性 age: 5~9 歳 score: 12444947 created_at: 0000-00-00 00:00:00 updated_at: 0000-00-00 00:00:00 2. データの参照 変換したデータを取り込んだ DB を Redash から参照。分析したいデータを取得するためのクエリを書いてダッシュボード化。 NDB オープンデータの活用例 以下に簡単なデータ活用のサンプルを載せました。医薬診療行為だけでなく特定健診や薬剤のデータを使うともう少し面白い気付きがあるかもしれません。 いずれにせよ、このように加工可能な形でのデータ提供こそがオープンデータ提供の価値だと思うので、このような仕組みが加速すれば良いなと思います。 0-4 歳 男性 診療行為点数 90 歳以上 男性 診療行為点数 140023350 胃瘻より流動食点滴注入 都道府県別 150086210 角膜移植術 年齡別 まとめ 以上、NDB オープンデータをオープン化してみた話について書いてみました。 このように.go.jp から提供されるデータは一般的に Excel や PDF でのファイル提供が基本で、インターネットサービスのように API のような形で提供されることはありません。せっかく貴重なデータが提供されているにも関わらず、それが IT システムと連動しづらいことで、活用されない状況になっているのはとても残念なことに思います。 Code for America の事例ではないですが、もっとインターネット系の人材がこのような取り組みに入り込んでいくようになれば、より合理的でスマートな仕組みが加速し、業界全体の IT 化も加速するのではないでしょうか。 お知らせ メドレーでは、医師たちがつくるオンライン医療事典「 MEDLEY 」、オンライン診療アプリ「 CLINICS 」、医療介護の求人サイト「 ジョブメドレー 」、口コミで探せる介護施設の検索サイト「 介護のほんね 」などのプロダクトを提供しています。これらのサービスの拡大を受けて、その成長を支えるエンジニア・デザイナーを募集しています。 メドレーで一緒に医療体験を変えるプロダクト作りに関わりたい方のご連絡お待ちしております。 www.medley.jp
ビールが美味しい季節ですね! 最近飲みすぎて嫁に叱られて、飲み会自粛中のデザイナー・ マエダ です。 メドレーでは TechLunch という社内勉強会を実施しているのですが、デザインについて私も発表する機会をいただきましたので、その内容を紹介させていただきます。テーマは「DLS の導入について」です。発表資料は記事の最後をご覧ください。 DLS(デザイン言語システム)とは DLS とは DesignLanguageSystem の略で、すごい単純にいえばデザインガイドラインみたいに UI に一貫性をもたせるため、配色やレイアウト、タイポグラフィやマージンなどのルールを策定するもの です。 私が主に担当しているオンライン診療アプリ「 CLINICS 」は、iOS、Android、Web と 3 つのプラットフォームで運用しているのですが、入社した当初はプラットフォーム毎に違った UI やルールで開発しており、サービスとして一貫性のあるサービス体験を提供できるとは言えない状況でした。また新たに機能を追加する際、それぞれ違なるデザインをしなければならず、デザイン作業においても負荷がかかっていました。 DLS が必要な理由 CLINICS ではプラットフォームごとに異なる UI を提供していたため、一貫したサービス品質をユーザーに提供できていないこと、開発者ごとに UI に対して認識にズレが生じていたことが課題でした。それに伴い開発速度も決して速いとは言えず、どうにか一定の品質を担保しつつ開発スピードも改善できないかと悩んでいたところ、Airbnb の開発者ブログで Airbnb Design System という記事を見かけました。 これまでのデザインガイドラインは単にカラーやマージンの定義を取り決めるだけだったのですが、 Airbnb ではデザイン言語として定義し、他の言語と同じようにチームと共有し、エンジニア・デザイナー同士で理解できる設計を作り上げている といった内容でした。 ※参考 medium.com 私がデザイナーとしてサービスデザインに携わる重要な役割のひとつとして、単にデザインをするだけでなく デザインを通して UI 設計の制約をつくり、継続的に運用しやすいプロダクトに仕上げること があると思っています。 DLS を起点として、各プラットフォームの開発者が共通の認識でシステム開発が行えれば、これまで以上にスピーディが開発が行え、一貫性のある体験をユーザーに提供できるプロダクトにできるはずだと考え、CLINICS 独自の DLS を開発することにしました。 CLINICS の DLS の一部 DLS を導入してどうなったか CLINICS では、Android、iOS、web で担当するエンジニアが異なるのですが、DLS を設計しシステムの詳細を共有することで、UI に対しての共通認識が生まれ、一貫した品質を担保できるようになりました。さらにこれまでエンジニアだけでデザインを考えて悩んでいた時間を、コンポーネント設計で組み立てたデザインを DLS で定義したことで、UI に悩むことなく機能ロジックに重点を置いた開発に専念できるようになったのではないかと思います。 デザイン言語でサービス設計の基礎を築けたことで、開発だけに追われていた状況から、より良いサービスを作るためにはどんな UX をユーザーに提供すべきかという声がエンジニアからも頻繁に声が上がりはじめたことも良かった点です。 エンジニア陣が UI について熱い議論を交わしている様子 TechLunch では、こうした内容について実際に作ったコンポーネント設計なども見せながらお話しました。発表資料はこちら。 speakerdeck.com まとめ DLS 導入以前は、エンジニアが開発に追われていたということもあり、プラットフォーム毎に議論ができていなかったエンジニアがお互いの担当プラットフォームを意識したコミュニケーションがとれるようになったことは予想外に良かった点です(別に仲が悪かったとかそういうことではなく w)。 さらに DLS で UI の基盤をつくったことで、デザイナーが手を動かさずともコンポーネントの組み合わせを話し合うだけで、エンジニア完結で一貫した品質で機能実装できるようになりました。これにより私も次の施策やプロジェクトに専念できるようになり、効率的に仕事ができるようになりました。 まだデザインルールに一貫性がないプロジェクトを担当しているデザイナーやエンジニアは、ぜひ DLS の導入を検討してみてはいかがでしょうか。 単にデザイン品質だけでなく、チームコミュニケーションも改善されるとおもいます。 より詳しく話を聞きたいかたは、気軽に「 話を聞きに行きたい 」をクリックしてみてください。ビールを飲みながらデザイン談義をしましょう!(嫁に怒られない程度に w) メドレー開発本部について、もっと詳しく知りたい方はこちらからどうぞ。 www.medley.jp www.wantedly.com
ビールが美味しい季節ですね! 最近飲みすぎて嫁に叱られて、飲み会自粛中のデザイナー・ マエダ です。 メドレーでは TechLunch という社内勉強会を実施しているのですが、デザインについて私も発表する機会をいただきましたので、その内容を紹介させていただきます。テーマは「DLS の導入について」です。発表資料は記事の最後をご覧ください。 DLS(デザイン言語システム)とは DLS とは DesignLanguageSystem の略で、すごい単純にいえばデザインガイドラインみたいに UI に一貫性をもたせるため、配色やレイアウト、タイポグラフィやマージンなどのルールを策定するもの です。 私が主に担当しているオンライン診療アプリ「 CLINICS 」は、iOS、Android、Web と 3 つのプラットフォームで運用しているのですが、入社した当初はプラットフォーム毎に違った UI やルールで開発しており、サービスとして一貫性のあるサービス体験を提供できるとは言えない状況でした。また新たに機能を追加する際、それぞれ違なるデザインをしなければならず、デザイン作業においても負荷がかかっていました。 DLS が必要な理由 CLINICS ではプラットフォームごとに異なる UI を提供していたため、一貫したサービス品質をユーザーに提供できていないこと、開発者ごとに UI に対して認識にズレが生じていたことが課題でした。それに伴い開発速度も決して速いとは言えず、どうにか一定の品質を担保しつつ開発スピードも改善できないかと悩んでいたところ、Airbnb の開発者ブログで Airbnb Design System という記事を見かけました。 これまでのデザインガイドラインは単にカラーやマージンの定義を取り決めるだけだったのですが、 Airbnb ではデザイン言語として定義し、他の言語と同じようにチームと共有し、エンジニア・デザイナー同士で理解できる設計を作り上げている といった内容でした。 ※参考 medium.com 私がデザイナーとしてサービスデザインに携わる重要な役割のひとつとして、単にデザインをするだけでなく デザインを通して UI 設計の制約をつくり、継続的に運用しやすいプロダクトに仕上げること があると思っています。 DLS を起点として、各プラットフォームの開発者が共通の認識でシステム開発が行えれば、これまで以上にスピーディが開発が行え、一貫性のある体験をユーザーに提供できるプロダクトにできるはずだと考え、CLINICS 独自の DLS を開発することにしました。 CLINICS の DLS の一部 DLS を導入してどうなったか CLINICS では、Android、iOS、web で担当するエンジニアが異なるのですが、DLS を設計しシステムの詳細を共有することで、UI に対しての共通認識が生まれ、一貫した品質を担保できるようになりました。さらにこれまでエンジニアだけでデザインを考えて悩んでいた時間を、コンポーネント設計で組み立てたデザインを DLS で定義したことで、UI に悩むことなく機能ロジックに重点を置いた開発に専念できるようになったのではないかと思います。 デザイン言語でサービス設計の基礎を築けたことで、開発だけに追われていた状況から、より良いサービスを作るためにはどんな UX をユーザーに提供すべきかという声がエンジニアからも頻繁に声が上がりはじめたことも良かった点です。 エンジニア陣が UI について熱い議論を交わしている様子 TechLunch では、こうした内容について実際に作ったコンポーネント設計なども見せながらお話しました。発表資料はこちら。 speakerdeck.com まとめ DLS 導入以前は、エンジニアが開発に追われていたということもあり、プラットフォーム毎に議論ができていなかったエンジニアがお互いの担当プラットフォームを意識したコミュニケーションがとれるようになったことは予想外に良かった点です(別に仲が悪かったとかそういうことではなく w)。 さらに DLS で UI の基盤をつくったことで、デザイナーが手を動かさずともコンポーネントの組み合わせを話し合うだけで、エンジニア完結で一貫した品質で機能実装できるようになりました。これにより私も次の施策やプロジェクトに専念できるようになり、効率的に仕事ができるようになりました。 まだデザインルールに一貫性がないプロジェクトを担当しているデザイナーやエンジニアは、ぜひ DLS の導入を検討してみてはいかがでしょうか。 単にデザイン品質だけでなく、チームコミュニケーションも改善されるとおもいます。 より詳しく話を聞きたいかたは、気軽に「 話を聞きに行きたい 」をクリックしてみてください。ビールを飲みながらデザイン談義をしましょう!(嫁に怒られない程度に w) メドレー開発本部について、もっと詳しく知りたい方はこちらからどうぞ。 www.medley.jp www.wantedly.com
ビールが美味しい季節ですね! 最近飲みすぎて嫁に叱られて、飲み会自粛中のデザイナー・ マエダ です。 メドレーでは TechLunch という社内勉強会を実施しているのですが、デザインについて私も発表する機会をいただきましたので、その内容を紹介させていただきます。テーマは「DLS の導入について」です。発表資料は記事の最後をご覧ください。 DLS(デザイン言語システム)とは DLS とは DesignLanguageSystem の略で、すごい単純にいえばデザインガイドラインみたいに UI に一貫性をもたせるため、配色やレイアウト、タイポグラフィやマージンなどのルールを策定するもの です。 私が主に担当しているオンライン診療アプリ「 CLINICS 」は、iOS、Android、Web と 3 つのプラットフォームで運用しているのですが、入社した当初はプラットフォーム毎に違った UI やルールで開発しており、サービスとして一貫性のあるサービス体験を提供できるとは言えない状況でした。また新たに機能を追加する際、それぞれ違なるデザインをしなければならず、デザイン作業においても負荷がかかっていました。 DLS が必要な理由 CLINICS ではプラットフォームごとに異なる UI を提供していたため、一貫したサービス品質をユーザーに提供できていないこと、開発者ごとに UI に対して認識にズレが生じていたことが課題でした。それに伴い開発速度も決して速いとは言えず、どうにか一定の品質を担保しつつ開発スピードも改善できないかと悩んでいたところ、Airbnb の開発者ブログで Airbnb Design System という記事を見かけました。 これまでのデザインガイドラインは単にカラーやマージンの定義を取り決めるだけだったのですが、 Airbnb ではデザイン言語として定義し、他の言語と同じようにチームと共有し、エンジニア・デザイナー同士で理解できる設計を作り上げている といった内容でした。 ※参考 medium.com 私がデザイナーとしてサービスデザインに携わる重要な役割のひとつとして、単にデザインをするだけでなく デザインを通して UI 設計の制約をつくり、継続的に運用しやすいプロダクトに仕上げること があると思っています。 DLS を起点として、各プラットフォームの開発者が共通の認識でシステム開発が行えれば、これまで以上にスピーディが開発が行え、一貫性のある体験をユーザーに提供できるプロダクトにできるはずだと考え、CLINICS 独自の DLS を開発することにしました。 CLINICS の DLS の一部 DLS を導入してどうなったか CLINICS では、Android、iOS、web で担当するエンジニアが異なるのですが、DLS を設計しシステムの詳細を共有することで、UI に対しての共通認識が生まれ、一貫した品質を担保できるようになりました。さらにこれまでエンジニアだけでデザインを考えて悩んでいた時間を、コンポーネント設計で組み立てたデザインを DLS で定義したことで、UI に悩むことなく機能ロジックに重点を置いた開発に専念できるようになったのではないかと思います。 デザイン言語でサービス設計の基礎を築けたことで、開発だけに追われていた状況から、より良いサービスを作るためにはどんな UX をユーザーに提供すべきかという声がエンジニアからも頻繁に声が上がりはじめたことも良かった点です。 エンジニア陣が UI について熱い議論を交わしている様子 TechLunch では、こうした内容について実際に作ったコンポーネント設計なども見せながらお話しました。発表資料はこちら。 speakerdeck.com まとめ DLS 導入以前は、エンジニアが開発に追われていたということもあり、プラットフォーム毎に議論ができていなかったエンジニアがお互いの担当プラットフォームを意識したコミュニケーションがとれるようになったことは予想外に良かった点です(別に仲が悪かったとかそういうことではなく w)。 さらに DLS で UI の基盤をつくったことで、デザイナーが手を動かさずともコンポーネントの組み合わせを話し合うだけで、エンジニア完結で一貫した品質で機能実装できるようになりました。これにより私も次の施策やプロジェクトに専念できるようになり、効率的に仕事ができるようになりました。 まだデザインルールに一貫性がないプロジェクトを担当しているデザイナーやエンジニアは、ぜひ DLS の導入を検討してみてはいかがでしょうか。 単にデザイン品質だけでなく、チームコミュニケーションも改善されるとおもいます。 より詳しく話を聞きたいかたは、気軽に「 話を聞きに行きたい 」をクリックしてみてください。ビールを飲みながらデザイン談義をしましょう!(嫁に怒られない程度に w) メドレー開発本部について、もっと詳しく知りたい方はこちらからどうぞ。 www.medley.jp www.wantedly.com
ビールが美味しい季節ですね! 最近飲みすぎて嫁に叱られて、飲み会自粛中のデザイナー・ マエダ です。 メドレーでは TechLunch という社内勉強会を実施しているのですが、デザインについて私も発表する機会をいただきましたので、その内容を紹介させていただきます。テーマは「DLS の導入について」です。発表資料は記事の最後をご覧ください。 DLS(デザイン言語システム)とは DLS とは DesignLanguageSystem の略で、すごい単純にいえばデザインガイドラインみたいに UI に一貫性をもたせるため、配色やレイアウト、タイポグラフィやマージンなどのルールを策定するもの です。 私が主に担当しているオンライン診療アプリ「 CLINICS 」は、iOS、Android、Web と 3 つのプラットフォームで運用しているのですが、入社した当初はプラットフォーム毎に違った UI やルールで開発しており、サービスとして一貫性のあるサービス体験を提供できるとは言えない状況でした。また新たに機能を追加する際、それぞれ違なるデザインをしなければならず、デザイン作業においても負荷がかかっていました。 DLS が必要な理由 CLINICS ではプラットフォームごとに異なる UI を提供していたため、一貫したサービス品質をユーザーに提供できていないこと、開発者ごとに UI に対して認識にズレが生じていたことが課題でした。それに伴い開発速度も決して速いとは言えず、どうにか一定の品質を担保しつつ開発スピードも改善できないかと悩んでいたところ、Airbnb の開発者ブログで Airbnb Design System という記事を見かけました。 これまでのデザインガイドラインは単にカラーやマージンの定義を取り決めるだけだったのですが、 Airbnb ではデザイン言語として定義し、他の言語と同じようにチームと共有し、エンジニア・デザイナー同士で理解できる設計を作り上げている といった内容でした。 ※参考 medium.com 私がデザイナーとしてサービスデザインに携わる重要な役割のひとつとして、単にデザインをするだけでなく デザインを通して UI 設計の制約をつくり、継続的に運用しやすいプロダクトに仕上げること があると思っています。 DLS を起点として、各プラットフォームの開発者が共通の認識でシステム開発が行えれば、これまで以上にスピーディが開発が行え、一貫性のある体験をユーザーに提供できるプロダクトにできるはずだと考え、CLINICS 独自の DLS を開発することにしました。 CLINICS の DLS の一部 DLS を導入してどうなったか CLINICS では、Android、iOS、web で担当するエンジニアが異なるのですが、DLS を設計しシステムの詳細を共有することで、UI に対しての共通認識が生まれ、一貫した品質を担保できるようになりました。さらにこれまでエンジニアだけでデザインを考えて悩んでいた時間を、コンポーネント設計で組み立てたデザインを DLS で定義したことで、UI に悩むことなく機能ロジックに重点を置いた開発に専念できるようになったのではないかと思います。 デザイン言語でサービス設計の基礎を築けたことで、開発だけに追われていた状況から、より良いサービスを作るためにはどんな UX をユーザーに提供すべきかという声がエンジニアからも頻繁に声が上がりはじめたことも良かった点です。 エンジニア陣が UI について熱い議論を交わしている様子 TechLunch では、こうした内容について実際に作ったコンポーネント設計なども見せながらお話しました。発表資料はこちら。 speakerdeck.com まとめ DLS 導入以前は、エンジニアが開発に追われていたということもあり、プラットフォーム毎に議論ができていなかったエンジニアがお互いの担当プラットフォームを意識したコミュニケーションがとれるようになったことは予想外に良かった点です(別に仲が悪かったとかそういうことではなく w)。 さらに DLS で UI の基盤をつくったことで、デザイナーが手を動かさずともコンポーネントの組み合わせを話し合うだけで、エンジニア完結で一貫した品質で機能実装できるようになりました。これにより私も次の施策やプロジェクトに専念できるようになり、効率的に仕事ができるようになりました。 まだデザインルールに一貫性がないプロジェクトを担当しているデザイナーやエンジニアは、ぜひ DLS の導入を検討してみてはいかがでしょうか。 単にデザイン品質だけでなく、チームコミュニケーションも改善されるとおもいます。 より詳しく話を聞きたいかたは、気軽に「 話を聞きに行きたい 」をクリックしてみてください。ビールを飲みながらデザイン談義をしましょう!(嫁に怒られない程度に w) メドレー開発本部について、もっと詳しく知りたい方はこちらからどうぞ。 www.medley.jp www.wantedly.com
ビールが美味しい季節ですね! 最近飲みすぎて嫁に叱られて、飲み会自粛中のデザイナー・ マエダ です。 メドレーでは TechLunch という社内勉強会を実施しているのですが、デザインについて私も発表する機会をいただきましたので、その内容を紹介させていただきます。テーマは「DLS の導入について」です。発表資料は記事の最後をご覧ください。 DLS(デザイン言語システム)とは DLS とは DesignLanguageSystem の略で、すごい単純にいえばデザインガイドラインみたいに UI に一貫性をもたせるため、配色やレイアウト、タイポグラフィやマージンなどのルールを策定するもの です。 私が主に担当しているオンライン診療アプリ「 CLINICS 」は、iOS、Android、Web と 3 つのプラットフォームで運用しているのですが、入社した当初はプラットフォーム毎に違った UI やルールで開発しており、サービスとして一貫性のあるサービス体験を提供できるとは言えない状況でした。また新たに機能を追加する際、それぞれ違なるデザインをしなければならず、デザイン作業においても負荷がかかっていました。 DLS が必要な理由 CLINICS ではプラットフォームごとに異なる UI を提供していたため、一貫したサービス品質をユーザーに提供できていないこと、開発者ごとに UI に対して認識にズレが生じていたことが課題でした。それに伴い開発速度も決して速いとは言えず、どうにか一定の品質を担保しつつ開発スピードも改善できないかと悩んでいたところ、Airbnb の開発者ブログで Airbnb Design System という記事を見かけました。 これまでのデザインガイドラインは単にカラーやマージンの定義を取り決めるだけだったのですが、 Airbnb ではデザイン言語として定義し、他の言語と同じようにチームと共有し、エンジニア・デザイナー同士で理解できる設計を作り上げている といった内容でした。 ※参考 medium.com 私がデザイナーとしてサービスデザインに携わる重要な役割のひとつとして、単にデザインをするだけでなく デザインを通して UI 設計の制約をつくり、継続的に運用しやすいプロダクトに仕上げること があると思っています。 DLS を起点として、各プラットフォームの開発者が共通の認識でシステム開発が行えれば、これまで以上にスピーディが開発が行え、一貫性のある体験をユーザーに提供できるプロダクトにできるはずだと考え、CLINICS 独自の DLS を開発することにしました。 CLINICS の DLS の一部 DLS を導入してどうなったか CLINICS では、Android、iOS、web で担当するエンジニアが異なるのですが、DLS を設計しシステムの詳細を共有することで、UI に対しての共通認識が生まれ、一貫した品質を担保できるようになりました。さらにこれまでエンジニアだけでデザインを考えて悩んでいた時間を、コンポーネント設計で組み立てたデザインを DLS で定義したことで、UI に悩むことなく機能ロジックに重点を置いた開発に専念できるようになったのではないかと思います。 デザイン言語でサービス設計の基礎を築けたことで、開発だけに追われていた状況から、より良いサービスを作るためにはどんな UX をユーザーに提供すべきかという声がエンジニアからも頻繁に声が上がりはじめたことも良かった点です。 エンジニア陣が UI について熱い議論を交わしている様子 TechLunch では、こうした内容について実際に作ったコンポーネント設計なども見せながらお話しました。発表資料はこちら。 speakerdeck.com まとめ DLS 導入以前は、エンジニアが開発に追われていたということもあり、プラットフォーム毎に議論ができていなかったエンジニアがお互いの担当プラットフォームを意識したコミュニケーションがとれるようになったことは予想外に良かった点です(別に仲が悪かったとかそういうことではなく w)。 さらに DLS で UI の基盤をつくったことで、デザイナーが手を動かさずともコンポーネントの組み合わせを話し合うだけで、エンジニア完結で一貫した品質で機能実装できるようになりました。これにより私も次の施策やプロジェクトに専念できるようになり、効率的に仕事ができるようになりました。 まだデザインルールに一貫性がないプロジェクトを担当しているデザイナーやエンジニアは、ぜひ DLS の導入を検討してみてはいかがでしょうか。 単にデザイン品質だけでなく、チームコミュニケーションも改善されるとおもいます。 より詳しく話を聞きたいかたは、気軽に「 話を聞きに行きたい 」をクリックしてみてください。ビールを飲みながらデザイン談義をしましょう!(嫁に怒られない程度に w) メドレー開発本部について、もっと詳しく知りたい方はこちらからどうぞ。 www.medley.jp www.wantedly.com