Disusun Konfigurasi Sistim disebarkeun

Abdi hoyong ngabejaan Anjeun hiji mékanisme metot pikeun gawé bareng konfigurasi tina sistem disebarkeun. Konfigurasi ieu digambarkeun langsung dina basa disusun (Scala) ngagunakeun tipe aman. Tulisan ieu nyayogikeun conto konfigurasi sapertos kitu sareng ngabahas sagala rupa aspék palaksanaan konfigurasi anu disusun kana prosés pangwangunan sakabéh.

Disusun Konfigurasi Sistim disebarkeun

(english)

perkenalan

Ngawangun sistem distribusi anu dipercaya hartosna yén sadaya titik nganggo konfigurasi anu leres, disingkronkeun sareng titik anu sanés. Téknologi DevOps (terraform, ansible atanapi anu sapertos kitu) biasana dianggo pikeun otomatis ngahasilkeun file konfigurasi (sering khusus pikeun unggal titik). Kami ogé hoyong mastikeun yén sadaya titik komunikasi nganggo protokol anu sami (kalebet versi anu sami). Upami teu kitu, incompatibility bakal diwangun kana sistem disebarkeun kami. Di dunya JVM, salah sahiji akibat tina sarat ieu nyaéta versi perpustakaan anu sami anu ngandung seratan protokol kedah dianggo dimana-mana.

Kumaha upami nguji sistem anu disebarkeun? Tangtosna, urang nganggap yén sadaya komponén gaduh tés unit sateuacan urang teraskeun kana uji integrasi. (Supaya urang extrapolate hasil tés kana runtime, urang ogé kudu nyadiakeun susunan perpustakaan idéntik dina tahap nguji sarta dina runtime.)

Nalika damel sareng tés integrasi, sering langkung gampang ngagunakeun jalur kelas anu sami dimana-mana dina sadaya titik. Sadaya anu urang kedah laksanakeun nyaéta mastikeun yén classpath anu sami dianggo dina waktos runtime. (Sedengkeun éta sagemblengna mungkin pikeun ngajalankeun titik béda jeung classpaths béda, ieu teu nambahan pajeulitna kana sakabéh konfigurasi jeung kasusah jeung deployment sarta tés integrasi.) Pikeun kaperluan pos ieu, urang nganggap yén sakabéh titik bakal ngagunakeun classpath sarua.

Konfigurasi evolves kalawan aplikasi. Kami nganggo vérsi pikeun ngaidentipikasi tahapan évolusi program anu béda. Sigana logis ogé ngaidentipikasi versi béda tina konfigurasi. Sarta nempatkeun konfigurasi sorangan dina sistem kontrol versi. Upami ngan ukur aya hiji konfigurasi dina produksi, maka urang ngan saukur tiasa nganggo nomer versi. Upami urang nganggo seueur instansi produksi, maka urang peryogi sababaraha
cabang konfigurasi sarta labél tambahan salian versi (Contona, ngaran cabang). Ku cara ieu urang jelas tiasa ngaidentipikasi konfigurasi anu pasti. Unggal identifier konfigurasi unik pakait jeung kombinasi husus titik disebarkeun, palabuhan, sumberdaya éksternal, sarta versi perpustakaan. Pikeun kaperluan pos ieu kami bakal nganggap yen aya ngan hiji cabang na urang bisa nangtukeun konfigurasi dina cara biasa ngagunakeun tilu angka dipisahkeun ku titik (1.2.3).

Dina lingkungan modern, file konfigurasi jarang dijieun sacara manual. Beuki sering aranjeunna dihasilkeun nalika panyebaran sareng henteu keuna deui (supaya ulah megatkeun nanaon). Patarosan alami timbul: naha urang masih nganggo format téks pikeun nyimpen konfigurasi? Alternatif anu lumayan sigana nyaéta kamampuan ngagunakeun kode biasa pikeun konfigurasi sareng kauntungan tina cék waktos kompilasi.

Dina tulisan ieu kami bakal ngajalajah ide ngagambarkeun konfigurasi dina artefak anu disusun.

Konfigurasi disusun

Bagian ieu nyadiakeun conto konfigurasi statik disusun. Dua jasa saderhana dilaksanakeun - jasa gema sareng klien jasa gema. Dumasar kana dua jasa ieu, dua pilihan sistem dirakit. Dina hiji pilihan, duanana jasa lokasina dina titik sarua, dina pilihan séjén - dina titik béda.

Biasana sistem anu disebarkeun ngandung sababaraha titik. Anjeun tiasa ngaidentipikasi titik nganggo nilai tina sababaraha jinis NodeId:

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

atawa

case class NodeId(hostName: String)

atawa malah

object Singleton
type NodeId = Singleton.type

Node ngalakukeun sababaraha peran, aranjeunna ngajalankeun jasa sareng sambungan TCP / HTTP tiasa didamel diantara aranjeunna.

Pikeun ngajelaskeun sambungan TCP urang peryogi sahenteuna nomer port. Kami ogé hoyong ngagambarkeun protokol anu dirojong dina port éta pikeun mastikeun yén klien sareng server nganggo protokol anu sami. Urang bakal ngajelaskeun sambungan ngagunakeun kelas handap:

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

di mana Port - ngan hiji integer Int nunjukkeun rentang nilai ditarima:

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

Jenis refined

Tingali perpustakaan refined и milik urang laporan. Pondokna, perpustakaan ngidinan Anjeun pikeun nambahkeun konstrain kana jenis nu dipariksa dina waktos compile. Dina hal ieu, nilai angka port valid nyaéta integer 16-bit. Pikeun konfigurasi disusun, ngagunakeun perpustakaan refined teu wajib, tapi ngaronjatkeun kamampuh kompiler pikeun pariksa konfigurasi.

Pikeun protokol HTTP (REST), salian nomer port, urang ogé peryogi jalur pikeun jasa:

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

Jenis Phantom

Pikeun ngaidentipikasi protokol dina waktos kompilasi, kami nganggo parameter jinis anu henteu dianggo dina kelas. Kaputusan ieu kusabab kanyataan yén kami henteu nganggo conto protokol dina waktos runtime, tapi kami hoyong kompiler mariksa kasaluyuan protokol. Ku netepkeun protokol, urang moal tiasa ngalangkungan jasa anu teu pantes salaku kagumantungan.

Salah sahiji protokol umum nyaéta REST API sareng serialisasi Json:

sealed trait JsonHttpRestProtocol[RequestMessage, ResponseMessage]

di mana RequestMessage - jinis pamundut, ResponseMessage - tipe respon.
Tangtosna, urang tiasa nganggo déskripsi protokol sanés anu nyayogikeun katepatan déskripsi anu urang butuhkeun.

Pikeun kaperluan pos ieu, urang bakal ngagunakeun versi saderhana tina protokol:

sealed trait SimpleHttpGetRest[RequestMessage, ResponseMessage]

Di dieu pamundut téh string appended kana url jeung respon teh string balik dina awak respon HTTP.

Konfigurasi jasa dijelaskeun ku nami jasa, palabuhan, sareng katergantungan. Unsur-unsur ieu tiasa diwakilan dina Scala ku sababaraha cara (contona, HList-s, tipe data aljabar). Pikeun kaperluan pos ieu, urang bakal ngagunakeun Pola Kue jeung ngagambarkeun modul ngagunakeun trait'ov. (Pola Kue sanes unsur anu dipikabutuh pikeun pendekatan ieu. Ieu ngan saukur hiji palaksanaan anu mungkin.)

Dependensi antara jasa bisa digambarkeun salaku métode nu balik port EndPoint's tina titik séjén:

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

Pikeun nyieun layanan gema, anjeun peryogi nomer port sareng indikasi yén port éta ngadukung protokol écho. Urang bisa jadi teu nangtukeun port husus, sabab ... Tret ngidinan Anjeun pikeun nyatakeun métode tanpa palaksanaan (metode abstrak). Dina hal ieu, nalika nyieun konfigurasi beton, kompiler bakal merlukeun kami nyadiakeun hiji palaksanaan métode abstrak sarta nyadiakeun nomer port. Kusabab kami geus dilaksanakeun metoda, nalika nyieun konfigurasi husus, urang bisa jadi teu nangtukeun port béda. Nilai standar bakal dianggo.

Dina konfigurasi klien kami nyatakeun kagumantungan kana jasa gema:

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

Katergantunganna mangrupikeun jinis anu sami sareng jasa anu diékspor echoService. Khususna, dina klien gema kami meryogikeun protokol anu sami. Ku alatan éta, nalika nyambungkeun dua jasa, urang bisa mastikeun yén sagalana bakal jalan leres.

Palaksanaan jasa

A fungsi diperlukeun pikeun ngamimitian jeung ngeureunkeun layanan. (Kamampuhan pikeun ngeureunkeun layanan mangrupa kritik pikeun nguji.) Deui, aya sababaraha pilihan pikeun nerapkeun fitur sapertos (Contona, urang bisa make kelas tipe dumasar kana tipe konfigurasi). Pikeun kaperluan tulisan ieu kami bakal nganggo Pola Kue. Kami bakal ngawakilan jasa nganggo kelas cats.Resource, sabab Kelas ieu geus nyadiakeun sarana pikeun aman ngajamin sékrési sumberdaya bisi aya masalah. Pikeun kéngingkeun sumber daya, urang kedah nyayogikeun konfigurasi sareng kontéks runtime anu siap. Fungsi ngamimitian jasa tiasa sapertos kieu:

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

di mana

  • Config - tipe konfigurasi pikeun layanan ieu
  • AddressResolver - obyék runtime anu ngamungkinkeun anjeun mendakan alamat titik anu sanés (tingali di handap)

jeung tipe séjén ti perpustakaan cats:

  • F[_] - jinis pangaruh (dina kasus pangbasajanna F[A] ngan bisa jadi hiji fungsi () => A. Dina tulisan ieu kami bakal nganggo cats.IO.)
  • Reader[A,B] - leuwih atawa kurang sinonim jeung fungsi A => B
  • cats.Resource - sumberdaya nu bisa didapet tur dileupaskeun
  • Timer - timer (ngamungkinkeun anjeun bobo sakedap sareng ngukur interval waktos)
  • ContextShift - analog ExecutionContext
  • Applicative - kelas tipe pangaruh nu ngidinan Anjeun pikeun ngagabungkeun épék individu (ampir monad a). Dina aplikasi anu langkung kompleks sigana langkung saé dianggo Monad/ConcurrentEffect.

Ngagunakeun signature fungsi ieu urang bisa nerapkeun sababaraha layanan. Contona, layanan nu teu nanaon:

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

(Cm. sumber, dimana jasa séjén dilaksanakeun - layanan gema, echo klien
и Controllers hirupna.)

Titik mangrupikeun obyék anu tiasa ngaluncurkeun sababaraha jasa (peluncuran ranté sumber daya dipastikeun ku Pola Kue):

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

Punten dicatet yén kami netepkeun jinis konfigurasi pasti anu diperyogikeun pikeun titik ieu. Upami urang hilap netepkeun salah sahiji jinis konfigurasi anu diperyogikeun ku jasa khusus, bakal aya kasalahan kompilasi. Ogé, urang moal bisa ngamimitian titik iwal kami nyadiakeun sababaraha objék tina tipe luyu jeung sakabeh data diperlukeun.

Resolusi Ngaran Host

Pikeun nyambung ka host jauh, urang peryogi alamat IP nyata. Ieu mungkin nu alamat bakal jadi dipikawanoh engké ti sesa konfigurasi. Janten urang peryogi fungsi anu mapkeun ID titik ka alamat:

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

Aya sababaraha cara pikeun nerapkeun fungsi ieu:

  1. Upami alamatna dikenal ku urang sateuacan nyebarkeun, maka urang tiasa ngahasilkeun kode Scala
    alamat lajeng ngajalankeun ngawangun. Ieu bakal nyusun sareng ngajalankeun tés.
    Dina hal ieu, fungsi bakal dipikawanoh statik sarta bisa digambarkeun dina kode salaku pemetaan a Map[NodeId, NodeAddress].
  2. Dina sababaraha kasus, alamat sabenerna ngan dipikawanoh sanggeus titik geus dimimitian.
    Dina hal ieu, urang tiasa nerapkeun "jasa penemuan" anu dijalankeun sateuacan titik anu sanés sareng sadaya titik bakal ngadaptar sareng jasa ieu sareng nyuhunkeun alamat titik anu sanés.
  3. Lamun urang bisa ngaropéa /etc/hosts, teras anjeun tiasa nganggo hostname anu tos disetel (sapertos my-project-main-node и echo-backend) jeung saukur numbu ngaran ieu
    kalawan alamat IP salila deployment.

Dina tulisan ieu kami moal nganggap kasus ieu sacara langkung rinci. Pikeun urang
dina conto kaulinan, sadaya titik bakal gaduh alamat IP anu sami - 127.0.0.1.

Salajengna, urang nganggap dua pilihan pikeun sistem anu disebarkeun:

  1. Nempatkeun sadaya jasa dina hiji titik.
  2. Sareng nyayogikeun jasa gema sareng klien gema dina titik anu béda.

Konfigurasi pikeun hiji titik:

Konfigurasi titik tunggal

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

Obyék ngalaksanakeun konfigurasi tina klien sareng server. Konfigurasi waktos-ka-hirup ogé dianggo supados saatos interval lifetime ngeureunkeun program. (Ctrl-C ogé tiasa dianggo sareng ngabebaskeun sadaya sumber daya kalayan leres.)

Set sarua konfigurasi sarta palaksanaan Tret bisa dipaké pikeun nyieun sistem diwangun ku dua titik misah:

Konfigurasi dua titik

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

Kadé! Perhatikeun kumaha jasa numbu. Urang nangtukeun hiji layanan dilaksanakeun ku hiji titik salaku palaksanaan sahiji metodeu kagumantungan titik sejen urang. Jinis kagumantungan dipariksa ku compiler, sabab ngandung tipe protokol. Nalika dijalankeun, kagumantungan bakal ngandung ID titik udagan anu leres. Hatur nuhun kana skéma ieu, urang nangtukeun jumlah port persis sakali tur salawasna dijamin ngarujuk kana port bener.

Palaksanaan dua titik sistem

Pikeun konfigurasi ieu, kami nganggo palaksanaan jasa anu sami tanpa parobahan. Hijina bédana nyaéta yén urang ayeuna gaduh dua objék anu ngalaksanakeun sét jasa anu béda:

  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
  }

Titik munggaran ngalaksanakeun server sareng ngan ukur peryogi konfigurasi server. Titik kadua ngalaksanakeun klien sareng nganggo bagian anu béda tina konfigurasi. Ogé duanana titik butuh manajemén hirupna. Titik server dijalankeun salamina dugi ka dieureunkeun SIGTERM'om, sarta titik klien terminates sanggeus sababaraha waktu. Cm. aplikasi launcher.

Prosés pangwangunan umum

Hayu urang tingali kumaha pendekatan konfigurasi ieu mangaruhan prosés pangwangunan sakabéh.

Konfigurasi bakal disusun babarengan jeung sesa kode jeung hiji artefak (.jar) bakal dihasilkeun. Sigana asup akal nempatkeun konfigurasi dina artefak misah. Ieu kusabab urang tiasa gaduh sababaraha konfigurasi dumasar kana kode anu sami. Deui, kasebut nyaéta dimungkinkeun pikeun ngahasilkeun artefak pakait jeung cabang konfigurasi béda. Gumantung kana versi husus perpustakaan disimpen babarengan jeung konfigurasi, sarta versi ieu disimpen salawasna iraha wae urang mutuskeun pikeun nyebarkeun éta versi konfigurasi.

Sakur parobahan konfigurasi robah jadi parobahan kode. Ku kituna, unggal
parobahan bakal katutupan ku prosés jaminan kualitas normal:

Tiket dina tracker bug -> PR -> review -> ngagabung jeung cabang relevan ->
integrasi -> deployment

Konsékuansi utama palaksanaan konfigurasi disusun nyaéta:

  1. Konfigurasi bakal konsisten dina sadaya titik sistem anu disebarkeun. Kusabab kanyataan yén sadaya titik nampi konfigurasi anu sami tina hiji sumber.

  2. Masalahna pikeun ngarobih konfigurasi ngan ukur dina salah sahiji titik. Ku alatan éta, "konfigurasi drift" saperti teu mirip.

  3. Janten langkung hese pikeun ngarobih sakedik kana konfigurasi.

  4. Paling parobahan konfigurasi bakal lumangsung salaku bagian tina prosés ngembangkeun sakabéh tur bakal tunduk kana review.

Naha kuring peryogi gudang anu misah pikeun nyimpen konfigurasi produksi? Konfigurasi ieu tiasa ngandung kecap akses sareng inpormasi sénsitip sanés anu kami hoyong ngawatesan aksés. Dumasar ieu, sigana asup akal pikeun nyimpen konfigurasi ahir dina gudang anu misah. Anjeun tiasa ngabagi konfigurasi kana dua bagian-hiji ngandung setélan konfigurasi anu tiasa diaksés ku umum sareng hiji ngandung setélan anu diwatesan. Ieu bakal ngamungkinkeun sabagéan ageung pamekar gaduh aksés kana setélan umum. Separation Ieu gampang pikeun ngahontal ngagunakeun Tret panengah ngandung nilai standar.

Mungkin variasi

Hayu urang coba ngabandingkeun konfigurasi disusun kalawan sababaraha alternatif umum:

  1. file téks dina mesin target.
  2. Toko nilai konci terpusat (etcd/zookeeper).
  3. komponén prosés nu bisa reconfigured / restarted tanpa restarting prosés.
  4. Nyimpen konfigurasi di luar artefak sareng kontrol versi.

file téks nyadiakeun kalenturan signifikan dina watesan parobahan leutik. Administrator sistem tiasa lebet kana titik jauh, ngadamel parobihan kana file anu cocog sareng ngabalikan deui jasa. Pikeun sistem badag, kumaha oge, kalenturan misalna bisa jadi teu desirable. Parobihan anu dilakukeun henteu aya jejak dina sistem anu sanés. Teu aya anu marios parobihan. Hésé pikeun nangtoskeun saha anu leres-leres ngadamel parobihan sareng naon alesanana. Parobahan teu diuji. Upami sistemna disebarkeun, maka pangurus tiasa hilap ngadamel parobihan anu aya dina titik anu sanés.

(Ieu ogé kudu dicatet yén ngagunakeun konfigurasi disusun teu nutup kamungkinan ngagunakeun file téks dina mangsa nu bakal datang. Ieu bakal cukup pikeun nambahkeun hiji parser na validator nu ngahasilkeun tipe sarua salaku kaluaran. Config, sareng anjeun tiasa nganggo file téks. Éta langsung nuturkeun yén pajeulitna sistem sareng konfigurasi anu disusun rada kirang tina pajeulitna sistem anu nganggo file téks, sabab file téks merlukeun kode tambahan.)

Toko konci-nilai terpusat mangrupikeun mékanisme anu hadé pikeun nyebarkeun parameter meta tina aplikasi anu disebarkeun. Urang kedah mutuskeun naon parameter konfigurasi sareng naon waé data. Hayu urang boga fungsi C => A => B, sareng parameter C jarang robah, sarta data A - mindeng. Dina hal ieu urang bisa disebutkeun yen C - parameter konfigurasi, jeung A - data. Nembongan yen parameter konfigurasi béda ti data nu aranjeunna umumna robah kirang remen ti data. Ogé, data biasana asalna tina hiji sumber (ti pamaké), sarta parameter konfigurasi ti nu sejen (ti administrator sistem).

Upami jarang ngarobah parameter kedah diropéa tanpa ngamimitian deui program, maka ieu sering tiasa nyababkeun komplikasi program, sabab urang kedah kumaha waé ngirimkeun parameter, nyimpen, nga-parse sareng pariksa, sareng ngolah nilai anu salah. Ku alatan éta, tina sudut pandang pikeun ngurangan pajeulitna program, ngajadikeun rasa pikeun ngurangan jumlah parameter nu bisa ngarobah salila operasi program (atawa teu ngarojong parameter misalna).

Pikeun kaperluan tulisan ieu, urang bakal ngabédakeun antara parameter statik sareng dinamis. Lamun logika jasa merlukeun ngarobah parameter salila operasi program, urang bakal nelepon parameter sapertos dinamis. Upami teu kitu, pilihanna statik sareng tiasa dikonpigurasi nganggo konfigurasi anu disusun. Pikeun reconfiguration dinamis, urang bisa jadi kudu mékanisme pikeun balikan deui bagian tina program jeung parameter anyar, sarupa jeung kumaha prosés sistem operasi restarted. (Dina pamadegan urang, éta sasaena ulah reconfiguration real-time, saprak ieu ngaronjatkeun pajeulitna sistem. Mun mungkin, eta leuwih hade migunakeun kamampuhan OS baku pikeun restarting prosés.)

Hiji aspék penting tina ngagunakeun konfigurasi statik nu ngajadikeun jalma mertimbangkeun reconfiguration dinamis nyaéta waktu nu diperlukeun pikeun sistem reboot sanggeus apdet konfigurasi (downtime). Nyatana, upami urang kedah parobihan kana konfigurasi statik, urang kedah ngabalikan deui sistem supados nilai-nilai énggal tiasa dianggo. Masalah downtime variasina dina severity pikeun sistem béda. Dina sababaraha kasus, anjeun tiasa ngajadwalkeun reboot dina waktos beban minimal. Lamun perlu nyadiakeun layanan kontinyu, Anjeun bisa nerapkeun sambungan AWS ELB draining. Dina waktos anu sami, nalika urang kedah reboot sistem, urang ngaluncurkeun conto paralel tina sistem ieu, pindahkeun kasaimbangan ka dinya, sareng ngantosan sambungan anu lami parantos réngsé. Sanggeus kabéh sambungan heubeul geus terminated, urang mareuman conto heubeul tina sistem.

Hayu urang ayeuna mertimbangkeun masalah nyimpen konfigurasi di jero atawa di luar artefak. Upami urang nyimpen konfigurasi di jero artefak, sahenteuna urang ngagaduhan kasempetan pikeun pariksa kabeneran konfigurasi nalika ngarakit artefak. Upami konfigurasina aya di luar artefak anu dikontrol, hese ngalacak saha anu ngarobih file ieu sareng kunaon. Kumaha pentingna? Numutkeun kami, pikeun seueur sistem produksi, penting pikeun gaduh konfigurasi anu stabil sareng kualitas luhur.

Versi artefak ngamungkinkeun anjeun pikeun nangtoskeun iraha éta diciptakeun, nilai naon anu dikandungna, fungsi naon anu diaktipkeun / ditumpurkeun, sareng saha waé anu tanggung jawab pikeun parobahan dina konfigurasi. Tangtu, nyimpen konfigurasi dina artefak merlukeun sababaraha usaha, jadi Anjeun kudu nyieun kaputusan informed.

Naros sareng kontra

Abdi hoyong cicing dina pro sareng kontra ngeunaan téknologi anu diusulkeun.

kaunggulan

Di handap ieu daptar fitur utama konfigurasi sistem distribusi anu disusun:

  1. Pariksa konfigurasi statik. Ngidinan anjeun pastikeun yén
    konfigurasi bener.
  2. Basa konfigurasi euyeub. Ilaharna, métode konfigurasi séjén anu dugi ka substitusi variabel string paling. Lamun make Scala, rupa-rupa fitur basa sadia pikeun ngaronjatkeun konfigurasi Anjeun. Salaku conto urang tiasa nganggo
    Tret pikeun nilai standar, ngagunakeun objék pikeun parameter grup, urang tiasa ningali vals nyatakeun ngan sakali (Gering) dina lingkup enclosing. Anjeun tiasa instantiate sagala kelas langsung di jero konfigurasi (Seq, Map, kelas custom).
  3. DSL. Scala gaduh sababaraha fitur basa anu ngagampangkeun ngadamel DSL. Kasebut nyaéta dimungkinkeun pikeun ngamangpaatkeun fitur ieu sarta nerapkeun basa konfigurasi nu leuwih merenah pikeun grup targét pamaké, ku kituna konfigurasi sahenteuna bisa dibaca ku ahli domain. Spesialis tiasa, contona, ilubiung dina prosés review konfigurasi.
  4. Integritas sareng sinkron antara titik. Salah sahiji kaunggulan gaduh konfigurasi sakabéh sistem disebarkeun disimpen dina hiji titik nyaéta yén sakabéh nilai dinyatakeun persis sakali lajeng dipaké deui dimana wae aranjeunna diperlukeun. Nganggo jinis phantom pikeun nyatakeun palabuhan mastikeun yén titik-titik ngagunakeun protokol anu cocog dina sadaya konfigurasi sistem anu leres. Ngabogaan katergantungan wajib anu eksplisit antara titik mastikeun yén sadaya jasa disambungkeun.
  5. Parobahan kualitas luhur. Ngarobih konfigurasi nganggo prosés pangembangan umum ngamungkinkeun pikeun ngahontal standar kualitas luhur pikeun konfigurasi ogé.
  6. Pembaruan konfigurasi sakaligus. deployment sistem otomatis sanggeus parobahan konfigurasi mastikeun yén sakabéh titik diropéa.
  7. Nyederhanakeun aplikasi. Aplikasina henteu peryogi parsing, mariksa konfigurasi, atanapi nanganan nilai anu salah. Ieu ngurangan pajeulitna aplikasi. (Sababaraha pajeulitna konfigurasi dititénan dina conto urang teu hiji atribut tina konfigurasi disusun, tapi ngan kaputusan sadar disetir ku kahayang pikeun nyadiakeun kaamanan tipe gede.) Ieu rada gampang mulang ka konfigurasi biasa - ngan nerapkeun leungit. bagian. Ku alatan éta, anjeun tiasa, contona, mimitian ku konfigurasi disusun, deferring palaksanaan bagian-bagian nu teu perlu nepi ka waktu nalika eta bener diperlukeun.
  8. Konfigurasi diverifikasi. Kusabab parobahan konfigurasi nuturkeun nasib biasa tina sagala parobahan séjénna, kaluaran urang meunang mangrupa artefak jeung versi unik. Hal ieu ngamungkinkeun urang, contona, mulang ka versi saméméhna tina konfigurasi lamun perlu. Urang malah bisa make konfigurasi ti sataun katukang jeung sistem bakal dianggo persis sarua. Konfigurasi stabil ningkatkeun prediksi sareng reliabilitas sistem anu disebarkeun. Kusabab konfigurasi dibereskeun dina tahap kompilasi, rada hese pikeun palsu dina produksi.
  9. Modularitas. Kerangka anu diusulkeun nyaéta modular sareng modul tiasa digabungkeun ku cara anu béda pikeun nyiptakeun sistem anu béda. Khususna, anjeun tiasa ngonpigurasikeun sistem pikeun ngajalankeun dina titik tunggal dina hiji perwujudan, sareng dina sababaraha titik dina anu sanés. Anjeun tiasa nyiptakeun sababaraha konfigurasi pikeun instansi produksi sistem.
  10. Nguji. Ku ngagentos jasa individu sareng objék bohongan, anjeun tiasa nampi sababaraha vérsi sistem anu cocog pikeun diuji.
  11. Tés integrasi. Ngabogaan konfigurasi tunggal pikeun sakabéh sistem disebarkeun ngamungkinkeun pikeun ngajalankeun sakabeh komponen dina lingkungan dikawasa salaku bagian tina nguji integrasi. Gampang ditiru, contona, kaayaan dimana sababaraha titik tiasa diaksés.

Kalemahan jeung watesan

Konfigurasi disusun béda ti pendekatan konfigurasi sejen tur bisa jadi teu cocog pikeun sababaraha aplikasi. Di handap ieu aya sababaraha kalemahan:

  1. Konfigurasi statik. Kadang-kadang anjeun kedah gancang ngabenerkeun konfigurasi dina produksi, ngalangkungan sadaya mékanisme pelindung. Kalawan pendekatan ieu bisa jadi leuwih hese. Sahenteuna, kompilasi sareng panyebaran otomatis bakal diperyogikeun. Ieu duanana mangrupa fitur mangpaat tina pendekatan sarta disadvantage dina sababaraha kasus.
  2. Generasi konfigurasi. Upami file konfigurasi dibangkitkeun ku alat otomatis, usaha tambahan tiasa diperyogikeun pikeun ngahijikeun naskah ngawangun.
  3. Parabot. Ayeuna, utilitas sareng téknik anu dirancang pikeun dianggo sareng konfigurasi dumasar kana file téks. Henteu sadayana utilitas / téknik sapertos kitu bakal sayogi dina konfigurasi anu disusun.
  4. Peryogikeun parobahan sikap. Pamekar sareng DevOps biasa kana file téks. Gagasan pikeun nyusun konfigurasi tiasa rada teu kaduga sareng teu biasa sareng nyababkeun panolakan.
  5. A prosés ngembangkeun kualitas luhur diperlukeun. Dina raraga nyaman ngagunakeun konfigurasi disusun, automation pinuh tina prosés ngawangun sarta deploying aplikasi (CI / CD) diperlukeun. Upami teu kitu, éta bakal rada teu merenah.

Hayu urang ogé ngahudangkeun sababaraha watesan tina conto anu dianggap anu henteu aya hubunganana sareng ideu konfigurasi anu disusun:

  1. Upami kami nyayogikeun inpormasi konfigurasi anu teu perlu anu henteu dianggo ku node, maka kompiler moal ngabantosan urang ngadeteksi palaksanaan anu leungit. Masalah ieu tiasa direngsekeun ku ngantunkeun Pola Kue sareng nganggo jinis anu langkung kaku, contona, HList atawa tipe data aljabar (kelas kasus) pikeun ngagambarkeun konfigurasi.
  2. Aya garis dina file konfigurasi nu teu patali jeung konfigurasi sorangan: (package, import, deklarasi objék; override def's pikeun parameter nu boga nilai standar). Ieu sawaréh tiasa dihindari upami anjeun nerapkeun DSL anjeun nyalira. Sajaba ti éta, tipe séjén konfigurasi (contona, XML) ogé maksakeun larangan tangtu dina struktur file.
  3. Pikeun kaperluan pos ieu, urang teu tempo reconfiguration dinamis tina gugusan titik sarupa.

kacindekan

Dina tulisan ieu, urang ngajalajah ide ngagambarkeun konfigurasi dina kode sumber nganggo kamampuan canggih tina sistem jinis Scala. Pendekatan ieu tiasa dianggo dina sagala rupa aplikasi salaku gaganti metode konfigurasi tradisional dumasar kana xml atanapi file téks. Sanaos conto urang dilaksanakeun dina Scala, ideu anu sami tiasa dialihkeun ka basa anu disusun sanés (sapertos Kotlin, C #, Swift, ...). Anjeun tiasa nyobian pendekatan ieu dina salah sahiji proyék di handap ieu, sarta lamun teu dianggo, pindah ka file téks, nambahkeun bagian leungit.

Alami, konfigurasi disusun merlukeun prosés ngembangkeun kualitas luhur. Sabalikna, kualitas luhur sareng reliabilitas konfigurasi dipastikeun.

Pendekatan anu dianggap tiasa diperpanjang:

  1. Anjeun tiasa nganggo makro pikeun ngalakukeun cék waktos kompilasi.
  2. Anjeun tiasa nerapkeun DSL pikeun nampilkeun konfigurasi ku cara anu tiasa diaksés ku pangguna akhir.
  3. Anjeun tiasa nerapkeun manajemén sumberdaya dinamis sareng adjustment konfigurasi otomatis. Contona, ngarobah jumlah titik dina klaster merlukeun yén (1) unggal titik narima konfigurasi rada béda; (2) manajer klaster narima informasi ngeunaan titik anyar.

Ngahaturkeun

Abdi hoyong hatur Andrei Saksonov, Pavel Popov jeung Anton Nekhaev pikeun kritik konstruktif maranéhanana ngeunaan draf artikel.

sumber: www.habr.com

Tambahkeun komentar