10 分で書ける cloud foundry route service

36
10 分で書ける Cloud Foundry Route Service @33PaaS勉強会 2016/08/02 Hiroaki Ukaji

Upload: hiroakiukaji

Post on 06-Jan-2017

382 views

Category:

Engineering


0 download

TRANSCRIPT

10分で書けるCloudFoundryRouteService

@第33回PaaS勉強会2016/08/02HiroakiUkaji

今回のテーマ

CloudFoundryRouteService

RouteServiceって何?

※知ってる!って方は聞き流して大丈夫です

RouteService@公式

Introduction  

CloudFoundryapplicaAondevelopersmaywishtoapplytransformaAonorprocessingtorequestsbeforetheyreachanapplicaAon.ex.)authenAcaAon/ratelimiAng/cachingservices

AppへのRequest到達前に何か処理加えたくない?

RouteServiceって何

CloudFoundryRouteService

RouteServiceって何

CloudFoundryRouteService

PaaS

RouteServiceって何

CloudFoundryRouteService

PaaS  

≒Appのソースを投げ込むと上手いこと動かしてくれる君

RouteServiceって何

CloudFoundryRouteService

(CloudFoundryにおいて) Appにくっついて     お仕事してくれる君

RouteServiceって何

CloudFoundryRouteService

(CloudFoundryにおいて) Appにくっついて     お仕事してくれる君

App MySQLService

RMQService

applicaAonservice

RouteServiceって何

CloudFoundryRouteService

(CloudFoundryにおいて) Appにくっついて     お仕事してくれる君

App MySQLService

RMQService

bind

applicaAonservice

RouteServiceって何

CloudFoundryRouteService

(CloudFoundryにおいて) Appにくっついて     お仕事してくれる君

RouteServiceって何

CloudFoundryRouteService

CloudFoundryで   ApplicaAonと一緒になって        Route関係の仕事をしてくれる君

アプリへのAccessRoute

Client LoadBalancer

CFRouter App

 CF

アプリを使う人ロードバランサあってもなくても

CFアプリCFの中で

アクセス割り振る人

()① ② ③

CloudFoundryRouteService

Client LoadBalancer

CFRouter App

 CF

RouteService

①②

CloudFoundryRouteService

Client LoadBalancer

CFRouter App

 CF

RouteService

①②

アプリへのRoute到達前に一旦自分を経由させる

CloudFoundryRouteService

Client LoadBalancer

CFRouter App

 CF

RouteService

①②

基本的に全てHTTPなので・・・

CloudFoundryRouteService

Client LoadBalancer

CFRouter App

 CF

RouteService

①②

RouteServiceの正体 = HTTPサーバ

デモ

hiroaki@HMP:~/demo$ tree.!"" hello#   !"" Staticfile#   !"" index.html#   %"" manifest.yml%"" s-rs !"" Godeps #   !"" Godeps.json #   !"" Readme #   %"" _workspace !"" Procfile !"" README.md !"" main.go %"" manifest.yml

4 directories, 9 files

Client LoadBalancer

CFRouter App

 CF

RouteService

hello/配下はこの後BackendのAppに、s-rs/配下はRoute-Serviceになる予定です。

ソースコードは下記Repositoryでも見ることができますh[ps://github.com/hiroakiukaji/simple-route-service-handson

hiroaki@HMP:~/demo$ cd hello/hiroaki@HMP:~/demo/hello$ lsStaticfile index.html manifest.ymlhiroaki@HMP:~/demo/hello$ cf pushUsing manifest file /Users/hiroaki/demo/hello/manifest.yml

Creating app staticapp in org ukaji_org / space ukaji_space as ukaji...OK

:::::

App started

OKApp staticapp was started using this command `sh boot.sh`

Showing health and status for app staticapp in org ukaji_org / space ukaji_space as ukaji...OK

requested state: startedinstances: 1/1usage: 256M x 1 instancesurls: staticapp.mcf.nttlabs.infolast uploaded: Mon Aug 8 02:36:03 UTC 2016stack: unknownbuildpack: staticfile 1.3.9

state since cpu memory disk details#0 running 2016-08-08 11:36:17 AM 0.0% 0 of 256M 0 of 1Ghiroaki@HMP:~/demo/hello$ curl staticapp.mcf.nttlabs.info(´・_・`)

Client LoadBalancer

CFRouter App

 CF

まずはBackendのアプリをデプロイ

hiroaki@HMP:~/demo/hello$ cd ../s-rs/hiroaki@HMP:~/demo/s-rs$ lsGodeps Procfile README.md main.go manifest.ymlhiroaki@HMP:~/demo/s-rs$ cf push

:::::

requested state: startedinstances: 1/1usage: 256M x 1 instancesurls: simple-rs.mcf.nttlabs.infolast uploaded: Mon Aug 8 04:19:13 UTC 2016stack: unknownbuildpack: go_buildpack

state since cpu memory disk details#0 running 2016-08-08 01:19:32 PM 0.0% 0 of 256M 0 of 1Ghiroaki@HMP:~/demo/s-rs$ cf create-user-provided-service simplerouteservice \ -r https://simple-rs.mcf.nttlabs.infoCreating user provided service simplerouteservice in org ukaji_org / space ukaji_space as ukaji...OKhiroaki@HMP:~/demo/s-rs$ cf servicesGetting services in org ukaji_org / space ukaji_space as ukaji...OK

name service plan bound apps last operationsimplerouteservice user-provided

RouteServiceとして使うHTTPサーバをデプロイ。(※)その後HTTPサーバをServiceとして認識させる。

※HTTPSで到達できる場所ならばどこでも構いませんが、今回はたまたまCloudFoundry上に同居させています。

Client LoadBalancer

CFRouter App

 CF

RouteService

 

hiroaki@HMP:~/demo/s-rs$ cf bind-route-service mcf.nttlabs.info simplerouteservice -n staticappBinding route staticapp.mcf.nttlabs.info to service instance simplerouteservice in org ukaji_org / space ukaji_space as ukaji...OKhiroaki@HMP:~/demo/s-rs$ curl staticapp.mcf.nttlabs.info(´・_・`) RouteServiceとしてバインドすれば完成。

Client LoadBalancer

CFRouter App

 CF

RouteService

 

hiroaki@HMP:~$ cf logs simple-rsConnected, tailing logs for app simple-rs in org ukaji_org / space ukaji_space as ukaji...

2016-08-08T13:36:58.24+0900 [RTR/0] OUT simple-rs.mcf.nttlabs.info - [08/08/2016:04:36:58.238 +0000] "GET / HTTP/1.0" 200 0 13 "-" "curl/7.43.0" 192.168.12.34:35667 x_forwarded_for:"192.168.10.40, 192.168.12.34, 192.168.13.51" x_forwarded_proto:"https" vcap_request_id:ab5cfd36-1548-4f95-7fb2-8c9fc7dc3262 response_time:0.008521804 app_id:2b11f3ec-d733-48e2-b141-5ac98020eee3

何も処理をしていないので振る舞いは変わりませんが、RouteServiceのアプリのログを見てみると何らかのHTTPアクセスが飛んでいることが分かるはず。

RouteServiceの実装

RouteServicebyGolangの実装

小構成で60行ぐらいpackage main

import (:)

type SimpleRoundTripper struct {transport http.RoundTripper

}

func newSimpleRoundTripper() *SimpleRoundTripper {transport := &http.Transport{

TLSClientConfig: &tls.Config{InsecureSkipVerify: skipSslValidation()},}return &SimpleRoundTripper{

transport: transport,}

}

func (s *SimpleRoundTripper) RoundTrip(request *http.Request) (*http.Response, error) {var response *http.Responsevar err errorresponse, err = s.transport.RoundTrip(request)if err != nil {

return nil, err}return response, err

}

func main() {http.Handle("/", newProxy())log.Fatal(http.ListenAndServe(":"+os.Getenv("PORT"), nil))

}

func newProxy() http.Handler {proxy := &httputil.ReverseProxy{

Director: func(r *http.Request) {url, err := url.Parse(r.Header.Get("X-Cf-Forwarded-Url"))if err != nil {

log.Fatalln(err.Error())}r.URL = urlr.Host = url.Host

},Transport: newSimpleRoundTripper(),

}return proxy

}

func skipSslValidation() bool {var skipSslValidation boolvar err errorif skipSslValidation, err = strconv.ParseBool(os.Getenv("SKIP_SSL_VALIDATION")); err != nil {

skipSslValidation = true}return skipSslValidation

}

RouteServicebyGolangの実装

Entrypoint

func main() {http.Handle("/", newProxy())

log.Fatal(http.ListenAndServe(":"+os.Getenv("PORT"), nil))}

GET / を待ち受けるただのHTTPサーバ

RouteServicebyGolangの実装

RouteServiceの本体を担うメソッド

func (s *SimpleRoundTripper) RoundTrip(request *http.Request) (*http.Response, error) {var response *http.Responsevar err error

response, err = s.transport.RoundTrip(request)if err != nil {

return nil, err}

return response, err}

あからさまにRequestを受けてResponseを返している人がいます

※この例は本当に素通しで何もしていません

RouteServicebyGolangの実装

RouteServiceの本体を担うメソッドを書いてみる

func (s *SimpleRoundTripper) RoundTrip(request *http.Request) (*http.Response, error) {var response *http.Responsevar err error

response, err = s.transport.RoundTrip(request)if err != nil {

return nil, err}

return response, err}

適当な処理を書いてResponseを投げ返してみましょう

こ の へ ん

デモ

hiroaki@HMP:~/demo/s-rs$ lsGodeps Procfile README.md main.go manifest.ymlhiroaki@HMP:~/demo/s-rs$ vi main.go

:

func (s *SimpleRoundTripper) RoundTrip(request *http.Request) (*http.Response, error) { var response *http.Response var err error

str := "_人人人人人_\n> (´・_・`) <\n ̄Y^Y^Y^Y^Y ̄\n" dummyResponse := &http.Response{ StatusCode: 200, Body: ioutil.NopCloser(bytes.NewBufferString(str)), } return dummyResponse, err

response, err = s.transport.RoundTrip(request) if err != nil { return nil, err } return response, err}

:

ダミーのHTTPレスポンスを生成して返してしまうだけのコードを追加

hiroaki@HMP:~/demo/s-rs$ cf push

:::::

requested state: startedinstances: 1/1usage: 256M x 1 instancesurls: simple-rs.mcf.nttlabs.infolast uploaded: Mon Aug 8 04:54:37 UTC 2016stack: unknownbuildpack: go_buildpack

state since cpu memory disk details#0 running 2016-08-08 01:55:10 PM 0.0% 3.2M of 256M 7.7M of 1Ghiroaki@HMP:~/demo/s-rs$ curl staticapp.mcf.nttlabs.info_人人人人人_> (´・_・`) <

 ̄Y^Y^Y^Y^Y ̄

コードを書き換えたので再デプロイ。HTTPサーバの中身が入れ替わるだけなので、Service登録のやり直し等は特に必要ありません。

Client LoadBalancer

CFRouter App

 CF

RouteService

 

hiroaki@HMP:~/demo/s-rs$ cf unbind-route-service mcf.nttlabs.info simplerouteservice -n staticapp -fUnbinding route staticapp.mcf.nttlabs.info from service instance simplerouteservice in org ukaji_org / space ukaji_space as ukaji...OKhiroaki@HMP:~/demo/s-rs$ curl staticapp.mcf.nttlabs.info(´・_・`)hiroaki@HMP:~/demo/s-rs$ cf bind-route-service mcf.nttlabs.info simplerouteservice -n staticappBinding route staticapp.mcf.nttlabs.info to service instance simplerouteservice in org ukaji_org / space ukaji_space as ukaji...OKhiroaki@HMP:~/demo/s-rs$ curl staticapp.mcf.nttlabs.info_人人人人人_> (´・_・`) < ̄Y^Y^Y^Y^Y ̄

今度はRouteServiceのbind/unbind毎にHTTPレスポンスの差を視認できるはず。

Client LoadBalancer

CFRouter App

 CF

RouteService

①②

Q.何か余計なアクセスぐるぐるしてるけど性能的にどうなんですか?

A.落ちます。

こ の へ ん

RouteService無し 素通しRouteService

1000REQ/1par 124.11 34.04

1000REQ/5par 512.31 118.04

1000REQ/10par 793.65 174.64

1000REQ/20par 1377.21 207.25

VS

RouteService無し 素通しRouteService

ただし・・・

A.落ちます。ただし、

今回の実験ではRouteServiceもCloudFoundry上に同居

A.落ちます。ただし、

諸事情により採用したアーキテクチャがnetworkhop嵩む系

FullyBrokered StaAcBrokered UserProvided

今回はこれ

使う側が超楽◯

× 経路増加大

経路に無駄がない◯

× インフラ構成要変更

お手軽◯

× 経路増加大

公式RouteServiceArchitecture3パターン

まとめ

•  CloudFoundryRouteService =CFアプリへのリクエストに処理を加えるService

–  実体はほぼただのHTTPサーバ–  ソースコードは平易なので一読がおすすめ–  性能は当然落ちるので導入要否は各自検証

参考

RouteServices|CloudFoundryDocs

h[ps://github.com/cloudfoundry-samples/logging-route-service

h[ps://github.com/cloudfoundry-samples/ratelimit-serviceh[ps://docs.cloudfoundry.org/services/route-services.html

Github:cloudfoundry-samples/ratelimit-service

Github:cloudfoundry-samples/logging-route-service

h[p://www.slideshare.net/gwennetourneau/cloud-foundry-meetup-tokyo-1-route-service

CloudFoundryMeetupTokyo#1RouteService