ãã®è¨äºã¯MERPAY TECH OPENNESS MONTHã®10æ¥ç®ã®è¨äºã§ãã
ããã«ã¡ã¯ãã¡ã«ãã¤ã®ããã¯ã¨ã³ãã¨ã³ã¸ãã¢ã®æ´ç°ï¼@yoshiki_shibataï¼ã§ãã
ã¡ã«ãã¤ã®ããã¯ã¨ã³ãã¯ãGoogle Cloud Platformä¸ã§Google Kubernetes Engineã使ç¨ãã¦ããã¤ã¯ããµã¼ãã¹ã¢ã¼ããã¯ãã£ãæ¡ç¨ããå¤æ°ã®ãã¤ã¯ããµã¼ãã¹ããæ§æããã¦ãã¾ããã¢ããªã·ãã¯ãªãµã¼ãã¹å®è£ ã§ã¯è¤æ°å±¤ã®ã©ã¤ãã©ãªï¼ãããã¯ã³ã³ãã¼ãã³ãï¼ããæ§æãããã®ã«å¯¾ãã¦ããã¤ã¯ããµã¼ãã¹ã¢ã¼ããã¯ãã£ã§ã¯è¤æ°å±¤ã®ãã¤ã¯ããµã¼ãã¹ããæ§æããã¾ãã
ã©ã¡ãã®ã¢ã¼ããã¯ãã£ã«ããã¦ããå¶çºçããã°ã©ãã³ã°ï¼Programming by Coincidenceï¼1ãé¿ãã2ããã«ã注æãæã£ã¦ä½æããå¿ è¦ãããã®ããå¢çé¨åã®APIï¼Application Programming Interfaceï¼ä»æ§ã§ããã¢ããªã·ãã¯ãªãµã¼ãã¹å®è£ ã§ããã°ããããæ§æããåã©ã¤ãã©ãªï¼ãããã¯ã³ã³ãã¼ãã³ãï¼ã®APIä»æ§ã§ããããã¤ã¯ããµã¼ãã¹ã¢ã¼ããã¯ãã£ã§ããã°ãåãã¤ã¯ããµã¼ãã¹ã®APIä»æ§ã§ãã
ãã®è¨äºã§ã¯ããã¤ã¯ããµã¼ãã¹éã®éä¿¡ã«ç¨ãã¦ããgRPCã®APIä»æ§ãã©ã®ããã«è¨è¿°ãã¦ããããç´¹ä»ãã¾ãã
APIä»æ§ã«æ±ããããå 容
ã©ã®ãããªAPIä»æ§ã§ãã£ã¦ããããã«è¨è¿°ãããªããã°ãªããªãäºæã¯åºæ¬çã«åãã§ãã
- æä¾ãããæ©è½ã®èª¬æ
- é¢æ°å¼ã³åºããã¡ã½ããå¼ã³åºãããããã¯ãRPCå¼ã³åºãã§ã®ãã©ã¡ã¼ã¿ã®æå³ã¨æ£å½ãªå¤ã®ç¯å²
- å¼ã³åºãããããã®äºåã®ç¶æ ã«ä½ããã®å¶ç´ããã£ãããå¼ã³åºãé åºã«ä½ããã®å¶ç´ããã£ããããã®ã§ããã°ãã©ã®ãããªå¶ç´ãªã®ã
ããã¦ãé²å¾¡çããã°ã©ãã³ã°ï¼defensive programmingï¼ã®è¦³ç¹ããã以ä¸ã®äºæããã¡ãã¨ä»æ§ã«è¨è¿°ããã¦ããå¿ è¦ãããã¾ãã
- ä¸æ£ãªãã©ã¡ã¼ã¿å¤ã渡ãããå ´åãã©ã®ãããªã¨ã©ã¼ãè¿ãããï¼ãããã¯ä¾å¤ãã¹ãã¼ãããï¼ã®ã
- ä¸æ£ãªç¶æ ãä¸æ£ãªé åºã§å¼ã³åºãããå ´åãã©ã®ãããªã¨ã©ã¼ãè¿ãããï¼ãããã¯ä¾å¤ãã¹ãã¼ãããï¼ã®ã
Javaè¨èªã§ããã°ããããã¯ãã¹ã¦Javadocå½¢å¼ã§ã½ã¼ã¹ã³ã¼ãã«æ¸ãã¦ããã¾ããã1.ï¼ã«å¯¾ãã¦ã¯ãNullPointerException
ãIllegalArgumentException
ãIndexOutOfBoundException
ãªã©ãã2.ï¼ã«å¯¾ãã¦ã¯IllegalStateException
ãªã©ã使ãã¾ããJavaè¨èªã§ããã°ã幸ããªãã¨ã«ãAPIä»æ§ã«ã©ã®ãããªäºæãæ¸ãã¹ããããEffective Java 第3çãã«æ¸ããã¦ãã¾ãã
ä¸æ¹ãã¡ã«ãã¤ã®ããã¯ã¨ã³ãã®åãã¤ã¯ããµã¼ãã¹ã¯Goè¨èªãç¨ãã¦å®è£ ããã¦ããããã¤ã¯ããµã¼ãã¹éã®éä¿¡ã¯gRPCãç¨ãã¦ãã¾ããJavaè¨èªã¨éã£ã¦ãgRPCãç¨ããAPIä»æ§ã®æ¸ãæ¹ã®æ¨æºã¯åå¨ãã¾ãããããããgRPCãç¨ããã¨ãã¦ãæ¸ãã¹ãäºæã¯åãã§ãããJavadocã«ç¸å½ããæ¸ãæ¹ã®æ¨æºããªãã®ã§ãè¨è¿°æ¹æ³ã工夫ããå¿ è¦ãããã¾ãã
ãã®ããã°ã§ã¯ãç§èªèº«ã工夫ããè¨è¿°æ¹æ³ã説æãã¾ãã
.proto
ãã¡ã¤ã«ã«è¨è¿°
gRPCã¯ãRPCã®å®ç¾©ã.proto
ãã¡ã¤ã«ã«æ¸ãã¦protocã§ã³ã³ãã¤ã«ãã¦ã¹ã¿ããçæãã¾ããRPCã¯ãã®ååã示ãéããRemote Procedure Callã§ãããæç¶ãï¼procedureï¼ãå®ç¾©ãã訳ã§ããå¼ã³åºãã®ãã©ã¡ã¼ã¿ãå¼ã³åºãçµæã®ã¬ã¹ãã³ã¹ãªã©ãæ§é ä½ï¼structï¼ã¨ãã¦å®ç¾©ãã¾ããã¾ããã¨ã©ã¼ãéç¥ããããã«ã¹ãã¼ã¿ã¹ã³ã¼ããè¿ããã¨ãã§ããããã«ãªã£ã¦ãã¾ããã¹ãã¼ã¿ã¹ã³ã¼ãã¯ãJavaã«ãã¨ããã¨ã¡ã½ãããã¹ãã¼ããä¾å¤ã«ç¸å½ãã¾ãã
gRPCã®APIä»æ§ã®æ¨æºçãªè¨è¿°æ¹æ³ã¯ããã¾ããããã¹ãã¼ã¿ã¹ã³ã¼ãã.proto
ãã¡ã¤ã«ã«è¨è¿°ããããã®æ§æãããã¾ãããæ
å½ãããã¤ã¯ããµã¼ãã¹ã®APIä»æ§ãçå®ããéã«ããã¤ã¯ããµã¼ãã¹ã®gRPCã®å®ç¾©ï¼.proto
ãã¡ã¤ã«ï¼ã¨APIä»æ§ãä¹é¢ãããã¨ãé¿ããããã«ãAPIä»æ§ã¯ãã¹ã¦.protoãã¡ã¤ã«ã«ã³ã¡ã³ãã¨ãã¦è¨è¿°ãããã¨ã«ãã¾ããã
ç°¡åãªä¾
gRPCã®protoãã¡ã¤ã«ã®ä¾ã¨ãã¦ãhttps://grpc.io/docs/guides/ ã«ã¯æ¬¡ã®ãããªãµã³ãã«ãæ²è¼ããã¦ãã¾ãããã®ä¾ã使ã£ã¦ãæ¡ç¨ããæ¸ãæ¹ã説æãã¾ãããªããçªå·ï¼â ãâ¡ãâ¢ãâ£ï¼ã¯ç§ã説æç¨ã«ã¤ãããã®ã§ãã
// The greeter service definition. â service Greeter { // Sends a greetingãâ¡ rpc SayHello (HelloRequest) returns (HelloReply) {} } // The request message containing the user's name.ã⢠message HelloRequest { string name = 1; } // The response message containing the greetingsã⣠message HelloReply { string message = 1; }
serviceã®èª¬æ
â ã«ã¯ãå®ç¾©ãããµã¼ãã¹ã®èª¬æãæ¸ãå¿ è¦ãããã¾ãããã®ä¾ã§ã¯ããµã¼ãã¹ã«RPCãä¸ã¤ããå®ç¾©ããã¦ãã¾ããããé常ã¯è¤æ°ã®RPCå®ç¾©ãæ¸ããã¾ãã®ã§ããµã¼ãã¹ãæä¾ããæ©è½ã®æ¦è¦ãæ¸ãå¿ è¦ãããã¾ãããµã¼ãã¹ã«ãã£ã¦ã¯ãæ°è¡ã§ã¯ãªãã10è¡ä»¥ä¸ã®èª¬æã«ãªããã¨ããããã¨æãã¾ããã¾ãããµã¼ãã¹ã®èª¬æã ãã§ãªãããµã¼ãã¹ãæä¾ãããã¹ã¦ã®RPCã§å ±éã«è¿ãã¹ãã¼ã¿ã¹ã³ã¼ãï¼ã¨ã©ã¼ã³ã¼ãï¼ã®èª¬æãæ¸ããã¨ã«ãªãã¾ãã
RPCã®èª¬æã¨ã¨ã©ã¼ã®è¨è¿°
â¡ã«ã¯ãRPCã®èª¬æãç°¡æ½ã«ä¸è¡ã§æ¸ãã¦ããã°ååã ã¨å¤æãã¾ããããªããªããRPCã®ç´°ããªæ¯ãèãããªã¯ã¨ã¹ãã©ã¡ã¼ã¿ã«ãããäºåæ¡ä»¶ã説æãããã¨ããã¨ããã©ã¡ã¼ã¿ã§ããæ§é ä½ãã¬ã¹ãã³ã¹ã§ããæ§é ä½ã®ãã£ã¼ã«ãã®å®ç¾©ãããã«åç
§ã§ããããã«åãç®æã«æ¸ããã¦ããæ¹ãé½åãããã®ã§ãâ¡ã«æ¸ãã«ã¯ä¸é©åã ã¨å¤æãã¾ãããããã«ãç§ãæ
å½ãããã¤ã¯ããµã¼ãã¹ã§ã¯RPCã®å®ç¾©ã40å以ä¸ãã£ããã¨ããservice
å®ç¾©é¨åã§åã
ã®RPCã®èª¬æãæ¸ãã®ãä¸é©åã ã¨å¤æããçç±ã§ã*3ã
â¢ã¯ãRPCã«å¯¾å¿ãããªã¯ã¨ã¹ããã©ã¡ã¼ã¿ã®æ§é ä½å®ç¾©ã«å¯¾å¿ãã説æé¨åãªã®ã§ããã®RPCã®èª¬æï¼æ¯ãèãï¼ãæ¸ãã®ã¯ãã®é¨åãé©åã ã¨å¤æãã¾ãããããã¦ãããã«ã以ä¸ã®ãã¨ãè¨è¿°ãããã¨ã«ãã¾ããã
- ãªã¯ã¨ã¹ãã®æ§é ä½ã®åãã£ã¼ã«ãã«è¨±ãããå¤
- 許ãããªãå¤ãè¨å®ããã¦ããå ´åã«è¿ãããã¨ã©ã¼
ãã¨ãã°ãä¸è¨ã®ä¾ã§ã¯ãå®éã«ã¯ä½ãæ¸ããã¦ãã¾ãããname
ã空ã§ãããã®ãã空ã許ãã¨ãããããã¯ä½ãæå³ãããã¨ã«ãªãã®ãã空ã許ããªãã¨ããã空ã®å ´åã©ã®ã¹ãã¼ã¿ã¹ã³ã¼ããè¿ãããã®ããä½ãæ¸ããã¦ãã¾ãããã¾ããRPCãå¼ã³åºãããã«ä½ããã®èªè¨¼ãå¿
è¦ãªã®ãã©ãããè¨è¿°ããã¦ãã¾ããããã®ãããªã¨ã©ã¼ã®è¨è¿°ã¯ãRPCããã³ãªã¯ã¨ã¹ãã®åãã£ã¼ã«ãã®èª¬æã¨åãé¨åã«æ¸ãã®ãé½åãããã®ã§ãâ¢ã®é¨åã«æ¸ããã¨ã«ãã¾ããã
ä¸æ£ãªãã©ã¡ã¼ã¿ã®å ´åãåç´ã«ãªã¯ã¨ã¹ãã®ãã£ã¼ã«ãã®å¤ãä»æ§ã§è¦æ±ãããå½¢å¼ãåãå¾ãå¤ã®ç¯å²ãæºãããªãã®ã§ããã°ãã¹ãã¼ã¿ã¹ã³ã¼ãã¯InvalidArgument
ã§ãããã¨æãã¾ããããã§ã¯ãªãã¦ããã¨ãã°ãªã¯ã¨ã¹ãã®ãã£ã¼ã«ãã§æå®ããããã¼ã¿ããã¼ã¿ãã¼ã¹ã«ç¡ãã®ã§ããã°ãNotFound
ããããã¾ãããã©ã¡ãã§ãã£ã¦ããã©ã®ãããªå ´åã«ãã©ã®ã¹ãã¼ã¿ã¹ã³ã¼ããè¿ããããããã¡ãã¨è¨è¿°ããå¿
è¦ãããã¾ãã
gRPCã«ã¯æåã®OKãå«ãã¦æ¨æºã®ã¹ãã¼ã¿ã¹ã³ã¼ãã17åå®ç¾©ããã¦ãã¾ãï¼Goè¨èªç¨ã®å®ç¾©ã¯ãã¡ãï¼ãã©ã®ãããªå ´åã«ãã©ã®ãããªã¹ãã¼ã¿ã¹ã³ã¼ãï¼ã¨ã©ã¼ã³ã¼ãï¼ãè¿ããã¯ããã¡ãã¨è¨è¨ãããã¤ãAPIä»æ§ã«æ確ã«è¨è¿°ããªããã°ãªãã¾ãããã¤ã¾ããâ¢ã®é¨åã«æ確ã«è¨è¿°ããå¿ è¦ãããã¨ãããã¨ã§ã*4ã
â£ã®ã¬ã¹ãã³ã¹ã«ã¤ãã¦ã¯ããã®å 容ãç解ããããã«å¿ è¦ãªèª¬æãæ¸ãå¿ è¦ãããã¾ãããã ãå®ç¾©ããèªæã®å ´åã«ã¯ãä½ãæ¸ããªãã¦ãããããããã¾ããã
å®éã«ç§ãè±èªã§æ¸ããããããã¤ã¯ããµã¼ãã¹ã®.proto
ãã¡ã¤ã«ï¼1åã®service
ã46åã®rpc
ï¼ã¯APIä»æ§ãå«ãã¦2000è¡ä»¥ä¸ãããä¼æ¥ç§å¯ãªã®ã§ããã§ç¤ºããã¨ã¯ã§ãã¾ãããããããä¾ã¨ãã¦ãä¸è¨ã®Greeter
ãä¾ã¨ãã¦æ¸ãç´ããã¨ãã¦ãã次ã®ããã«ãªãã¾ãã
/** *Greeter
service provides a way to say a greeting message to a user and * returns a message from the user. * - Each RPC may returnInternal
but it is not listed in the[ERRORS]
section for brevity. */ service Greeter { // Sends a greeting message to a user and returns a message from the user. rpc SayHello (HelloRequest) returns (HelloResponse) {} } /** *Hello
sends say a hello message a user and returns a message from * the user. * - the returned message may be empty. * * [ERRORS] * - InvalidArgument: * -name
is empty or too long * - NotFound: * - the user specified byname
is not found in the system */ message HelloRequest { string name = 1; } message HelloResponse { string message = 1; }
Unknwon
ã¨Internal
APIä»æ§ã«ã¯ãgRPCã§æä¾ãããµã¼ãã¹ãæä¾ããæ©è½ã«å¿ãã¦ãã©ã®ãããªã¹ãã¼ã¿ã¹ã³ã¼ããè¿ãããããè¨è¿°ãããã¨ãéè¦ã ã¨è¿°ã¹ã¾ããããã ããUnknownã¨Internalã«é¢ãã¦ã¯æ³¨æãå¿ è¦ã§ãã
Goè¨èªã®gRPCç¨ã®ããã«ã¦ã§ã¢ã§ã¯ãstatus
ããã±ã¼ã¸ã使ããã«çæããerror
ãè¿ãã¨ãã³ã¼ãã¨ãã¦Unknown
ãè¿ããã¾ãããã¨ãã°ããã¼ã¿ãã¼ã¹ã¸ã¢ã¯ã»ã¹ããçµæã®error
ããã®ã¾ã¾RPCã®error
ã¨ãã¦è¿ãã¨ãã³ã¼ãã¯Unknown
ã¨ãªãã¾ããã¤ã¾ããUnknown
ã¨ã¯é©åã«ã¹ãã¼ã¿ã¹ã³ã¼ããæå®ãããªãã£ããã¨ãæå³ãã¾ãã®ã§ãAPIä»æ§ã§Unknown
ãè¿ããã¨ãããã¨ã¯æ±ºãã¦æ¸ãããã¹ãã§ã¯ããã¾ããã
è¿ãã¹ãã¼ã¿ã¹ã³ã¼ãã¨ãã¦ã®Internal
ã¯ãå¼ã³åºããå´ã®åé¡ã§ã¯ãªããå¼ã³åºãããå´ã®ä½ããã®ä¸å¤å¼ï¼invariant
ï¼ãæç«ãã¦ããªãã¨ãã«è¿ãã¾ããè¨ãæããã¨ãè¨è¨ä¸ã®ãã°ã¨èãããããã®ã¯Internal
ãè¿ããã¨ã«ãªãã¾ããJavaè¨èªã§è¨ãã°AssertionError
ãæ示çã«ã¹ãã¼ããããããªå ´åã§ããã½ããã¦ã§ã¢ãå®ç§ã«ä½ãã®ã¯å®¹æã§ããã¾ããã®ã§ãè¨è¨ä¸ã®èª¤ãã¨æ³å®ãããäºè±¡ãèµ·ããã¨ãã¯Internal
ãè¿ããã¨ã«ãªãã¾ããããã¹ã¦ã®RPCã«å
±éãããã¨ãªã®ã§ããµã¼ãã¹ã®èª¬æã«æ¸ãã¦ããã ãã§ããã¨æãã¾ãããã¡ãããUnknown
ãInternal
ã¯ããµã¼ãã¹ã¤ã³ã®åã«ãã¹ã¦çºçããªãããã«ãã¹ããå®æ½ãã¦ãããã¨ãçæ³ã§ãã
ã¨ã©ã¼ç¿»è¨³
åè¿°ã®Unknown
ã®ä¾ã ãã§ãªããä¸ã¤ã®ãã¤ã¯ããµã¼ãã¹ãä¾åãã¦ããä»ã®ãã¤ã¯ããµã¼ãã¹ãè¿ãã¨ã©ã¼ããã®ã¾ã¾ä¼æ¬ãã¦è¿ãã¨ãä¸é©åãªã¨ã©ã¼ã¨ãªããã¨ãå¤ãã§ããRPCãæä¾ããæ©è½ã«å¯¾ããé©åãªã¹ãã¼ã¿ã¹ã³ã¼ããè¿ãããã«ã¯ããã¨ã©ã¼ç¿»è¨³ãï¼Javaã§è¨ãã¨ããã®ãä¾å¤ç¿»è¨³ã*5ï¼ãè¡ãå¿
è¦ãããã¾ããé©åãªã¨ã©ã¼ç¿»è¨³ãè¡ãããã«ã¯ãRPCãæä¾ããæ©è½ã«å¯¾ãã¦æ¦å¿µçã«æ£ããã¹ãã¼ã¿ã¹ã³ã¼ããä»æ§ã«å®ç¾©ãã¦ããã¤ã¯ããµã¼ãã¹ã®å®è£
ã§ãã®ã¹ãã¼ã¿ã¹ã³ã¼ãã¸å¤æããå¿
è¦ãããã¾ãã
README.md
ã®èªåçæ
ã¡ã«ã«ãª/ã¡ã«ãã¤ã®.proto
ãã¡ã¤ã«ã¯ãGitHubä¸ã®ãããªãã¸ããªã§ç®¡çããã¦ããã.proto
ãã¡ã¤ã«ãæ´æ°ãããã¨ãèªåçã«README.md
ãã¡ã¤ã«ãçæãããããã«è¨å®ããã¦ãã¾ããã³ã¡ã³ãã¨ãã¦APIä»æ§ãæ¸ãå ´åã«ã¯ã.proto
ãã¡ã¤ã«ããã³ã¡ã³ããæ½åºãã¦ããªã³ã©ã¤ã³ããã¥ã¡ã³ããçæãã¦ããããã¼ã«ãæ±ããå½¢å¼ã§æ¸ãã®ãããã¨æãã¾ãããã¨ãã°ããã¼ã«ã¨ãã¦ã¯protoc-gen-docãªã©ãããã¾ãã®ã§ãããã使ç¨ããã®ã§ããã°ããã¼ã«ã«åããã¦APIä»æ§ãæ¸ãã®ããããã¨æãã¾ãã
ã¾ã¨ã
ãã¡ãã¨ããAPIä»æ§ãæ¸ãã¦ããªãå ´åããã®APIã®ãã¹ãã³ã¼ãã¯æ£å¸¸ã±ã¼ã¹ã ãã ã£ãããä¸æ£ãªãã©ã¡ã¼ã¿ã渡ãããã¨ãã«ã©ã®ããã«æ¯ãèããã¯ãå®è£ ã®ã½ã¼ã¹ã³ã¼ããè¦ãªãã¨åãããªãã£ãããã¾ããããã«ããã¨ã©ã¼ç¿»è¨³ãï¼ãä¾å¤ç¿»è¨³ãï¼ãè¡ã£ã¦ããªãå®è£ ã¯ããã¤ã®ã¾ã«ãè¿ãããã¨ã©ã¼ãå¤ãã£ã¦ãã¾ã£ã¦ãããã¨ãèµ·ããå¾ã¾ãã
ä¸åãå¤ãAPIä»æ§ã¯ãä¸å ·åãå¤ãAPIå®è£ ãçã¿åºããçµæã¨ãã¦é·æçãªéçºã³ã¹ããå¢å ããã¾ããããã¯ããµã¼ããã¼ãã£ã¸æä¾ããã½ããã¦ã§ã¢ã§ã¯ãªãã¦ããä¼ç¤¾å ã§éãã¦ããã½ããã¦ã§ã¢ã§ããé·æçãªéçºã³ã¹ããå¢å ãããçµæã¨ãªãã¾ãã
ï¼Javadocã®ãããªï¼APIä»æ§è¨è¿°ã®æ¥çæ¨æºãåå¨ããªãããã¨ãã£ã¦ãgRPCã®å®ç¾©ã§APIä»æ§ããä½ãæ¸ããªãã¦ãããããã§ã¯ããã¾ãããä½ããã®å·¥å¤«ããã¦æ¸ãå¿
è¦ãããã¾ããç§ãæ
å½ãããã¤ã¯ããµã¼ãã¹ã§ã¯ã.proto
ãã¡ã¤ã«ã«ãã¹ã¦ã³ã¡ã³ãã¨ãã¦è¨è¿°ãããã¨ãé¸æãã¾ããããããããæ¹æ³ãåå¨ããããããã¾ããããä»å¾ç»å ´ããããããã¾ããã
*1:Andrew HuntãDavid Thomas ãé人ããã°ã©ãã¼ãï¼ãªã¼ã 社ï¼
*2:ãé人ããã°ã©ãã¼ãã®ãTip 44 å¶çºçããã°ã©ãã³ã°ãè¡ããªããã¨ã
*3:Spannerã®APIã®ããã«ãã¹ã¦ããã«æ¸ããã¦ãããã®ãåå¨ãã¾ãã
*4:Spannerã®APIã§ã¯æ®å¿µãªããã©ã®ãããªã¹ãã¼ã¿ã¹ã³ã¼ããè¿ããããã¯ãæ¸ããã¦ãã¾ããã
*5:ãEffective Java 第3çãã®ãé ç® 73 æ½è±¡æ¦å¿µã«é©ããä¾å¤ãã¹ãã¼ããã