ããã«ã¡ã¯ãNecoãã¼ã ã®æ± æ·»ï¼@zoetroï¼ã§ãã
gofailã¯ãetcdã®éçºãã¼ã ãã¤ãã£ãFailure Injectionã®ããã®ãã¼ã«ã§ãã Goè¨èªã§æ¸ãããããã°ã©ã ä¸ã«æ æã«ã¨ã©ã¼ãçºçããããã¤ã³ã(failpoint)ãåãè¾¼ã¿ãä»»æã®ã¿ã¤ãã³ã°ã§ããã°ã©ã ã®æåãå¤ãããã¨ãã§ãã¾ãã å ¬å¼ããã¥ã¡ã³ãã«è¨è¼ããã¦ããªãé ç®ãå¤ã ããã®ã§ã詳ãã使ãæ¹ãç´¹ä»ãããã¨æãã¾ãã
ãªããæ¬è¨äºã¯2018å¹´8ææç¹ã®ã½ã¼ã¹ã³ã¼ãã対象ã«è§£èª¬ãã¦ãã¾ãã
gofailã®ã¤ã³ã¹ãã¼ã«
gofail ãã¤ã³ã¹ãã¼ã«ãã¾ãã
$ go get -u github.com/etcd-io/gofail/...
failpointã®åãè¾¼ã¿
ããã°ã©ã ä¸ã«failpointãåãè¾¼ãããã«ã¯ãGoè¨èªã®ããã°ã©ã ä¸ã« gofail
ã¨ãããã¼ã¯ã¼ãããå§ã¾ãã³ã¡ã³ããè¨è¿°ãã¾ãã
ãªãããããã¯ã³ã¡ã³ãã®å ´åã¯failpointã¨ãã¦èªèãããªããããå¿
ãè¡ã³ã¡ã³ãã§è¨è¿°ããå¿
è¦ãããã¾ãã
ã³ã¡ã³ãã®1è¡ç®ã«ã¯ããªã¬ã¼ã¨ãªãå¤æ°å®ç¾©ãè¨è¿°ãã2è¡ç®ä»¥éã«ã¯failpointãæå¹åããæã«å®è¡ãããã³ã¼ããè¨è¿°ãããã¨ãã§ãã¾ãã è¤æ°è¡ã®å¦çãåãè¾¼ã¿ããå ´åã¯ã空è¡ããããã«ã³ã¡ã³ããè¨è¿°ãã¾ãã
ä¾ãã°ä»»æã®å¤ãè¿ããããªfailpointãåãè¾¼ã¿ããå ´åã¯ãä¸è¨ã®ããã«1è¡ç®ã«è¿ãå¤ã¨ãªãå¤æ°å®£è¨ã2è¡ç®ã«returnãè¨è¿°ãã¾ãã
func someFunc() string { // gofail: var SomeFuncString string // return SomeFuncString return "default" }
ãªããfailpointã¨ãªãå¤æ°ã®å㯠bool
, int
, string
, struct{}
ã®ã¿ã«ãªãã¾ãã
failçºçå¾ã«ä»»æã®å¦çãå®è¡ããå¿
è¦ããªãå ´å(panicãçºçãããå ´åãªã©)ã¯ã以ä¸ã®ããã« struct {}
åã®å¤æ°å®£è¨ã®ã¿ãè¨è¿°ãã¾ãã
func ExampleOneLineFunc() string { // gofail: var ExampleOneLine struct{} return "abc" }
failpointãæå¹åããæã«gotoãã©ãã«ä»ãcontinueæãå®è¡ãããå ´åã¯ãä¸è¨ã®ããã« gofail ã®å¾ãã«ã©ãã«åãè¨è¿°ãããã¨ãã§ãã¾ãã
func ExampleRetry() { // gofail: RETRY: for i := 0; ; i++ { fmt.Println(i) time.Sleep(time.Second) // gofail: var RetryLabel struct{} // goto RETRY } }
failpointãåãè¾¼ãã§ãã«ã
failpointãåãè¾¼ãã§ãã«ãããã«ã¯ãã¾ãä¸è¨ã®ã³ãã³ããå®è¡ãã¾ãã
$ gofail enable
ããã¨gofailããå§ã¾ãã³ã¡ã³ããè¨è¿°ããç®æãæ¸ãæãããã*.fail.go
ã¨ãããã¡ã¤ã«ãçæããã¾ãã
ãã¨ã¯çæãããã³ã¼ããå«ãã¦é常éãã«ãã«ããã¾ãã
æ¸ãæããããã³ã¼ãããã¨ã«æ»ãã«ã¯ã以ä¸ã®ã³ãã³ããå®è¡ãã¾ãã
$ gofail disable
failpointã®æå¹å
åãè¾¼ã¾ããfailpointã¯åæç¶æ ã§ã¯offã«ãªã£ã¦ããã®ã§ãå®éã«failãããããã«ã¯failpointã®æå¹åããããªãå¿ è¦ãããã¾ãã failpointãæå¹åãããæ段ã¨ãã¦ã¯ãããã°ã©ã ã®èµ·åæã«ç°å¢å¤æ°ã§æå®ãããHTTP APIã§æå¹åããã2éãã®æ¹æ³ãããã¾ãããããã§ã¯HTTP APIãå©ç¨ããæ¹æ³ãç´¹ä»ãã¾ãã
ã¾ãgofailã®ã¨ã³ããã¤ã³ããç°å¢å¤æ°ã§æå®ãã¦ããã°ã©ã ãèµ·åãã¾ãã
GOFAIL_HTTP="127.0.0.1:1234" ./cmd
ä¸è¨ã®APIãå©ãã¨ãfailpointã®ä¸è¦§ãåå¾ãããã¨ãã§ãã¾ãã
$ curl http://127.0.0.1:1234/ my/package/path/SomeFuncString= my/package/path/ExampleOneLine= my/package/path/ExampleLabels=
failpointãæå¹åããããã«ã¯ä¸è¨ã®APIãå®è¡ãã¾ãã
ããã§ã¯ãSomeFuncString
ã hello
ã¨ããæååãè¿ãããã«è¨å®ãã¦ãã¾ãã
$ curl http://127.0.0.1:1234/my/package/path/SomeFuncString -XPUT -d'return("hello")'
å度ä¸è¨ã®APIãå®è¡ããã¨ãfailpointãè¨å®ããã¦ãããã¨ã確èªã§ãã¾ãã
$ curl http://127.0.0.1:1234/ my/package/path/SomeFuncString=return("hello") my/package/path/ExampleOneLine= my/package/path/ExampleLabels=
ãã®ç¶æ
ã§someFunc()
é¢æ°ãå®è¡ãããã¨ãhello
ã¨ããæååãè¿ã£ã¦ããããã«ãªãã¾ãã
failpointãç¡å¹åããã«ã¯ä¸è¨ã®APIãå®è¡ãã¾ãã
$ curl http://127.0.0.1:1234/my/package/path/SomeFuncString -XDELETE
failpointã§å®è¡å¯è½ãªã¢ã¯ã·ã§ã³
failpointã«ã¯ãä¸è¨ã®ã¢ã¯ã·ã§ã³ãæå®ãããã¨ãã§ãã¾ãã
- off: failpointã®ç¡å¹å
- return: ä»»æã®å¤ãè¿ã(è¿ããã¨ã®ã§ããå㯠bool, int, string, struct{} ã®ã¿)
- sleep: ä¸å®æéå¾ ã¤(å¾ ã¡æéã¯Durationãã©ã¼ãããã§æå®å¯è½ãintã§æå®ããå ´åã¯ããªç§ã«ãªã)
- panic: panicãçºçããã
- break: ãããã¬ã«ããbreakãçºçããã
- print: æ¨æºåºåã«æååãåºåãã
ã¾ããfailãçºçãããåæ°ã確çãæå®ãããã¨ãã§ãã¾ãã
ä¸è¨ã®ä¾ã§ã¯ãfailpointãå¼ã³åºãããæåã®3åã¯hello
ã¨ããæååãè¿ãããã®å¾ã¯é常ã®ç¶æ
ã«æ»ãã¾ãã
$ curl http://127.0.0.1:1234/my/package/path/SomeFuncString -XPUT -d'3*return("hello")'
ä¸è¨ã®ä¾ã§ã¯ã50%ã®ç¢ºçã§hello
ãè¿ãããã«ãªãã¾ãã
$ curl http://127.0.0.1:1234/my/package/path/SomeFuncString -XPUT -d'50.0%return("hello")'
ãããã«
gofailãå©ç¨ããã¨ä»»æã®ã¿ã¤ãã³ã°ã§ã½ããã¦ã§ã¢ã®æåãå¤ãããã¨ãã§ããFailure Injection Testããããªãéã«ã¯ã¨ã¦ã便å©ãªã®ã§ããã²ä½¿ã£ã¦ã¿ã¦ãã ããã
æã ã¯gofailãå©ç¨ããèé害æ§è©¦é¨ãå®æ½ããä¿¡é ¼æ§ã®é«ãã¤ã³ãã©åºç¤ã®æ§ç¯ãé²ãã¦ãã¾ãã次åã®è¨äºã§ã¯ãã®ãããã詳ããç´¹ä»ãããã¨æãã¾ãã