忣ã·ã¹ãã æ§æã§äœæ¥ããããã®è峿·±ãã¡ã«ããºã ãã話ãããããšæããŸãã æ§æã¯ãå®å
šãªåã䜿çšããŠã³ã³ãã€ã«èšèªïŒScalaïŒã§çŽæ¥æç€ºãããŸãã ãã®æçš¿ã§ã¯ããã®ãããªæ§æã®äŸãåæããéçºããã»ã¹å
šäœã§ã³ã³ãã€ã«ãããæ§æãå®è£
ããããŸããŸãªåŽé¢ãæ€èšããŸãã

ïŒ è±èª ïŒ
ã¯ããã«
ä¿¡é Œæ§ã®é«ã忣ã·ã¹ãã ãæ§ç¯ãããšããããšã¯ããã¹ãŠã®ããŒããä»ã®ããŒããšåæããæ£ããæ§æã䜿çšããããšãæå³ããŸãã éåžžãDevOpsãã¯ãããžãŒïŒterraformãansibleããŸãã¯ãã®ãããªãã®ïŒã䜿çšããŠãæ§æãã¡ã€ã«ãèªåçã«çæããŸãïŒå€ãã®å ŽåãããŒãããšã«ç¬èªã®ãã¡ã€ã«ïŒã ãŸããçžäºäœçšãããã¹ãŠã®ããŒãïŒåãããŒãžã§ã³ãå«ãïŒã§åäžã®ãããã³ã«ã䜿çšããããã«ããŸãã ããããªããšã忣ã·ã¹ãã ã«éäºææ§ãåã蟌ãŸããŸãã JVMã®äžçã§ã¯ããã®èŠä»¶ã®1ã€ã®çµæãšããŠããããã³ã«ã¡ãã»ãŒãžãå«ãåãããŒãžã§ã³ã®ã©ã€ãã©ãªãã©ãã§ã䜿çšããå¿
èŠããããŸãã
忣ã·ã¹ãã ã®ãã¹ãã¯ã©ãã§ããïŒ ãã¡ãããçµ±åãã¹ãã«é²ãåã«ããã¹ãŠã®ã³ã³ããŒãã³ãã«å¯ŸããŠåäœãã¹ããæäŸãããŠãããšæ³å®ããŠããŸãã ïŒãã¹ãçµæãã©ã³ã¿ã€ã ã«å€æ¿ããã«ã¯ããã¹ã段éãšã©ã³ã¿ã€ã ã§åäžã®ã©ã€ãã©ãªã»ãããæäŸããå¿
èŠããããŸããïŒ
çµ±åãã¹ãã䜿çšããå Žåãå€ãã®å Žåããã¹ãŠã®ããŒãã§åäžã®ã¯ã©ã¹ãã¹ã䜿çšããæ¹ãã©ãã§ãç°¡åã§ãã å®è¡æã«åãã¯ã©ã¹ãã¹ãå«ãŸããŠããããšã確èªããã ãã§ãã ïŒç°ãªãã¯ã©ã¹ãã¹ã§ç°ãªãããŒããå®è¡ããããšã¯éåžžã«å¯èœã§ãããããã¯æ§æå
šäœã®è€éåãšãå±éããã³çµ±åãã¹ãã®å°é£ã«ã€ãªãããŸããïŒãã®æçš¿ã®äžéšãšããŠããã¹ãŠã®ããŒãã§åãã¯ã©ã¹ãã¹ã䜿çšããããšæ³å®ããŠããŸãã
æ§æã¯ã¢ããªã±ãŒã·ã§ã³ãšãšãã«é²åããŸãã ããã°ã©ã ã®é²åã®ããŸããŸãªæ®µéãèå¥ããããã«ãããŒãžã§ã³ã䜿çšããŸãã æ§æã®ç°ãªãããŒãžã§ã³ãèå¥ããããšãè«ççã«æãããŸãã ãŸããæ§æèªäœãããŒãžã§ã³ç®¡çã·ã¹ãã ã«é
眮ããå¿
èŠããããŸãã å®çšŒåç°å¢ã«æ§æã1ã€ãããªãå Žåã¯ãããŒãžã§ã³çªå·ã䜿çšã§ããŸãã è€æ°ã®å®çšŒåã€ã³ã¹ã¿ã³ã¹ã䜿çšãããŠããå Žåãããã€ãã®ã€ã³ã¹ã¿ã³ã¹ãå¿
èŠã§ã
æ§æãã©ã³ããšãããŒãžã§ã³ã«å ããŠè¿œå ã®ã©ãã«ïŒããšãã°ããã©ã³ãã®ååïŒã ãããã£ãŠãæ£ç¢ºãªæ§æãäžæã«èå¥ã§ããŸãã åæ§æèå¥åã¯ã忣ããŒããããŒããå€éšãªãœãŒã¹ãã©ã€ãã©ãªããŒãžã§ã³ã®ç¹å®ã®çµã¿åããã«äžæã«å¯Ÿå¿ããŸãã ãã®æçš¿ã®ãã¬ãŒã ã¯ãŒã¯ã§ã¯ããã©ã³ãã1ã€ãããªããšããäºå®ããé²ã¿ããããïŒ1.2.3ïŒã§åºåããã3ã€ã®æ°åã䜿çšããŠéåžžã®æ¹æ³ã§æ§æãèå¥ã§ããŸãã
çŸä»£ã®ç°å¢ã§ã¯ãæ§æãã¡ã€ã«ãæåã§äœæãããããšã¯ã»ãšãã©ãããŸããã å€ãã®å Žåãå±éäžã«çæãããïŒ äœãç Žæããªãããã«ïŒåœ±é¿ãåããªããªããŸãã è«ççãªçåãçããŸããããªãããã¹ã圢åŒã䜿çšããŠæ§æãä¿åããã®ã§ããïŒ å®å
šã«å®è¡å¯èœãªä»£æ¿ææ®µã¯ãæ§æã«éåžžã®ã³ãŒãã䜿çšããã³ã³ãã€ã«æã®ãã§ãã¯ããå©çãåŸãæ©èœã§ãã
ãã®æçš¿ã§ã¯ãã³ã³ãã€ã«ãããã¢ãŒãã£ãã¡ã¯ãå
ã®æ§æã衚ããšããã¢ã€ãã¢ã暡玢ããŠããŸãã
ã³ã³ãã€ã«ãããæ§æ
ãã®ã»ã¯ã·ã§ã³ã§ã¯ãéçã«ã³ã³ãã€ã«ãããæ§æã®äŸã説æããŸãã ãšã³ãŒãµãŒãã¹ãšãšã³ãŒãµãŒãã¹ã¯ã©ã€ã¢ã³ãã®2ã€ã®åçŽãªãµãŒãã¹ãå®è£
ãããŠããŸãã ããã2ã€ã®ãµãŒãã¹ã«åºã¥ããŠã2ã€ã®ããŒãžã§ã³ã®ã·ã¹ãã ãçµã¿ç«ãŠãããŸãã äžå®æœåœ¢æ
ã§ã¯ãäž¡æ¹ã®ãµãŒãã¹ã¯åãããŒãã«é
眮ãããä»ã®å®æœåœ¢æ
ã§ã¯ç°ãªãããŒãã«é
眮ãããã
éåžžã忣ã·ã¹ãã ã«ã¯è€æ°ã®ããŒããå«ãŸããŸãã ããŒãã¯ã NodeId
ã¿ã€ãã®å€ã䜿çšããŠèå¥ã§ããŸãã
sealed trait NodeId case object Backend extends NodeId case object Frontend extends NodeId
ãŸãã¯
case class NodeId(hostName: String)
ãŸãã¯
object Singleton type NodeId = Singleton.type
ããŒãã¯ããŸããŸãªåœ¹å²ãæããããããã§ãµãŒãã¹ãèµ·åããããããã®éã§TCP / HTTPéä¿¡ã確ç«ã§ããŸãã
TCPéä¿¡ã説æããã«ã¯ãå°ãªããšãããŒãçªå·ãå¿
èŠã§ãã ãŸããã¯ã©ã€ã¢ã³ããšãµãŒããŒã®äž¡æ¹ãåããããã³ã«ã䜿çšããããšãä¿èšŒããããã«ããã®ããŒãã§ãµããŒããããŠãããããã³ã«ãåæ ããããšæããŸãã ãã®ã¯ã©ã¹ã䜿çšããæ¥ç¶ã«ã€ããŠèª¬æããŸãã
case class TcpEndPoint[Protocol](node: NodeId, port: Port[Protocol])
ããã§ã Port
ã¯æå¹ãªå€ã®ç¯å²ãæã€æŽæ°ã®æŽæ°ã§ãã
type PortNumber = Refined[Int, Closed[_0, W.`65535`.T]]
æŽç·Žãããã¿ã€ãæŽç·Žãããã©ã€ãã©ãªãšç§ã® ã¬ããŒããã芧ãã ããã ã€ãŸããã©ã€ãã©ãªã䜿çšãããšãã³ã³ãã€ã«æã«ãã§ãã¯ãããå¶çŽãåã«è¿œå ã§ããŸãã ãã®å Žåãæå¹ãªããŒãçªå·ã®å€ã¯æŽæ°ã®16ãããçªå·ã§ãã ã³ã³ãã€ã«æžã¿æ§æã®å ŽåãæŽç·Žãããã©ã€ãã©ãªãŒã®äœ¿çšã¯ãªãã·ã§ã³ã§ãããæ§æãæ€èšŒããã³ã³ãã€ã©ãŒã®æ©èœãåäžãããããšãã§ããŸãã
HTTPïŒRESTïŒãããã³ã«ã®å ŽåãããŒãçªå·ã«å ããŠããµãŒãã¹ãžã®ãã¹ãå¿
èŠã«ãªãå ŽåããããŸãã
type UrlPathPrefix = Refined[String, MatchesRegex[W.`"[a-zA-Z_0-9/]*"`.T]] case class PortWithPrefix[Protocol](portNumber: PortNumber, pathPrefix: UrlPathPrefix)
ãã¡ã³ãã ã¿ã€ãã³ã³ãã€ã«æ®µéã§ãããã³ã«ãèå¥ããããã«ãã¯ã©ã¹å
ã§äœ¿çšãããªãåãã©ã¡ãŒã¿ãŒã䜿çšããŸãã ãã®è§£æ±ºçã¯ãå®è¡æã«ãããã³ã«ã€ã³ã¹ã¿ã³ã¹ã䜿çšããªããšããäºå®ã«ãããã®ã§ãããã³ã³ãã€ã©ã«ãããã³ã«ã®äºææ§ããã§ãã¯ããŠããããããšèããŠããŸãã ãããã³ã«ã®æç€ºã«ãããäžé©åãªãµãŒãã¹ãäŸåé¢ä¿ãšããŠè»¢éããããšã¯ã§ããŸããã
äžè¬çãªãããã³ã«ã®1ã€ã¯ãJsonã·ãªã¢ã«åã䜿çšããREST APIã§ãã
sealed trait JsonHttpRestProtocol[RequestMessage, ResponseMessage]
ããã§ã RequestMessage
ã¯èŠæ±ã®ã¿ã€ãã ResponseMessage
ã¯ResponseMessage
ã®ã¿ã€ãã§ãã
ãã¡ãããå¿
èŠãªç²ŸåºŠãæäŸããä»ã®ãããã³ã«èšè¿°ã䜿çšã§ããŸãã
ãã®æçš¿ã§ã¯ããããã³ã«ã®ç°¡æããŒãžã§ã³ã䜿çšããŸãã
sealed trait SimpleHttpGetRest[RequestMessage, ResponseMessage]
ããã§ãèŠæ±ã¯URLã«è¿œå ãããæååã§ãããå¿çã¯HTTPå¿çã®æ¬æã§è¿ãããæååã§ãã
ãµãŒãã¹æ§æã¯ããµãŒãã¹åãããŒããããã³äŸåé¢ä¿ã«ãã£ãŠèšè¿°ãããŸãã ãããã®èŠçŽ ã¯ãScalaã§ããã€ãã®æ¹æ³ã§è¡šçŸã§ããŸãïŒããšãã°ã HList
ã代æ°ããŒã¿åïŒã ãã®æçš¿ã®ç®çã®ããã«ãCakeãã¿ãŒã³ã䜿çšãã trait
ã䜿çšããŠã¢ãžã¥ãŒã«ã衚ããŸãã ïŒã±ãŒããã¿ãŒã³ã¯ã説æããã¢ãããŒãã®å¿
é èŠçŽ ã§ã¯ãããŸãããå¯èœãªå®è£
ã®1ã€ã«ãããŸãããïŒ
ãµãŒãã¹éã®äŸåé¢ä¿ã¯ãä»ã®ããŒãã®EndPoint
ããŒããè¿ãã¡ãœãããšããŠè¡šãããšãã§ããŸãã
type EchoProtocol[A] = SimpleHttpGetRest[A, A] trait EchoConfig[A] extends ServiceConfig { def portNumber: PortNumber = 8081 def echoPort: PortWithPrefix[EchoProtocol[A]] = PortWithPrefix[EchoProtocol[A]](portNumber, "echo") def echoService: HttpSimpleGetEndPoint[NodeId, EchoProtocol[A]] = providedSimpleService(echoPort) }
ãšã³ãŒãµãŒãã¹ãäœæããã«ã¯ãããŒãçªå·ãšããã®ããŒãããšã³ãŒãããã³ã«ããµããŒãããŠãããšããæç€ºã ãã§ååã§ãã ç¹å®ã®ããŒãã瀺ãããšãã§ããŸããã§ããããªããªã ç¹æ§ã䜿çšãããšãå®è£
ãªãã§ã¡ãœããã宣èšã§ããŸãïŒæœè±¡ã¡ãœããïŒã ãã®å Žåãç¹å®ã®æ§æãäœæãããšãã«ãã³ã³ãã€ã©ãŒã¯æœè±¡ã¡ãœããã®å®è£
ãšããŒãçªå·ã®æäŸãèŠæ±ããŸãã ã¡ãœãããå®è£
ãããããç¹å®ã®æ§æãäœæãããšãã«ãå¥ã®ããŒããæå®ããããšã¯ã§ããŸããã ããã©ã«ãå€ã䜿çšãããŸãã
ã¯ã©ã€ã¢ã³ãæ§æã§ã¯ããšã³ãŒãµãŒãã¹ãžã®äŸåé¢ä¿ã宣èšããŸãã
trait EchoClientConfig[A] { def testMessage: String = "test" def pollInterval: FiniteDuration def echoServiceDependency: HttpSimpleGetEndPoint[_, EchoProtocol[A]] }
äŸåé¢ä¿ã¯ã echoService
ãšã¯ã¹ããŒããµãŒãã¹ãšåãã¿ã€ãã§ãã ç¹ã«ããšã³ãŒã¯ã©ã€ã¢ã³ãã§ã¯ãåããããã³ã«ãå¿
èŠã§ãã ãããã£ãŠã2ã€ã®ãµãŒãã¹ãæ¥ç¶ãããšãã«ããã¹ãŠãæ£ããæ©èœããããšã確èªã§ããŸãã
ãµãŒãã¹å®è£
ãµãŒãã¹ãéå§ããã³åæ¢ããã«ã¯ãæ©èœãå¿
èŠã§ãã ïŒãµãŒãã¹ã忢ããæ©èœã¯ãã¹ãã«äžå¯æ¬ ã§ããïŒç¹°ãè¿ããŸããããã®ãããªæ©èœãå®è£
ããããã®ãªãã·ã§ã³ãããã€ããããŸãïŒããšãã°ãæ§æã¿ã€ãã«åºã¥ããŠã¿ã€ãã¯ã©ã¹ã䜿çšã§ããŸãïŒã ãã®æçš¿ã§ã¯ãCake Patternã䜿çšããŸãã cats.Resource
ã¯ã©ã¹ã䜿çšããŠãµãŒãã¹ã衚ããŸãããªããªãã ãã®ã¯ã©ã¹ã§ã¯ãåé¡ãçºçããå Žåã«ãªãœãŒã¹ãå®å
šã«è§£æŸããææ®µããã§ã«æäŸãããŠããŸãã ãªãœãŒã¹ãååŸããã«ã¯ãæ§æãšæºåãæŽã£ãã©ã³ã¿ã€ã ã³ã³ããã¹ããæäŸããå¿
èŠããããŸãã ãµãŒãã¹ãéå§ãã颿°ã¯æ¬¡ã®ããã«ãªããŸãã
type ResourceReader[F[_], Config, A] = Reader[Config, Resource[F, A]] trait ServiceImpl[F[_]] { type Config def resource( implicit resolver: AddressResolver[F], timer: Timer[F], contextShift: ContextShift[F], ec: ExecutionContext, applicative: Applicative[F] ): ResourceReader[F, Config, Unit] }
ã©ãã§
Config
-ãã®ãµãŒãã¹ã®æ§æã¿ã€ãAddressResolver
ä»ã®ããŒãã®ã¢ãã¬ã¹ãèŠã€ããããšãå¯èœã«ããã©ã³ã¿ã€ã ãªããžã§ã¯ãïŒäžèšåç
§ïŒ
ããã³cats
ã©ã€ãã©ãªã®ä»ã®ã¿ã€ãïŒ
F[_]
-广ã®ã¿ã€ãïŒæãåçŽãªå Žåã F[A]
ã¯åãªã颿°() => A
ã«ãªããŸã() => A
ãã®æçš¿ã§ã¯cats.IO
ã䜿çšããŸãcats.IO
ïŒReader[A,B]
-å€ããå°ãªãã颿°A => B
ãšå矩cats.Resource
ååŸããã³è§£æŸã§ãããªãœãŒã¹Timer
-ã¿ã€ããŒïŒãã°ããç ãã«ã€ãããšãã§ããæéééãæž¬å®ã§ããŸãïŒContextShift
- ExecutionContext
é¡äŒŒç©Applicative
åã
ã®ãšãã§ã¯ãïŒã»ãšãã©ã¢ããïŒãçµã¿åãããããšãã§ãããšãã§ã¯ãã¿ã€ãã¯ã©ã¹ã ããè€éãªã¢ããªã±ãŒã·ã§ã³ã§ã¯ã Monad
/ ConcurrentEffect
ã䜿çšããã»ããè¯ãããã§ãã
ãã®é¢æ°ã·ã°ããã£ã䜿çšããŠãããã€ãã®ãµãŒãã¹ãå®è£
ã§ããŸãã ããšãã°ãäœãããªããµãŒãã¹ïŒ
trait ZeroServiceImpl[F[_]] extends ServiceImpl[F] { type Config <: Any def resource(...): ResourceReader[F, Config, Unit] = Reader(_ => Resource.pure[F, Unit](())) }
ïŒä»ã®ãµãŒãã¹ã®ãœãŒã¹ã³ãŒããåç
§ããŠãã ãã- ãšã³ãŒãµãŒãã¹ ã ãšã³ãŒã¯ã©ã€ã¢ã³ã
ããã³å¯¿åœã³ã³ãããŒã©ãŒ ã
ããŒãã¯ãè€æ°ã®ãµãŒãã¹ãéå§ã§ãããªããžã§ã¯ãã§ãïŒãªãœãŒã¹ãã§ãŒã³ã®èµ·åã¯ãCakeãã¿ãŒã³ã«ãã£ãŠä¿èšŒãããŸãïŒã
object SingleNodeImpl extends ZeroServiceImpl[IO] with EchoServiceService with EchoClientService with FiniteDurationLifecycleServiceImpl { type Config = EchoConfig[String] with EchoClientConfig[String] with FiniteDurationLifecycleConfig }
ãã®ããŒãã«å¿
èŠãªæ§æã®æ£ç¢ºãªã¿ã€ãã瀺ããŠããããšã«æ³šæããŠãã ããã å¥ã®ãµãŒãã¹ã«å¿
èŠãªæ§æã¿ã€ãã®1ã€ãæå®ãå¿ãããšãã³ã³ãã€ã«ãšã©ãŒãçºçããŸãã ãŸããé©åãªã¿ã€ãã®ãªããžã§ã¯ãã«å¿
èŠãªããŒã¿ããã¹ãŠæäŸããªããšãããŒããèµ·åã§ããŸããã
ãã¹ãå解決ãªã¢ãŒããã¹ãã«æ¥ç¶ããã«ã¯ãå®éã®IPã¢ãã¬ã¹ãå¿
èŠã§ãã ã¢ãã¬ã¹ã¯ãæ§æã®æ®ãã®éšåãããåŸã«èªèãããå¯èœæ§ããããŸãã ãããã£ãŠãããŒãèå¥åãã¢ãã¬ã¹ã«ããããã颿°ãå¿
èŠã§ãã
case class NodeAddress[NodeId](host: Uri.Host) trait AddressResolver[F[_]] { def resolve[NodeId](nodeId: NodeId): F[NodeAddress[NodeId]] }
ãã®ãããªé¢æ°ãå®è£
ããã«ã¯ãããã€ãã®æ¹æ³ããããŸãã
- ãããã€åã«ã¢ãã¬ã¹ãããã£ãå ŽåãScalaã³ãŒããçæã§ããŸãã
ã¢ãã¬ã¹ããã¢ã»ã³ããªãéå§ããŸãã ããã«ããããã¹ããã³ã³ãã€ã«ããã³å®è¡ãããŸãã
ãã®å Žåã颿°ã¯éçã«èªèãããããã衚瀺Map[NodeId, NodeAddress]
ãšããŠã³ãŒãã§è¡šãããšãã§ããŸãã - å Žåã«ãã£ãŠã¯ãããŒãã®èµ·ååŸã«ã®ã¿æå¹ãªã¢ãã¬ã¹ãèªèãããŸãã
ãã®å Žåãããã£ã¹ã«ããªãµãŒãã¹ãïŒãã£ã¹ã«ããªïŒãå®è£
ã§ããŸããããã¯ãä»ã®ããŒããšãã¹ãŠã®ããŒãããã®ãµãŒãã¹ã«ç»é²ãããä»ã®ããŒãã®ã¢ãã¬ã¹ãèŠæ±ããåã«å®è¡ãããŸãã /etc/hosts
倿Žã§ããå Žåã¯ãäºåå®çŸ©ããããã¹ãåïŒ my-project-main-node
ãecho-backend
ïŒã䜿çšããŠããããã®ååããã€ã³ãã§ããŸã
å±éäžã«IPã¢ãã¬ã¹ã䜿çšããŸãã
ãã®æçš¿ã®æ çµã¿ã§ã¯ããããã®ã±ãŒã¹ãããè©³çŽ°ã«æ€èšããŸããã ç§ãã¡ã®ããã«
ããã¡ãã®äŸã§ã¯ããã¹ãŠã®ããŒãã«1ã€ã®IPã¢ãã¬ã¹127.0.0.1
ãŸãã
次ã«ã忣ã·ã¹ãã ã®2ã€ã®ãªãã·ã§ã³ãæ€èšããŸãã
- 1ã€ã®ããŒãäžã®ãã¹ãŠã®ãµãŒãã¹ã®é
眮ã
- ãšã³ãŒãµãŒãã¹ãšãšã³ãŒã¯ã©ã€ã¢ã³ãã®ç°ãªãããŒããžã®é
眮ã
åäžããŒãæ§æïŒ
åäžããŒãæ§æ object SingleNodeConfig extends EchoConfig[String] with EchoClientConfig[String] with FiniteDurationLifecycleConfig { case object Singleton // identifier of the single node // configuration of server type NodeId = Singleton.type def nodeId = Singleton override def portNumber: PortNumber = 8088
ãªããžã§ã¯ãã¯ãã¯ã©ã€ã¢ã³ããšãµãŒããŒã®äž¡æ¹ã®æ§æãå®è£
ããŸãã çæ¶¯ã®æ§æãlifetime
åŸã«ããã°ã©ã ãçµããããã«äœ¿çšãããŸãã ïŒCtrl-Cãæ©èœãããã¹ãŠã®ãªãœãŒã¹ãæ£ããè§£æŸããŸããïŒ
åãæ§æç¹æ§ãšå®è£
ã®ã»ããã䜿çšããŠã 2ã€ã®å¥åã®ããŒãã§æ§æãããã·ã¹ãã ãäœæã§ããŸãã
2ã€ã®ããŒãã®æ§æ object NodeServerConfig extends EchoConfig[String] with SigTermLifecycleConfig { type NodeId = NodeIdImpl def nodeId = NodeServer override def portNumber: PortNumber = 8080 } object NodeClientConfig extends EchoClientConfig[String] with FiniteDurationLifecycleConfig {
éèŠïŒ ãµãŒãã¹ã®ãã€ã³ããã©ã®ããã«å®è¡ããããã«æ³šç®ããŠãã ããã å¥ã®ããŒãã®äŸåé¢ä¿ã¡ãœããã®å®è£
ãšããŠã1ã€ã®ããŒãã«ãã£ãŠå®è£
ããããµãŒãã¹ã瀺ããŸãã äŸåé¢ä¿ã®ã¿ã€ãã¯ã³ã³ãã€ã©ãŒã«ãã£ãŠãã§ãã¯ãããŸãã ãããã³ã«ã®ã¿ã€ããå«ãŸããŸãã èµ·åãããšãäŸåé¢ä¿ã«ã¿ãŒã²ããããŒãã®æ£ããèå¥åãå«ãŸããŸãã ãã®ã¹ããŒã ã®ãããã§ãããŒãçªå·ãäžåºŠã ãæ£ç¢ºã«ç€ºããåžžã«æ£ããããŒããåç
§ããããšãä¿èšŒãããŸãã
2ã€ã®ã·ã¹ãã ããŒãã®å®è£
ãã®æ§æã§ã¯ã倿Žããã«åããµãŒãã¹å®è£
ã䜿çšããŸãã å¯äžã®éãã¯ãç°ãªããµãŒãã¹ã»ãããå®è£
ãã2ã€ã®ãªããžã§ã¯ããããããšã§ãã
object TwoJvmNodeServerImpl extends ZeroServiceImpl[IO] with EchoServiceService with SigIntLifecycleServiceImpl { type Config = EchoConfig[String] with SigTermLifecycleConfig } object TwoJvmNodeClientImpl extends ZeroServiceImpl[IO] with EchoClientService with FiniteDurationLifecycleServiceImpl { type Config = EchoClientConfig[String] with FiniteDurationLifecycleConfig }
æåã®ããŒãã¯ãµãŒããŒãå®è£
ãããµãŒããŒæ§æã®ã¿ãå¿
èŠã§ãã 2çªç®ã®ããŒãã¯ã¯ã©ã€ã¢ã³ããå®è£
ããæ§æã®å¥ã®éšåã䜿çšããŸãã ãŸããäž¡æ¹ã®ããŒãã§ã©ã€ãã¿ã€ã ã管çããå¿
èŠããããŸãã ãµãŒããŒããŒãã¯SIGTERM
ã«ãã£ãŠåæ¢ããããŸã§ç¡æéã«å®è¡ãããã¯ã©ã€ã¢ã³ãããŒãã¯ãã°ããããŠçµäºããŸãã èµ·åã¢ããªã±ãŒã·ã§ã³ãåç
§ããŠãã ããã
äžè¬çãªéçºããã»ã¹
ãã®æ§æã¢ãããŒããéçºããã»ã¹å
šäœã«ã©ã®ããã«åœ±é¿ããããèŠãŠã¿ãŸãããã
æ§æã¯æ®ãã®ã³ãŒããšãšãã«ã³ã³ãã€ã«ãããã¢ãŒãã£ãã¡ã¯ãïŒ.jarïŒãçæãããŸãã ã©ããããæ§æãå¥ã®ã¢ãŒãã£ãã¡ã¯ãã«å
¥ããã®ãçã«ããªã£ãŠããŸãã ããã¯ãåãã³ãŒãã«åºã¥ããŠå€ãã®æ§æãæã€ããšãã§ããããã§ãã ç¹°ãè¿ããŸãããããŸããŸãªæ§æãã©ã³ãã«å¯Ÿå¿ããã¢ãŒãã£ãã¡ã¯ããçæã§ããŸãã æ§æãšãšãã«ãã©ã€ãã©ãªã®ç¹å®ã®ããŒãžã§ã³ãžã®äŸåé¢ä¿ãä¿æããããã®ããŒãžã§ã³ã®æ§æãå±éããããšã決å®ãããã³ã«ããããã®ããŒãžã§ã³ã¯æ°žä¹
ã«ä¿æãããŸãã
æ§æã®å€æŽã¯ãã¹ãŠã³ãŒãã®å€æŽã«ãªããŸãã ãããã£ãŠããã®ãããªå
倿Žã¯ãéåžžã®å質ä¿èšŒããã»ã¹ã«ãã£ãŠã«ããŒãããŸãã
ãã°ãã©ãã«ãŒã®ãã±ãã-> PR->ã¬ãã¥ãŒ->察å¿ãããã©ã³ããšããŒãž->
çµ±å->å±é
ã³ã³ãã€ã«ãããæ§æãå®è£
ããäž»ãªçµæïŒ
æ§æã¯ã忣ã·ã¹ãã ã®ãã¹ãŠã®ããŒãã§èª¿æŽãããŸãã ãã¹ãŠã®ããŒããåäžã®ãœãŒã¹ããåãæ§æãåãåããšããäºå®ã®ããã
1ã€ã®ããŒãã®ã¿ã§æ§æã倿Žããã®ã¯åé¡ã§ãã ãããã£ãŠããæ§æã®ããªãããã¯ã»ãšãã©ãããŸããã
å°ããªèšå®å€æŽãè¡ãããšã¯ããé£ãããªã£ãŠããŸãã
ã»ãšãã©ã®æ§æå€æŽã¯ãéçºããã»ã¹å
šäœã®äžéšãšããŠè¡ãããã¬ãã¥ãŒãããŸãã
æ¬çªæ§æãä¿åããããã«å¥ã®ãªããžããªãå¿
èŠã§ããïŒ ãã®ãããªæ§æã«ã¯ããã¹ã¯ãŒãããã®ä»ã®ç§å¯æ
å ±ãã¢ã¯ã»ã¹ãå¶éãããæ
å ±ãå«ãŸããå ŽåããããŸãã ããã«åºã¥ããŠãæçµæ§æãå¥ã®ãªããžããªã«ä¿åããããšã¯çã«ããªã£ãŠããããã§ãã æ§æã2ã€ã®éšåã«åå²ã§ããŸãã1ã€ã¯ãããªãã¯æ§æèšå®ãå«ã¿ããã1ã€ã¯ã¢ã¯ã»ã¹å¶éèšå®ãå«ã¿ãŸãã ããã«ãããã»ãšãã©ã®éçºè
ã¯å
±éã®ãã©ã¡ãŒã¿ãŒã«ã¢ã¯ã»ã¹ã§ããŸãã ãã®åé¢ã¯ãããã©ã«ãå€ãå«ãäžéç¹æ§ã䜿çšããŠç°¡åã«å®çŸã§ããŸãã
å¯èœãªããªãšãŒã·ã§ã³
ã³ã³ãã€ã«æžã¿ã®æ§æãšããã€ãã®äžè¬çãªä»£æ¿æ¡ãæ¯èŒããŠã¿ãŸãããã
- ã¿ãŒã²ãããã·ã³äžã®ããã¹ããã¡ã€ã«ã
- Key-Valueéäžã¹ãã¬ãŒãžïŒ
etcd
/ etcd
ïŒã - ããã»ã¹ãåèµ·åããã«åæ§æ/åèµ·åã§ããã³ã³ããŒãã³ããåŠçããŸãã
- ã¢ãŒãã£ãã¡ã¯ããšããŒãžã§ã³ç®¡çå€ã®æ§æã®ã¹ãã¬ãŒãžã
ããã¹ããã¡ã€ã«ã¯ãå°ããªå€æŽã®ç¹ã§éåžžã«æè»ã§ãã ã·ã¹ãã 管çè
ã¯ããªã¢ãŒãããŒãã«ç§»åããŠã察å¿ãããã¡ã€ã«ã倿ŽãããµãŒãã¹ãåèµ·åã§ããŸãã ãã ããå€§èŠæš¡ã·ã¹ãã ã®å Žåããã®ãããªæè»æ§ã¯æãŸãããªãå ŽåããããŸãã å ãããã倿Žãããä»ã®ã·ã¹ãã ã«ã¯çè·¡ã¯ãããŸããã 誰ã倿Žãã¬ãã¥ãŒããŸããã 誰ãã©ã®ãããªçç±ã§å€æŽãè¡ã£ããã確å®ããããšã¯å°é£ã§ãã 倿Žã¯ãã¹ããããŠããŸããã ã·ã¹ãã ã忣ãããŠããå Žåã管çè
ã¯ä»ã®ããŒãã§å¯Ÿå¿ãã倿Žãå¿ããããšããããŸãã
ïŒãŸããã³ã³ãã€ã«ãããæ§æã䜿çšããŠããå°æ¥ããã¹ããã¡ã€ã«ã䜿çšããå¯èœæ§ããããã¯ããªãããšã«æ³šæããŠãã ãããåºåãšããŠåãã¿ã€ãã®Config
ãæäŸããããŒãµãŒãšããªããŒã¿ã远å ããã ãã§ååã§ããããã¹ããã¡ã€ã«ã«ã¯è¿œå ã®ã³ãŒããå¿
èŠãªãããããã¹ããã¡ã€ã«ã䜿çšããã·ã¹ãã ã®è€éããããäœããªããŸããïŒ
éäžåãããããŒãšå€ã®ã¹ãã¬ãŒãžã¯ã忣ã¢ããªã±ãŒã·ã§ã³ã®ã¡ã¿ãã©ã¡ãŒã¿ãŒã忣ããããã®åªããã¡ã«ããºã ã§ãã æ§æãã©ã¡ãŒã¿ãŒãšã¯äœãããããŠããŒã¿ãšã¯äœããæ±ºå®ããå¿
èŠããããŸãã 颿°C => A => B
ãããããã©ã¡ãŒã¿ãŒC
ãã£ãã«å€åãããããŒã¿A
ãé »ç¹ã«ãããšããŸãã ãã®å Žåã C
ã¯æ§æãã©ã¡ãŒã¿ãŒã§ããã A
ã¯ããŒã¿ã§ãããšèšããŸãã æ§æãã©ã¡ãŒã¿ãŒã¯ãéåžžãããŒã¿ãããé »ç¹ã«å€æŽãããªããšããç¹ã§ãããŒã¿ãšã¯ç°ãªãããã§ãã ãŸããéåžžãããŒã¿ã¯1ã€ã®ãœãŒã¹ïŒãŠãŒã¶ãŒïŒããååŸãããæ§æãã©ã¡ãŒã¿ãŒã¯å¥ã®ãœãŒã¹ïŒã·ã¹ãã 管çè
ïŒããååŸãããŸãã
ããã°ã©ã ãåèµ·åããã«ã»ãšãã©å€æŽããªããã©ã¡ãŒã¿ãŒãæŽæ°ããå¿
èŠãããå Žåãå€ãã®å Žåããã©ã¡ãŒã¿ãŒã®é
ä¿¡ãä¿åãè§£æããã§ãã¯ãäžæ£ãªå€ã®åŠçãå¿
èŠã«ãªããããããã°ã©ã ã®è€éåã«ã€ãªããå¯èœæ§ããããŸãã ãããã£ãŠãããã°ã©ã ã®è€éãã軜æžãããšãã芳ç¹ããã¯ãããã°ã©ã äžã«å€æŽã§ãããã©ã¡ãŒã¿ãŒã®æ°ãæžããããšïŒãŸãã¯ããã®ãããªãã©ã¡ãŒã¿ãŒããŸã£ãããµããŒãããªãããšïŒã¯çã«ããªã£ãŠããŸãã
ãã®æçš¿ã®èгç¹ãããéçãã©ã¡ãŒã¿ãŒãšåçãã©ã¡ãŒã¿ãŒãåºå¥ããŸãã ãµãŒãã¹ã®ããžãã¯ã§ããã°ã©ã äžã«ãã©ã¡ãŒã¿ãŒã倿Žããå¿
èŠãããå Žåããã®ãããªãã©ã¡ãŒã¿ãŒãåçã«åŒã³åºããŸãã ãã以å€ã®å Žåããã©ã¡ãŒã¿ãŒã¯éçã§ãããã³ã³ãã€ã«æžã¿æ§æã䜿çšããŠæ§æã§ããŸãã åçåæ§æã®å Žåããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®ããã»ã¹ãåèµ·åããæ¹æ³ãšåæ§ã«ãããã°ã©ã ã®äžéšãæ°ãããã©ã¡ãŒã¿ãŒã§åèµ·åããã¡ã«ããºã ãå¿
èŠã«ãªãå ŽåããããŸãã ïŒã·ã¹ãã ã®è€éããå¢ãã«ã€ããŠããªã¢ã«ã¿ã€ã ã®åæ§æãåé¿ããããšããå§ãããŸããå¯èœã§ããã°ãããã»ã¹ã®åèµ·åã«ã¯æšæºã®OSæ©èœã䜿çšããããšããå§ãããŸããïŒ
人ã
ãåçãªåæ§æãèæ
®ããããšã匷å¶ããéçãªæ§æã䜿çšããéèŠãªåŽé¢ã®1ã€ã¯ãæ§æã®æŽæ°åŸã®ã·ã¹ãã ã®åèµ·åã«ãããæéïŒããŠã³ã¿ã€ã ïŒã§ãã å®éãéçæ§æã倿Žããå¿
èŠãããå Žåã¯ãæ°ããå€ãæå¹ã«ããããã«ã·ã¹ãã ãåèµ·åããå¿
èŠããããŸãã ããŠã³ã¿ã€ã ã®åé¡ã¯ãã·ã¹ãã ããšã«é倧床ãç°ãªããŸãã å Žåã«ãã£ãŠã¯ãè² è·ãæå°ã®ãšãã«åèµ·åãã¹ã±ãžã¥ãŒã«ã§ããŸãã ç¶ç¶çãªãµãŒãã¹ãæäŸããå Žåã¯ã ãææ°Žæ¥ç¶ãïŒAWS ELBæ¥ç¶ã®ææ°ŽïŒãå®è£
ã§ããŸãã åæã«ãã·ã¹ãã ãåèµ·åããå¿
èŠãããå Žåããã®ã·ã¹ãã ã®äžŠåã€ã³ã¹ã¿ã³ã¹ãèµ·åãããã©ã³ãµãŒãããã«åãæ¿ããŠãå€ãæ¥ç¶ãå®äºãããŸã§åŸ
ã¡ãŸãã ãã¹ãŠã®å€ãæ¥ç¶ãå®äºããããå€ãã·ã¹ãã ã€ã³ã¹ã¿ã³ã¹ããªãã«ããŸãã
ããã§ãã¢ãŒãã£ãã¡ã¯ãã®å
éšãŸãã¯å€éšã«æ§æãä¿åããåé¡ãæ€èšããŸãã ã¢ãŒãã£ãã¡ã¯ãå
ã«æ§æãä¿åããå Žåãå°ãªããšããã¢ãŒãã£ãã¡ã¯ãã®ã¢ã»ã³ããªäžã«æ§æãæ£ããããšã確èªããæ©äŒããããŸããã æ§æãå¶åŸ¡ãããææç©ã®å€åŽã«ããå Žåããã®ãã¡ã€ã«ã«èª°ãããªã倿Žãå ãããã远跡ããããšã¯å°é£ã§ãã ããã¯ã©ãã»ã©éèŠã§ããïŒ ç§ãã¡ã®æèŠã§ã¯ãå€ãã®çç£ã·ã¹ãã ã«ãšã£ãŠãå®å®ããé«åè³ªã®æ§æãéèŠã§ãã
ã¢ãŒãã£ãã¡ã¯ãã®ããŒãžã§ã³ã«ãããäœææ¥æãå«ãŸããå€ãæå¹å/ç¡å¹åãããæ©èœãæ§æã®å€æŽã®è²¬ä»»è
ãæ±ºå®ã§ããŸãã ãã¡ãããã¢ãŒãã£ãã¡ã¯ãå
ã«æ§æãä¿åããã«ã¯å€å°ã®åŽåãå¿
èŠãªã®ã§ãååãªæ
å ±ã«åºã¥ããŠæ±ºå®ããå¿
èŠããããŸãã
é·æãšçæ
ææ¡ãããæè¡ã®é·æãšçæã«ã€ããŠè©³ãã説æããããšæããŸãã
ã¡ãªãã
以äžã¯ãã³ã³ãã€ã«ããã忣ã·ã¹ãã æ§æã®äž»ãªæ©èœã®ãªã¹ãã§ãã
- éçæ§æãã§ãã¯ã ããã確å®ã«ããããšãã§ããŸã
. - . . Scala , . ,
trait' , , val', (DRY) . ( Seq
, Map
, ). - DSL. Scala , DSL. , , , . , , .
- . , , , , . , . , .
- . , , .
- . , .
- . , . . ( , , , , -.) â . , , , , .
- . , . , , . . . , production'.
- . , . , , â . production- .
- . mock-, , .
- . . , , , .
. :
- . production', . . . .
- . , , .
- . , , . / .
- . DevOps . .
- . (CI/CD). .
, :
- , , . , Cake Pattern' , ,
HList
(case class') . - , : (
package
, import
, ; override def
' , ). , DSL. , (, XML), . - .
ãããã«
Scala. xml- . , Scala, ( Kotlin, C#, Swift, ...). , , , , , .
, . .
:
- .
- DSL .
- . , , (1) ; (2) .
è¬èŸ
, .