Compilable configuration sa usa ka distributed nga sistema

Sa kini nga post gusto namon nga ipaambit ang usa ka makapaikag nga paagi sa pag-atubang sa pag-configure sa usa ka gipang-apod-apod nga sistema.
Direkta nga girepresentahan ang configuration sa Scala language sa tipo nga luwas nga paagi. Ang usa ka pananglitan nga pagpatuman gihulagway sa mga detalye. Lainlaing aspeto sa proposal ang gihisgutan, lakip ang impluwensya sa kinatibuk-ang proseso sa kalamboan.

Compilable configuration sa usa ka distributed nga sistema

(sa Russian)

Pasiuna

Ang pagtukod og lig-on nga gipang-apod-apod nga mga sistema nanginahanglan sa paggamit sa husto ug managsama nga pagsumpo sa tanan nga mga node. Ang kasagarang solusyon mao ang paggamit sa usa ka textual deployment deskripsyon (terraform, ansible o usa ka butang nga managsama) ug awtomatik nga namugna nga mga file sa pag-configure (kasagaran - gipahinungod alang sa matag node/role). Gusto usab namon nga mogamit sa parehas nga mga protocol sa parehas nga mga bersyon sa matag komunikasyon nga mga node (kung dili, makasinati kami mga isyu sa dili pagkaangay). Sa kalibutan sa JVM kini nagpasabut nga labing menos ang librarya sa pagmemensahe kinahanglan parehas nga bersyon sa tanan nga mga node sa komunikasyon.

Unsa man ang bahin sa pagsulay sa sistema? Siyempre, kinahanglan nga adunay mga pagsulay sa yunit alang sa tanan nga mga sangkap sa wala pa moabut sa mga pagsulay sa panagsama. Aron ma-extrapolate ang mga resulta sa pagsulay sa oras sa pagdagan, kinahanglan naton sigurohon nga ang mga bersyon sa tanan nga mga librarya magpabilin nga parehas sa parehas nga runtime ug mga palibot sa pagsulay.

Kung nagpadagan sa mga pagsulay sa panagsama, kasagaran mas dali nga adunay parehas nga agianan sa klase sa tanan nga mga node. Kinahanglan lang nato nga masiguro nga ang parehas nga classpath gigamit sa pag-deploy. (Posible nga mogamit ug lain-laing mga classpath sa lain-laing mga node, apan mas lisud ang pagrepresentar niini nga configuration ug sa husto nga pag-deploy niini.) Busa aron mapabilin nga simple ang mga butang atong tagdon lamang ang managsama nga mga classpath sa tanang mga node.

Ang pag-configure lagmit nga molambo kauban ang software. Kasagaran namong gigamit ang mga bersyon aron mailhan ang lainlain
mga yugto sa ebolusyon sa software. Morag makatarunganon ang pagtabon sa configuration ubos sa pagdumala sa bersyon ug pag-ila sa lain-laing mga configuration nga adunay pipila ka mga label. Kung adunay usa lamang ka configuration sa produksyon, mahimo namong gamiton ang usa ka bersyon isip usa ka identifier. Usahay kita adunay daghang mga palibot sa produksiyon. Ug alang sa matag palibot tingali kinahanglan namon ang usa ka lahi nga sanga sa pag-configure. Busa ang mga kumpigurasyon mahimong mamarkahan sa sanga ug bersyon aron mailhan ang lainlaing mga pagsulud. Ang matag label ug bersyon sa sanga katumbas sa usa ka kombinasyon sa mga gipang-apod-apod nga mga node, mga pantalan, mga kapanguhaan sa gawas, mga bersyon sa librarya sa classpath sa matag node. Dinhi ato lang tabonan ang usa ka sanga ug ilhon ang mga configuration pinaagi sa tulo ka component decimal version (1.2.3), sa samang paagi sa ubang artifact.

Sa modernong mga palibot ang mga file sa pag-configure dili na usbon sa mano-mano. Kasagaran kita makamugna
config file sa panahon sa pag-deploy ug ayaw gayod sila hikapa pagkahuman. Mao nga ang usa makapangutana ngano nga gigamit pa naton ang format sa teksto alang sa mga file sa pag-configure? Ang usa ka praktikal nga kapilian mao ang pagbutang sa configuration sulod sa usa ka compilation unit ug makabenepisyo gikan sa compile-time nga configuration validation.

Sa kini nga post atong susihon ang ideya sa pagpadayon sa pagsumpo sa giipon nga artifact.

Compilable nga configuration

Niini nga seksyon atong hisgutan ang usa ka pananglitan sa static nga pag-configure. Duha ka yano nga serbisyo - serbisyo sa echo ug ang kliyente sa serbisyo sa echo gi-configure ug gipatuman. Unya duha ka lain-laing mga gipang-apod-apod nga mga sistema nga adunay parehas nga mga serbisyo ang gi-instantiated. Ang usa alang sa usa ka node configuration ug ang usa alang sa duha ka node configuration.

Ang usa ka tipikal nga giapod-apod nga sistema naglangkob sa pipila ka mga node. Ang mga node mahimong mailhan gamit ang usa ka matang:

sealed trait NodeId
case object Backend extends NodeId
case object Frontend extends NodeId

o makiangayon

case class NodeId(hostName: String)

o bisan pa

object Singleton
type NodeId = Singleton.type

Kini nga mga node naghimo sa lain-laing mga tahas, nagpadagan sa pipila ka mga serbisyo ug kinahanglan nga makahimo sa pagpakigsulti sa ubang mga node pinaagi sa TCP/HTTP koneksyon.

Alang sa koneksyon sa TCP labing menos usa ka numero sa port ang gikinahanglan. Gusto usab namon nga masiguro nga ang kliyente ug server nagsulti sa parehas nga protocol. Aron mamodelo ang usa ka koneksyon tali sa mga node ipahayag nato ang mosunod nga klase:

case class TcpEndPoint[Protocol](node: NodeId, port: Port[Protocol])

diin Port usa lang ka Int sulod sa gitugot nga range:

type PortNumber = Refined[Int, Closed[_0, W.`65535`.T]]

Pino nga mga tipo

Tan-awa ang dalisay librarya. Sa laktud, gitugotan niini ang pagdugang mga pagpugong sa oras sa pagtipon sa ubang mga tipo. Niini nga kaso Int gitugotan lamang nga adunay 16-bit nga mga kantidad nga mahimong magrepresentar sa numero sa port. Wala'y kinahanglanon nga gamiton kini nga librarya alang niini nga pamaagi sa pag-configure. Murag haom ra kaayo.

Alang sa HTTP (REST) ​​​​kinahanglan usab namon ang usa ka agianan sa serbisyo:

type UrlPathPrefix = Refined[String, MatchesRegex[W.`"[a-zA-Z_0-9/]*"`.T]]
case class PortWithPrefix[Protocol](portNumber: PortNumber, pathPrefix: UrlPathPrefix)

Phantom nga tipo

Aron mahibal-an ang protocol sa panahon sa pag-compile gigamit namon ang Scala nga bahin sa pagdeklarar nga tipo nga argumento Protocol nga wala gigamit sa klase. Kini usa ka gitawag matang sa phantom. Sa runtime panagsa ra namo kinahanglan ang usa ka pananglitan sa protocol identifier, mao nga dili namo kini tipigan. Atol sa paghugpong kini nga tipo sa phantom naghatag dugang nga kaluwasan sa tipo. Dili kami makaagi sa pantalan nga adunay dili husto nga protocol.

Usa sa labing kaylap nga gigamit nga mga protocol mao ang REST API nga adunay Json serialization:

sealed trait JsonHttpRestProtocol[RequestMessage, ResponseMessage]

diin RequestMessage mao ang base nga tipo sa mga mensahe nga mapadala sa kliyente sa server ug ResponseMessage mao ang tubag nga mensahe gikan sa server. Siyempre, mahimo kaming maghimo ug uban pang mga paghubit sa protocol nga nagtino sa protocol sa komunikasyon nga adunay gitinguha nga katukma.

Alang sa katuyoan sa kini nga post mogamit kami usa ka mas simple nga bersyon sa protocol:

sealed trait SimpleHttpGetRest[RequestMessage, ResponseMessage]

Niini nga protocol nga hangyo ang mensahe gidugang sa url ug ang tubag nga mensahe gibalik isip yano nga string.

Ang usa ka pag-configure sa serbisyo mahimong gihulagway pinaagi sa ngalan sa serbisyo, usa ka koleksyon sa mga pantalan ug pipila nga mga dependency. Adunay pipila ka posible nga mga paagi kung giunsa pagrepresentar ang tanan niini nga mga elemento sa Scala (pananglitan, HList, algebraic nga mga tipo sa datos). Alang sa mga katuyoan niini nga post among gamiton ang Cake Pattern ug magrepresentar sa mga kombinasyon nga mga piraso (modules) isip mga kinaiya. (Ang Cake Pattern dili usa ka kinahanglanon alang niining compilable configuration approach. Kini usa lamang ka posible nga pagpatuman sa ideya.)

Ang mga dependency mahimong irepresentar gamit ang Cake Pattern isip endpoints sa ubang mga node:

  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)
  }

Ang serbisyo sa echo nanginahanglan lamang usa ka port nga gi-configure. Ug among gipahayag nga kini nga pantalan nagsuporta sa echo protocol. Timan-i nga dili na nato kinahanglan nga ipiho ang usa ka partikular nga pantalan niining higayona, tungod kay ang kinaiya nagtugot sa abstract nga mga pamaagi nga deklarasyon. Kung mogamit kita og abstract nga mga pamaagi, ang compiler magkinahanglan usa ka pagpatuman sa usa ka pananglitan sa pagsumpo. Dinhi among gihatag ang pagpatuman (8081) ug kini gamiton isip default value kon laktawan nato kini sa konkretong configuration.

Mahimo namon nga ipahayag ang usa ka pagsalig sa pag-configure sa kliyente sa serbisyo sa echo:

  trait EchoClientConfig[A] {
    def testMessage: String = "test"
    def pollInterval: FiniteDuration
    def echoServiceDependency: HttpSimpleGetEndPoint[_, EchoProtocol[A]]
  }

Ang dependency adunay parehas nga tipo sa echoService. Sa partikular, nanginahanglan kini parehas nga protocol. Busa, makasiguro kita nga kung atong ikonektar kining duha ka mga dependency sila molihok sa husto.

Pagpatuman sa mga serbisyo

Ang usa ka serbisyo nanginahanglan usa ka function aron magsugod ug maayo nga pagsira. (Ang katakus sa pagsira sa usa ka serbisyo hinungdanon alang sa pagsulay.) Pag-usab adunay pipila ka mga kapilian sa pagtino sa ingon nga function alang sa usa ka gihatag nga config (pananglitan, mahimo naton gamiton ang mga klase nga klase). Alang niini nga post atong gamiton pag-usab ang Cake Pattern. Makarepresentar kami sa usa ka serbisyo gamit cats.Resource nga naghatag na og bracketing ug resource release. Aron makakuha usa ka kapanguhaan kinahanglan namon nga maghatag usa ka pagsumpo ug pipila nga konteksto sa runtime. Mao nga ang function sa pagsugod sa serbisyo mahimong tan-awon sama sa:

  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]
  }

diin

  • Config — matang sa pag-configure nga gikinahanglan niining service starter
  • AddressResolver — usa ka butang nga runtime nga adunay katakus sa pagkuha sa tinuod nga mga adres sa ubang mga node (padayon sa pagbasa alang sa mga detalye).

ang ubang mga matang gikan cats:

  • F[_] — tipo sa epekto (Sa pinakasimple nga kaso F[A] mahimo ra () => A. Niini nga post atong gamiton cats.IO.)
  • Reader[A,B] — mas daghan o dili kaayo usa ka synonym sa usa ka function A => B
  • cats.Resource - adunay mga paagi sa pag-angkon ug pagpagawas
  • Timer - nagtugot sa pagkatulog / pagsukod sa oras
  • ContextShift - analogue sa ExecutionContext
  • Applicative — wrapper sa mga function sa epekto (halos usa ka monad) (mahimo natong ilisan kini sa laing butang)

Gamit kini nga interface mahimo namon nga ipatuman ang pipila ka mga serbisyo. Pananglitan, usa ka serbisyo nga wala’y mahimo:

  trait ZeroServiceImpl[F[_]] extends ServiceImpl[F] {
    type Config <: Any
    def resource(...): ResourceReader[F, Config, Unit] =
      Reader(_ => Resource.pure[F, Unit](()))
  }

(Tan-awa Source code alang sa ubang mga serbisyo nga pagpatuman - serbisyo sa echo,
echo nga kliyente ug tibuok kinabuhi nga mga controller.)

Ang usa ka node usa ka butang nga nagpadagan sa pipila ka mga serbisyo (pagsugod sa usa ka kutay sa mga kahinguhaan gipagana sa Cake Pattern):

object SingleNodeImpl extends ZeroServiceImpl[IO]
  with EchoServiceService
  with EchoClientService
  with FiniteDurationLifecycleServiceImpl
{
  type Config = EchoConfig[String] with EchoClientConfig[String] with FiniteDurationLifecycleConfig
}

Timan-i nga sa node atong gipiho ang eksaktong matang sa configuration nga gikinahanglan niini nga node. Dili kami tugotan sa Compiler nga magtukod sa butang (Cake) nga dili igo nga tipo, tungod kay ang matag kinaiya sa serbisyo nagpahayag usa ka pagpugong sa Config matang. Usab dili kami makasugod sa node nga wala maghatag og kompleto nga configuration.

Resolusyon sa node address

Aron ma-establisar ang usa ka koneksyon kinahanglan namon ang usa ka tinuud nga adres sa host alang sa matag node. Mahimong mahibal-an kini sa ulahi kaysa sa ubang mga bahin sa pag-configure. Busa, nagkinahanglan kita ug paagi sa paghatag ug mapping tali sa node id ug sa aktuwal nga adres niini. Kini nga mapping usa ka function:

case class NodeAddress[NodeId](host: Uri.Host)
trait AddressResolver[F[_]] {
  def resolve[NodeId](nodeId: NodeId): F[NodeAddress[NodeId]]
}

Adunay pipila ka posible nga mga paagi sa pagpatuman sa ingon nga function.

  1. Kung nahibal-an namon ang aktwal nga mga adres sa wala pa i-deploy, sa panahon sa instantiation sa mga host sa node, nan mahimo namon nga makamugna ang Scala code nga adunay tinuud nga mga adres ug ipadagan ang pagtukod pagkahuman (nga nagpahigayon mga pagsusi sa oras sa pag-compile ug dayon nagpadagan sa integration test suite). Sa kini nga kaso ang among mapping function nahibal-an nga static ug mahimong pasimplehon sa usa ka butang sama sa a Map[NodeId, NodeAddress].
  2. Usahay makakuha kami ug aktuwal nga mga adres sa ulahi nga punto kung ang node nagsugod na, o wala kami mga adres sa mga node nga wala pa magsugod. Sa kini nga kaso mahimo kaming adunay usa ka serbisyo sa pagdiskobre nga gisugdan sa wala pa ang tanan nga uban pang mga node ug ang matag node mahimong mag-anunsyo sa adres niini sa kana nga serbisyo ug mag-subscribe sa mga dependency.
  3. Kung mahimo naton usbon /etc/hosts, mahimo namong gamiton ang mga predefined host names (sama sa my-project-main-node ug echo-backend) ug i-associate lang kini nga ngalan sa ip address sa oras sa pag-deploy.

Sa kini nga post wala namon gitabonan kini nga mga kaso sa dugang nga mga detalye. Sa tinuud sa among dulaan nga pananglitan ang tanan nga mga node adunay parehas nga IP address - 127.0.0.1.

Niini nga post atong tagdon ang duha ka gipang-apod-apod nga mga layout sa sistema:

  1. Usa ka layout sa node, diin ang tanan nga mga serbisyo gibutang sa usa ka node.
  2. Duha ka layout sa node, diin ang serbisyo ug kliyente naa sa lainlaing mga node.

Ang configuration alang sa a usa ka node ang layout mao ang mosunod:

Pag-configure sa usa ka node

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

  /** Type safe service port specification. */
  override def portNumber: PortNumber = 8088

  // configuration of client

  /** We'll use the service provided by the same host. */
  def echoServiceDependency = echoService

  override def testMessage: UrlPathElement = "hello"

  def pollInterval: FiniteDuration = 1.second

  // lifecycle controller configuration
  def lifetime: FiniteDuration = 10500.milliseconds // additional 0.5 seconds so that there are 10 requests, not 9.
}

Dinhi naghimo kami og usa ka configuration nga nagpalapad sa server ug client configuration. Usab among gi-configure ang usa ka controller sa lifecycle nga kasagarang tapuson ang kliyente ug server pagkahuman lifetime paglabay sa agwat.

Ang parehas nga set sa mga pagpatuman ug mga pag-configure sa serbisyo mahimong magamit aron makahimo usa ka layout sa sistema nga adunay duha nga magkabulag nga mga node. Kinahanglan lang nga maghimo kita duha ka managlahi nga node configs uban sa angay nga mga serbisyo:

Pag-configure sa duha ka node

  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
  {
    // NB! dependency specification
    def echoServiceDependency = NodeServerConfig.echoService

    def pollInterval: FiniteDuration = 1.second

    def lifetime: FiniteDuration = 10500.milliseconds // additional 0.5 seconds so that there are 10 request, not 9.

    def testMessage: String = "dolly"
  }

Tan-awa kung giunsa namo pagtino ang dependency. Gihisgotan namo ang gihatag nga serbisyo sa laing node isip dependency sa kasamtangan nga node. Ang matang sa dependency gisusi tungod kay kini adunay phantom type nga naghulagway sa protocol. Ug sa runtime kita adunay husto nga node id. Kini mao ang usa sa importante nga mga aspeto sa gisugyot nga paagi sa pag-configure. Naghatag kini kanamo og katakus nga magbutang usa ka pantalan ug siguruha nga among gipunting ang husto nga pantalan.

Pagpatuman sa duha ka node

Alang sa kini nga pag-configure gigamit namon ang parehas nga mga pagpatuman sa serbisyo. Wala gayoy kausaban. Bisan pa, naghimo kami duha ka lainlaing mga pagpatuman sa node nga adunay lainlaing hugpong sa mga serbisyo:

  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
  }

Ang una nga node nag-implementar sa server ug kini nagkinahanglan lamang sa server side config. Ang ikaduha nga node nagpatuman sa kliyente ug nagkinahanglan og laing bahin sa config. Ang duha ka mga node nanginahanglan pipila ka mga detalye sa tibuok kinabuhi. Alang sa mga katuyoan niini nga post service node adunay walay katapusan nga tibuok kinabuhi nga mahimong tapuson ang paggamit SIGTERM, samtang ang echo nga kliyente mohunong pagkahuman sa gi-configure nga gidugayon nga gidugayon. Tan-awa ang starter nga aplikasyon alang sa mga detalye.

Kinatibuk-ang proseso sa pag-uswag

Atong tan-awon kung giunsa kini nga pamaagi nagbag-o sa paagi sa among pagtrabaho kauban ang pag-configure.

Ang pag-configure ingon nga code tigumon ug maghimo usa ka artifact. Morag makatarunganon ang pagbulag sa artifact sa pag-configure gikan sa ubang mga artifact sa code. Kasagaran kita adunay daghang mga pag-configure sa parehas nga base sa code. Ug siyempre, mahimo kita adunay daghang mga bersyon sa lainlaing mga sanga sa pag-configure. Sa usa ka configuration makapili kita og partikular nga mga bersyon sa mga library ug kini magpabilin nga makanunayon sa matag higayon nga atong i-deploy kini nga configuration.

Ang pagbag-o sa pag-configure mahimong pagbag-o sa code. Busa kini kinahanglan nga masakop sa parehas nga proseso sa kasiguruhan sa kalidad:

Ticket -> PR -> review -> paghiusa -> padayon nga paghiusa -> padayon nga pagdeploy

Adunay mga mosunod nga mga sangputanan sa pamaagi:

  1. Ang pag-configure managsama alang sa usa ka pananglitan sa usa ka partikular nga sistema. Morag wala’y paagi nga adunay dili husto nga koneksyon tali sa mga node.
  2. Dili sayon ​​ang pag-usab sa configuration sa usa lang ka node. Morag dili makatarunganon ang pag-log in ug pag-ilis sa pipila ka mga text file. Busa ang configuration drift nahimong dili kaayo posible.
  3. Ang gagmay nga mga pagbag-o sa pag-configure dili sayon ​​​​buhaton.
  4. Kadaghanan sa mga pagbag-o sa pag-configure mosunod sa parehas nga proseso sa pag-uswag, ug kini moagi sa pipila nga pagrepaso.

Nagkinahanglan ba kami usa ka bulag nga tipiganan alang sa pagsumpo sa produksiyon? Mahimong adunay sulud nga sensitibo nga kasayuran ang configuration sa produksiyon nga gusto namon nga dili maabut sa daghang mga tawo. Mao nga mahimo’g takus ang pagtipig sa usa ka bulag nga repository nga adunay limitado nga pag-access nga adunay sulud nga pagsumpo sa produksiyon. Mahimo natong bahinon ang configuration ngadto sa duha ka bahin - ang usa nga adunay labing bukas nga mga parameter sa produksyon ug usa nga adunay sekreto nga bahin sa configuration. Makahimo kini sa pag-access sa kadaghanan sa mga nag-develop sa kadaghanan sa mga parameter samtang gipugngan ang pag-access sa labi ka sensitibo nga mga butang. Sayon nga mahimo kini gamit ang mga intermediate nga mga kinaiya nga adunay default nga mga kantidad sa parameter.

kalainan

Atong tan-awon ang mga bentaha ug disbentaha sa gisugyot nga pamaagi kung itandi sa ubang mga pamaagi sa pagdumala sa pag-configure.

Una sa tanan, ilista namo ang pipila ka alternatibo sa lain-laing aspeto sa gisugyot nga paagi sa pag-atubang sa configuration:

  1. Text file sa target nga makina.
  2. Sentralisado nga key-value storage (sama sa etcd/zookeeper).
  3. Subprocess nga mga sangkap nga mahimong ma-reconfigure / ma-restart nga wala gi-restart ang proseso.
  4. Pag-configure sa gawas sa artifact ug pagkontrol sa bersyon.

Naghatag ang text file sa pipila ka kadali sa mga termino sa pag-ayo sa ad-hoc. Ang administrador sa usa ka sistema maka-log in sa target node, makahimo og kausaban ug i-restart lang ang serbisyo. Mahimong dili kini maayo alang sa mas dagkong mga sistema. Walay mga timailhan nga nahabilin sa pagbag-o. Ang pagbag-o wala gisusi sa laing parisan sa mga mata. Mahimong lisud mahibal-an kung unsa ang hinungdan sa pagbag-o. Wala pa kini gisulayan. Gikan sa panglantaw sa giapod-apod nga sistema ang usa ka administrador makalimot lang sa pag-update sa configuration sa usa sa ubang mga node.

(Btw, kung sa kadugayan kinahanglan nga magsugod sa paggamit sa mga file sa pag-configure sa teksto, kinahanglan ra namon nga idugang ang parser + validator nga makahimo sa parehas Config type ug kana igo na aron magsugod sa paggamit sa mga config sa teksto. Gipakita usab niini nga ang pagkakomplikado sa pag-configure sa oras sa pag-compile mas gamay kaysa sa pagkakomplikado sa mga config nga nakabase sa teksto, tungod kay sa bersyon nga nakabase sa teksto kinahanglan namon ang dugang nga code.)

Ang sentralisadong key-value storage usa ka maayong mekanismo sa pag-apod-apod sa mga meta parameter sa aplikasyon. Dinhi kinahanglan naton hunahunaon kung unsa ang giisip namon nga mga kantidad sa pag-configure ug kung unsa ang datos ra. Gihatagan ug function C => A => B kasagaran namong gitawag nga panagsa ra nag-usab-usab nga mga bili C "configuration", samtang kanunay giusab nga datos A - input data lang. Ang pag-configure kinahanglan nga ihatag sa function sa sayo pa kaysa sa datos A. Gihatag kini nga ideya mahimo naton isulti nga gipaabut nga kasubsob sa mga pagbag-o kung unsa ang magamit aron mailhan ang datos sa pag-configure gikan sa datos ra. Usab ang datos kasagarang gikan sa usa ka tinubdan (user) ug ang configuration gikan sa laing tinubdan (admin). Ang pag-atubang sa mga parameter nga mahimong mabag-o pagkahuman sa proseso sa pagsugod nagdala sa pagdugang sa pagkakomplikado sa aplikasyon. Alang sa ingon nga mga parameter kinahanglan namon nga dumalahon ang ilang mekanismo sa pagpadala, pag-parse ug pag-validate, pagdumala sa dili husto nga mga kantidad. Busa, aron makunhuran ang pagkakomplikado sa programa, mas maayong pakunhuran nato ang gidaghanon sa mga parametro nga mahimong mausab sa panahon sa pagdagan (o bisan sa pagwagtang niini sa hingpit).

Gikan sa panan-aw sa kini nga post kinahanglan naton maghimo usa ka kalainan tali sa static ug dinamikong mga parameter. Kung ang lohika sa serbisyo nanginahanglan talagsa nga pagbag-o sa pipila nga mga parameter sa oras sa pagdagan, mahimo naton kini tawgon nga dinamikong mga parameter. Kung dili sila static ug mahimong ma-configure gamit ang gisugyot nga pamaagi. Alang sa dinamikong pag-configure sa ubang mga pamaagi mahimo’g kinahanglan. Pananglitan, ang mga bahin sa sistema mahimong i-restart sa bag-ong mga parameter sa pag-configure sa parehas nga paagi sa pagsugod pag-usab sa bulag nga mga proseso sa usa ka gipang-apod-apod nga sistema.
(Ang akong mapainubsanon nga opinyon mao ang paglikay sa runtime reconfiguration tungod kay kini nagdugang sa pagkakomplikado sa sistema.
Mahimong mas diretso nga magsalig lang sa suporta sa OS sa mga proseso sa pag-restart. Bisan pa, dili kini kanunay nga posible.)

Usa ka importante nga aspeto sa paggamit sa static nga configuration nga usahay maghimo sa mga tawo nga ikonsiderar ang dinamikong configuration (walay uban nga mga rason) mao ang service downtime atol sa configuration update. Sa tinuud, kung kinahanglan naton maghimo mga pagbag-o sa static nga pag-configure, kinahanglan naton i-restart ang sistema aron ang mga bag-ong kantidad mahimong epektibo. Ang mga kinahanglanon alang sa downtime lainlain alang sa lainlaing mga sistema, mao nga dili kini ingon ka kritikal. Kung kini kritikal, nan kinahanglan namon nga magplano sa unahan alang sa bisan unsang pag-restart sa sistema. Pananglitan, mahimo natong ipatuman Ang koneksyon sa AWS ELB nahurot. Sa kini nga senaryo sa matag higayon nga kinahanglan namon nga i-restart ang sistema, magsugod kami usa ka bag-ong instance sa sistema nga managsama, dayon ibalhin ang ELB niini, samtang gitugotan ang daan nga sistema nga makompleto ang pagserbisyo sa mga naa na nga koneksyon.

Unsa man ang bahin sa pagpadayon sa pag-configure sa sulod sa bersyon nga artifact o sa gawas? Ang pagpadayon sa pag-configure sa sulod sa usa ka artifact nagpasabut sa kadaghanan sa mga kaso nga kini nga pag-configure nakapasar sa parehas nga proseso sa kasiguruhan sa kalidad sama sa ubang mga artifact. Mao nga ang usa makasiguro nga ang pag-configure adunay maayo nga kalidad ug kasaligan. Sa sukwahi nga pag-configure sa usa ka lahi nga file nagpasabut nga wala’y mga pagsubay kung kinsa ug ngano nga nagbag-o sa kana nga file. Importante ba kini? Kami nagtuo nga alang sa kadaghanan sa mga sistema sa produksiyon mas maayo nga adunay lig-on ug taas nga kalidad nga pagsumpo.

Gitugotan ang bersyon sa artifact nga mahibal-an kung kanus-a kini gibuhat, kung unsang mga kantidad ang naa niini, kung unsang mga bahin ang gipagana / gipugngan, kinsa ang responsable sa paghimo sa matag pagbag-o sa pagsumpo. Mahimong manginahanglan kini og pipila ka paningkamot aron mapadayon ang pag-configure sa sulod sa usa ka artifact ug kini usa ka kapilian sa disenyo nga buhaton.

Mga kaayohan ug disbentaha

Dinhi gusto namon nga ipasiugda ang pipila nga mga bentaha ug hisgutan ang pipila nga mga disbentaha sa gisugyot nga pamaagi.

bentaha

Mga bahin sa compilable configuration sa usa ka kompleto nga gipang-apod-apod nga sistema:

  1. Static nga pagsusi sa configuration. Naghatag kini usa ka taas nga lebel sa pagsalig, nga ang pagsulud husto nga gihatag nga mga pagpugong sa tipo.
  2. Daghang pinulongan sa pag-configure. Kasagaran ang uban nga mga pamaagi sa pag-configure limitado sa kadaghanan nga pagbag-o nga pagpuli.
    Ang paggamit sa Scala ang usa makagamit sa usa ka halapad nga mga bahin sa lengguwahe aron mas maayo ang pag-configure. Pananglitan, mahimo natong gamiton ang mga kinaiya sa paghatag og default nga mga bili, mga butang nga magtakda og lain-laing scope, mahimo natong hisgotan vals gihubit kausa ra sa gawas nga sakup (DRY). Posible nga gamiton ang literal nga mga han-ay, o mga higayon sa pipila nga mga klase (Seq, Map, Ug uban pa).
  3. DSL. Ang Scala adunay desente nga suporta alang sa mga magsusulat sa DSL. Mahimong gamiton sa usa kini nga mga bahin aron magtukod usa ka sinultian nga pag-configure nga labi ka kombenyente ug mahigalaon sa end-user, aron ang katapusan nga pag-configure labing menos mabasa sa mga tiggamit sa domain.
  4. Integridad ug pagkahiusa sa mga node. Usa sa mga benepisyo sa pag-configure alang sa tibuuk nga sistema nga gipang-apod-apod sa usa ka lugar mao nga ang tanan nga mga kantidad gihubit nga estrikto kausa ug dayon gamiton pag-usab sa tanan nga mga lugar kung diin kinahanglan naton kini. I-type usab ang luwas nga mga deklarasyon sa pantalan pagsiguro nga sa tanan nga posible nga husto nga mga pag-configure ang mga node sa sistema mosulti sa parehas nga sinultian. Adunay klaro nga mga dependency tali sa mga node nga nagpalisud sa pagkalimot sa paghatag sa pipila ka mga serbisyo.
  5. Taas nga kalidad sa mga pagbag-o. Ang kinatibuk-ang pamaagi sa pagpasa sa mga pagbag-o sa configuration pinaagi sa normal nga proseso sa PR nagtukod og taas nga mga sumbanan sa kalidad usab sa configuration.
  6. Dungan nga kausaban sa configuration. Sa matag higayon nga maghimo kami bisan unsang mga pagbag-o sa awtomatikong pag-deploy sa configuration nagsiguro nga ang tanan nga mga node gi-update.
  7. Pagpasimple sa aplikasyon. Ang aplikasyon dili kinahanglan nga mag-parse ug mag-validate sa pag-configure ug pagdumala sa dili husto nga mga kantidad sa pag-configure. Gipasimple niini ang kinatibuk-ang aplikasyon. (Ang uban nga pagtaas sa pagkakomplikado anaa sa configuration mismo, apan kini usa ka mahunahunaon nga trade-off ngadto sa kaluwasan.) Medyo prangka ang pagbalik sa ordinaryo nga configuration — idugang lang ang nawala nga mga piraso. Mas dali ang pagsugod sa gihugpong nga pag-configure ug i-postpone ang pagpatuman sa dugang nga mga piraso sa pipila ka ulahi nga mga panahon.
  8. Gibag-o nga configuration. Tungod sa kamatuoran nga ang mga pagbag-o sa pag-configure nagsunod sa parehas nga proseso sa pag-uswag, ingon usa ka sangputanan nakakuha kami usa ka artifact nga adunay talagsaon nga bersyon. Gitugotan kami nga ibalik ang pag-configure kung kinahanglan. Mahimo pa gani namon nga i-deploy ang usa ka configuration nga gigamit usa ka tuig na ang milabay ug kini molihok sa parehas nga paagi. Ang stable nga configuration makapauswag sa predictability ug pagkakasaligan sa gipang-apod-apod nga sistema. Ang pag-configure gitakda sa oras sa pag-compile ug dili dali madaot sa usa ka sistema sa produksiyon.
  9. Modularidad. Ang gisugyot nga balangkas mao ang modular ug ang mga module mahimong ikombinar sa lainlaing mga paagi aron
    pagsuporta sa lain-laing mga configuration (setups/layouts). Sa partikular, posible nga adunay usa ka gamay nga sukod nga layout sa usa ka node ug usa ka dako nga sukod nga setting sa daghang node. Makatarunganon nga adunay daghang mga layout sa produksiyon.
  10. Pagsulay. Alang sa mga katuyoan sa pagsulay mahimo’g ipatuman sa usa ang usa ka serbisyo sa pagbiaybiay ug gamiton kini ingon usa ka pagsalig sa usa ka luwas nga paagi. Ang pipila ka lainlaing mga layout sa pagsulay nga adunay lainlaing mga bahin nga gipulihan sa mga pagbiaybiay mahimong mapadayon nga dungan.
  11. Pagsulay sa panagsama. Usahay sa gipang-apod-apod nga mga sistema lisud ang pagpadagan sa mga pagsulay sa panagsama. Gamit ang gihulagway nga pamaagi aron ma-type ang luwas nga pag-configure sa kompleto nga naapod-apod nga sistema, mahimo namon nga mapadagan ang tanan nga gipang-apod-apod nga mga bahin sa usa ka server sa usa ka makontrol nga paagi. Sayon nga sundogon ang sitwasyon
    kung ang usa sa mga serbisyo mahimong dili magamit.

disadvantages

Ang gihugpong nga pamaagi sa pag-configure lahi sa "normal" nga pag-configure ug dili kini angay sa tanan nga mga panginahanglanon. Ania ang pipila sa mga disadvantages sa compiled config:

  1. Static nga configuration. Mahimong dili kini angay alang sa tanan nga aplikasyon. Sa pipila ka mga kaso adunay panginahanglan sa dali nga pag-ayo sa pagsumpo sa produksiyon nga laktawan ang tanan nga mga lakang sa kaluwasan. Kini nga pamaagi naghimo niini nga mas lisud. Ang paghugpong ug redeployment gikinahanglan human sa paghimo sa bisan unsa nga kausaban sa configuration. Kini ang bahin ug ang palas-anon.
  2. Pagmugna sa pag-configure. Kung ang config gihimo sa pipila ka himan sa automation kini nga pamaagi nanginahanglan sunod nga pag-compile (nga mahimo’g mapakyas). Mahimong manginahanglan kini og dugang nga paningkamot aron mahiusa kining dugang nga lakang sa sistema sa pagtukod.
  3. Mga instrumento. Adunay daghang mga himan nga gigamit karon nga nagsalig sa mga config nga nakabase sa teksto. Ang uban kanila
    dili magamit kung gi-compile ang configuration.
  4. Kinahanglan ang pagbag-o sa panghunahuna. Ang mga developer ug DevOps pamilyar sa mga file sa pag-configure sa teksto. Ang ideya sa pag-compile sa pag-configure mahimo’g katingad-an sa kanila.
  5. Sa dili pa ipaila ang compilable configuration gikinahanglan ang taas nga kalidad nga proseso sa pagpalambo sa software.

Adunay pipila ka mga limitasyon sa gipatuman nga pananglitan:

  1. Kung maghatag kami ug dugang nga config nga wala gipangayo sa pagpatuman sa node, ang compiler dili makatabang kanamo nga makit-an ang wala nga pagpatuman. Kini mahimong matubag pinaagi sa paggamit HList o ADTs (case classes) para sa node configuration imbes nga traits ug Cake Pattern.
  2. Kinahanglan namon nga maghatag pipila ka boilerplate sa config file: (package, import, object mga deklarasyon;
    override defalang sa mga parameter nga adunay mga default nga kantidad). Mahimong partially addressed kini gamit ang DSL.
  3. Sa kini nga post wala namon gitabonan ang dinamikong pag-configure sa mga pungpong sa parehas nga mga node.

Panapos

Sa kini nga post among gihisgutan ang ideya sa pagrepresentar sa configuration direkta sa source code sa usa ka tipo nga luwas nga paagi. Ang pamaagi mahimong gamiton sa daghang mga aplikasyon isip usa ka puli sa xml- ug uban pang mga text-based configs. Bisan pa nga ang among panig-ingnan gipatuman sa Scala, kini mahimo usab nga hubaron sa ubang mga compilable nga mga pinulongan (sama sa Kotlin, C #, Swift, ug uban pa). Mahimong sulayan sa usa kini nga pamaagi sa usa ka bag-ong proyekto ug, kung dili kini angay, ibalhin sa daan nga paagi.

Siyempre, ang compilable configuration nagkinahanglan og taas nga kalidad nga proseso sa pag-uswag. Agig balos kini nagsaad nga maghatag parehas nga taas nga kalidad nga lig-on nga pagsulud.

Kini nga pamaagi mahimong madugangan sa lainlaing mga paagi:

  1. Mahimong mogamit ang usa ka macros aron mahimo ang pag-validate sa pagsumpo ug mapakyas sa oras sa pag-compile kung adunay bisan unsang mga kapakyasan sa lohika sa negosyo.
  2. Mahimong ipatuman ang usa ka DSL aron magrepresentar sa configuration sa usa ka domain-user-friendly nga paagi.
  3. Ang dinamikong pagdumala sa kapanguhaan nga adunay awtomatikong pag-adjust sa pag-configure. Pananglitan, kung atong i-adjust ang gidaghanon sa mga cluster node mahimo natong gusto (1) ang mga node makakuha og gamay nga giusab nga configuration; (2) cluster manager aron makadawat og bag-ong impormasyon sa node.

Salamat

Gusto kong magpasalamat kang Andrey Saksonov, Pavel Popov, Anton Nehaev sa paghatag ug makapadasig nga feedback sa draft niini nga post nga nakatabang nako nga mas klaro.

Source: www.habr.com