Конфигуратсияи системаҳои тақсимшуда

Ман мехоҳам ба шумо як механизми ҷолибро барои кор бо конфигуратсияи системаи тақсимшуда нақл кунам. Конфигуратсия мустақиман бо забони тартибдодашуда (Scala) бо истифода аз намудҳои бехатар муаррифӣ карда мешавад. Ин паём намунаи чунин конфигуратсияро пешкаш мекунад ва ҷанбаҳои гуногуни татбиқи конфигуратсияи тартибдодашуда дар раванди умумии рушдро баррасӣ мекунад.

Конфигуратсияи системаҳои тақсимшуда

(англисӣ)

Муқаддима

Сохтани системаи боэътимоди тақсимшуда маънои онро дорад, ки ҳама гиреҳҳо конфигуратсияи дурустро истифода мебаранд, ки бо дигар гиреҳҳо ҳамоҳанг карда шудаанд. Технологияҳои DevOps (terraform, ansible ё чизе монанди он) одатан барои ба таври худкор тавлид кардани файлҳои конфигуратсия истифода мешаванд (аксар вақт барои ҳар як гиреҳ мушаххас). Мо инчунин мехоҳем итминон дошта бошем, ки ҳама гиреҳҳои иртиботӣ протоколҳои якхеларо истифода мебаранд (аз ҷумла як версия). Дар акси ҳол, номувофиқатӣ дар системаи тақсимшудаи мо сохта мешавад. Дар ҷаҳони JVM, як натиҷаи ин талабот ин аст, ки ҳамон версияи китобхонаи дорои паёмҳои протоколӣ бояд дар ҳама ҷо истифода шавад.

Дар бораи санҷиши системаи тақсимшуда чӣ гуфтан мумкин аст? Албатта, мо тахмин мезанем, ки ҳама ҷузъҳо пеш аз гузаштан ба санҷиши ҳамгироӣ санҷишҳои воҳид доранд. (Барои он ки мо натиҷаҳои санҷишро ба вақти корӣ экстраполятсия кунем, мо бояд инчунин маҷмӯи якхелаи китобхонаҳоро дар марҳилаи санҷиш ва вақти корӣ таъмин кунем.)

Ҳангоми кор бо санҷишҳои ҳамгироӣ, истифода бурдани як роҳи синф дар ҳама ҷо дар ҳама гиреҳҳо осонтар аст. Мо танҳо бояд ин аст, ки ҳамон як роҳи синф дар вақти корӣ истифода шавад. (Гарчанде ки иҷро кардани гиреҳҳои гуногун бо роҳҳои синфҳои гуногун комилан имконпазир аст, ин ба конфигуратсияи умумӣ ва мушкилот бо санҷишҳои ҷобаҷогузорӣ ва ҳамгироӣ илова мекунад.) Барои ҳадафҳои ин мақола, мо тахмин мезанем, ки ҳама гиреҳҳо як роҳи синфро истифода хоҳанд кард.

Конфигуратсия бо барнома инкишоф меёбад. Мо версияҳоро барои муайян кардани марҳилаҳои гуногуни эволютсияи барнома истифода мебарем. Ба назар мантиқӣ инчунин муайян кардани версияҳои гуногуни конфигуратсияҳо. Ва худи конфигуратсияро дар системаи идоракунии версия ҷойгир кунед. Агар дар истеҳсолот танҳо як конфигуратсия мавҷуд бошад, мо метавонем танҳо рақами версияро истифода барем. Агар мо намунаҳои зиёди истеҳсолиро истифода барем, ба мо якчанд лозим меояд
шохаҳои конфигуратсия ва тамғаи иловагӣ ба ғайр аз версия (масалан, номи филиал). Бо ин роҳ мо метавонем конфигуратсияи дақиқро муайян кунем. Ҳар як идентификатори конфигуратсия ба маҷмӯи мушаххаси гиреҳҳои тақсимшуда, портҳо, захираҳои беруна ва версияҳои китобхона мувофиқат мекунад. Барои мақсадҳои ин мақола мо тахмин мезанем, ки танҳо як шоха вуҷуд дорад ва мо метавонем конфигуратсияро ба таври муқаррарӣ бо истифода аз се рақами бо нуқта ҷудошуда муайян кунем (1.2.3).

Дар муҳитҳои муосир, файлҳои конфигуратсия хеле кам ба таври дастӣ сохта мешаванд. Бештари вақт онҳо ҳангоми ҷойгиркунӣ тавлид мешаванд ва дигар ламс карда намешаванд (то чизеро вайрон накунед). Саволи табиӣ ба миён меояд: чаро мо то ҳол формати матниро барои нигоҳ доштани конфигуратсия истифода мебарем? Чунин ба назар мерасад, ки алтернативаи қобили истифода қобилияти истифодаи рамзи муқаррарӣ барои конфигуратсия ва баҳрабардорӣ аз санҷишҳои вақти тартибдиҳӣ мебошад.

Дар ин мақола мо идеяи муаррифии конфигуратсияро дар дохили артефакти тартибдодашуда меомӯзем.

Конфигуратсияи тартибдодашуда

Ин бахш намунаи конфигуратсияи статикии тартибдодашударо пешкаш мекунад. Ду хидмати оддӣ амалӣ карда мешавад - хидмати эхо ва муштарии хидмати эхо. Дар асоси ин ду хидмат, ду варианти система ҷамъ карда мешаванд. Дар як вариант, ҳарду хидматҳо дар як гиреҳ ҷойгиранд, дар варианти дигар - дар гиреҳҳои гуногун.

Одатан системаи тақсимшуда якчанд гиреҳҳоро дар бар мегирад. Шумо метавонед гиреҳҳоро бо истифода аз арзишҳои як навъ муайян кунед 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 - танҳо як адад Int бо нишон додани доираи арзишҳои қобили қабул:

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)

Намудҳои фантом

Барои муайян кардани протокол дар вақти тартибдиҳӣ, мо параметри навъиро истифода мебарем, ки дар дохили синф истифода намешавад. Ин тасмим аз он иборат аст, ки мо дар вақти иҷро як мисоли протоколро истифода намебарем, аммо мо мехоҳем, ки компилятор мутобиқати протоколро тафтиш кунад. Бо муайян кардани протокол, мо наметавонем хидмати номуносибро ҳамчун вобастагӣ гузаронем.

Яке аз протоколҳои маъмул REST API бо силсиласозии Json мебошад:

sealed trait JsonHttpRestProtocol[RequestMessage, ResponseMessage]

ки RequestMessage - намуди дархост, ResponseMessage - намуди ҷавоб.
Албатта, мо метавонем тавсифи протоколҳои дигареро истифода барем, ки дақиқии тавсифи моро таъмин мекунанд.

Барои мақсадҳои ин мақола, мо версияи соддакардашудаи протоколро истифода хоҳем кард:

sealed trait SimpleHttpGetRest[RequestMessage, ResponseMessage]

Дар ин ҷо дархост сатрест, ки ба URL замима шудааст ва посух сатри баргардонидашуда дар бадани посухи HTTP мебошад.

Конфигуратсияи хидмат бо номи хидмат, портҳо ва вобастагӣ тавсиф карда мешавад. Ин унсурҳоро дар Scala бо чанд роҳ муаррифӣ кардан мумкин аст (масалан, HList-s, намудҳои додаҳои алгебравӣ). Барои мақсадҳои ин мақола, мо намунаи тортро истифода мебарем ва модулҳоро бо истифода аз он муаррифӣ мекунем trait'ов. (Намунаи торт ҷузъи зарурии ин равиш нест. Ин танҳо як амали имконпазир аст.)

Вобастагии байни хадамотро метавон ҳамчун усулҳое муаррифӣ кард, ки портҳоро бармегардонанд EndPoint's аз гиреҳҳои дигар:

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

Барои эҷоди хидмати эхо, ба шумо танҳо рақами порт лозим аст ва нишонаи он, ки порт протоколи эхоро дастгирӣ мекунад. Мо шояд бандари мушаххасро муайян накунем, зеро... хусусиятҳо ба шумо имкон медиҳанд, ки усулҳоро бидуни татбиқ эълон кунед (усулҳои абстрактӣ). Дар ин ҳолат, ҳангоми сохтани конфигуратсияи мушаххас, компилятор аз мо талаб мекунад, ки татбиқи усули абстрактӣ ва рақами портро пешниҳод кунем. Азбаски мо ин усулро татбиқ кардем, ҳангоми сохтани конфигуратсияи мушаххас, мо метавонем порти дигарро муайян накунем. Арзиши пешфарз истифода мешавад.

Дар конфигуратсияи муштарӣ мо вобастагӣ аз хидмати echo эълон мекунем:

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

Вобастагӣ бо хидмати содиротӣ як навъ аст echoService. Аз ҷумла, дар муштарии echo мо ҳамон протоколро талаб мекунем. Аз ин рӯ, ҳангоми пайваст кардани ду хидмат, мо боварӣ дошта метавонем, ки ҳама чиз дуруст кор мекунад.

Татбиқи хидматҳо

Барои оғоз ва қатъ кардани хидмат функсия лозим аст. (Қобилияти қатъи хидмат барои санҷиш муҳим аст.) Боз, якчанд вариант барои татбиқи чунин хусусият вуҷуд дорад (масалан, мо метавонем синфҳои навъиро дар асоси намуди конфигуратсия истифода барем). Барои мақсадҳои ин мақола мо намунаи тортро истифода хоҳем бурд. Мо хидматро бо истифода аз синф муаррифӣ хоҳем кард 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. Дар ин мақола мо истифода хоҳем кард 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 Pattern таъмин карда мешавад):

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

Лутфан таваҷҷӯҳ намоед, ки мо навъи дақиқи конфигуратсияро, ки барои ин гиреҳ лозим аст, муайян мекунем. Агар мо муайян кардани яке аз намудҳои конфигуратсияро, ки аз ҷониби хидмати мушаххас талаб карда мешавад, фаромӯш кунем, хатогии ҷамъоварӣ ба амал меояд. Инчунин, мо гиреҳро оғоз карда наметавонем, агар мо ягон объекти навъи мувофиқро бо тамоми маълумоти зарурӣ таъмин накунем.

Ҳалли номи мизбон

Барои пайваст шудан ба мизбони дурдаст, ба мо суроғаи воқеии IP лозим аст. Мумкин аст, ки суроға дертар аз қисми боқимондаи конфигуратсия маълум шавад. Ҳамин тавр, ба мо функсияе лозим аст, ки ID гиреҳро ба суроға харита кунад:

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

Якчанд роҳҳо барои татбиқи ин функсия вуҷуд доранд:

  1. Агар суроғаҳо пеш аз ҷойгиркунӣ ба мо маълум шаванд, мо метавонем бо коди Scala тавлид кунем
    суроғаҳо ва сипас сохтмонро иҷро кунед. Ин санҷишҳоро тартиб медиҳад ва иҷро мекунад.
    Дар ин ҳолат, функсия ба таври статикӣ маълум мешавад ва метавонад дар код ҳамчун харитасозӣ муаррифӣ карда шавад Map[NodeId, NodeAddress].
  2. Дар баъзе ҳолатҳо, суроғаи воқеӣ танҳо пас аз оғоз шудани гиреҳ маълум мешавад.
    Дар ин ҳолат, мо метавонем "хизматрасонии кашф" -ро иҷро кунем, ки пеш аз гиреҳҳои дигар кор мекунад ва ҳама гиреҳҳо бо ин хидмат сабти ном мешаванд ва суроғаҳои гиреҳҳои дигарро дархост мекунанд.
  3. Агар мо метавонем тағир диҳем /etc/hosts, пас шумо метавонед номҳои мизбони пешакӣ муайяншударо истифода баред (масалан my-project-main-node и echo-backend) ва танҳо ин номҳоро пайванд кунед
    бо суроғаҳои IP ҳангоми ҷойгиркунӣ.

Дар ин мақола мо ин парвандаҳоро ба таври муфассал баррасӣ намекунем. Барои мо
дар мисоли бозича, ҳама гиреҳҳо суроғаи IP-и якхела доранд - 127.0.0.1.

Баъдан, мо ду вариантро барои системаи тақсимшуда баррасӣ мекунем:

  1. Ҷойгир кардани ҳама хидматҳо дар як гиреҳ.
  2. Ва ҷойгир кардани хидмати эхо ва муштарии эхо дар гиреҳҳои гуногун.

Конфигуратсия барои як гиреҳ:

Конфигуратсияи гиреҳи ягона

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

Объект конфигуратсияи ҳам муштарӣ ва ҳам серверро амалӣ мекунад. A конфигуратсияи вақт-ба-зиндагӣ низ истифода бурда мешавад, то ки пас аз фосилаи lifetime барномаро қатъ кунед. (Ctrl-C инчунин ҳама захираҳоро дуруст кор мекунад ва озод мекунад.)

Барои сохтани системае, ки иборат аст аз ҳамон маҷмӯи конфигуратсияҳо ва хусусиятҳои амалӣ истифода бурдан мумкин аст ду гиреҳи алоҳида:

Конфигуратсияи ду гиреҳ

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

Муҳим! Аҳамият диҳед, ки хидматҳо чӣ гуна алоқаманданд. Мо хидматеро, ки як гиреҳ иҷро мекунад, ҳамчун амалисозии усули вобастагии гиреҳи дигар муайян мекунем. Навъи вобастагӣ аз ҷониби компилятор тафтиш карда мешавад, зеро намуди протоколро дар бар мегирад. Ҳангоми иҷро, вобастагӣ ID гиреҳи дурусти ҳадафро дар бар мегирад. Бо шарофати ин схема, мо рақами портро як маротиба муайян мекунем ва ҳамеша кафолат дода мешавад, ки ба порти дуруст муроҷиат кунем.

Амалисозии ду гиреҳи система

Барои ин конфигуратсия мо ҳамон амалҳои хидматро бидуни тағирот истифода мебарем. Ягона фарқият дар он аст, ки мо ҳоло ду объект дорем, ки маҷмӯи гуногуни хидматҳоро амалӣ мекунанд:

  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
  }

Гиреҳи аввал серверро амалӣ мекунад ва танҳо ба конфигуратсияи сервер ниёз дорад. Гиреҳи дуюм муштариро амалӣ мекунад ва қисми дигари конфигуратсияро истифода мебарад. Инчунин ҳарду гиреҳ ба идоракунии умри худ ниёз доранд. Гиреҳи сервер то қатъ шудани он номуайян кор мекунад SIGTERM'om, ва гиреҳи муштарӣ пас аз чанд вақт қатъ мешавад. См. барномаи оғозкунанда.

Раванди рушди умумӣ

Биёед бубинем, ки ин равиши конфигуратсия ба раванди умумии рушд чӣ гуна таъсир мерасонад.

Конфигуратсия дар якҷоягӣ бо қисми боқимондаи код тартиб дода мешавад ва артефакт (.jar) тавлид мешавад. Чунин ба назар мерасад, ки конфигуратсияро дар артефакти алоҳида гузоштан маъно дорад. Сабаб дар он аст, ки мо метавонем конфигуратсияҳои сершуморро дар асоси як код дошта бошем. Боз, имконпазир аст, ки артефактҳое, ки ба шохаҳои гуногуни конфигуратсия мувофиқанд, тавлид кунед. Вобастагӣ аз версияҳои мушаххаси китобхонаҳо дар якҷоягӣ бо конфигуратсия захира карда мешаванд ва ин версияҳо то абад захира карда мешаванд, вақте ки мо тасмим гирифтем, ки ин версияи конфигуратсияро ҷойгир кунем.

Ҳар як тағирёбии конфигуратсия ба тағири код табдил меёбад. Ва аз ин рӯ, ҳар як
Тағйирот бо раванди муқаррарии кафолати сифат фаро гирифта мешавад:

Чипта дар трекери хато -> PR -> барраси -> бо филиалҳои дахлдор якҷоя кунед ->
ҳамгироӣ -> ҷобаҷогузорӣ

Оқибатҳои асосии татбиқи конфигуратсияи тартибдодашуда инҳоянд:

  1. Конфигуратсия дар тамоми гиреҳҳои системаи тақсимшуда мувофиқ хоҳад буд. Аз сабаби он, ки ҳама гиреҳҳо конфигуратсияи якхеларо аз як манбаъ мегиранд.

  2. Тағир додани конфигуратсия танҳо дар яке аз гиреҳҳо мушкил аст. Аз ин рӯ, "драфти конфигуратсия" аз эҳтимол дур нест.

  3. Тағироти хурди конфигуратсияро ворид кардан душвортар мешавад.

  4. Аксари тағйироти конфигуратсия ҳамчун як қисми раванди таҳияи умумӣ ба амал меоянд ва мавриди баррасӣ қарор хоҳанд гирифт.

Оё барои нигоҳ доштани конфигуратсияи истеҳсолӣ ба ман анбори алоҳида лозим аст? Ин конфигуратсия метавонад паролҳо ва дигар маълумоти ҳассос дошта бошад, ки мо мехоҳем дастрасиро ба онҳо маҳдуд созем. Дар асоси ин, нигоҳ доштани конфигуратсияи ниҳоӣ дар як анбори алоҳида ба назар мерасад. Шумо метавонед конфигуратсияро ба ду қисм тақсим кунед - яке дорои танзимоти конфигуратсияи барои омма дастрас ва дигаре дорои танзимоти маҳдуд. Ин ба аксари таҳиягарон имкон медиҳад, ки ба танзимоти умумӣ дастрасӣ дошта бошанд. Ин ҷудокуниро бо истифода аз хислатҳои фосилавӣ, ки арзишҳои пешфарз доранд, ба осонӣ ба даст овардан мумкин аст.

Вариантҳои имконпазир

Биёед кӯшиш кунем, ки конфигуратсияи тартибдодашударо бо баъзе алтернативаҳои маъмул муқоиса кунем:

  1. Файли матнӣ дар мошини мавриди ҳадаф.
  2. Мағозаи мутамаркази арзиши калидӣ (etcd/zookeeper).
  3. Ҷузъҳои раванд, ки метавонанд бе аз нав оғоз кардани раванд дубора танзим карда шаванд/аз нав оғоз карда шаванд.
  4. Нигоҳ доштани конфигуратсия берун аз назорати артефакт ва версия.

Файлҳои матнӣ чандирии назаррасро дар робита бо тағироти хурд таъмин мекунанд. Мудири система метавонад ба гиреҳи дурдаст ворид шуда, ба файлҳои мувофиқ тағйирот ворид кунад ва хидматро аз нав оғоз кунад. Аммо барои системаҳои калон, чунин чандирӣ матлуб нест. Тағйироти воридшуда дар дигар системаҳо осоре намегузорад. Ҳеҷ кас тағиротро баррасӣ намекунад. Муайян кардан душвор аст, ки ин дигаргунихоро махз кй ва бо кадом сабаб ба амал овардааст. Тағиротҳо санҷида намешаванд. Агар система тақсим карда шавад, он гоҳ маъмур метавонад тағироти мувофиқро дар гиреҳҳои дигар фаромӯш кунад.

(Инчунин бояд қайд кард, ки истифодаи конфигуратсияи тартибдодашуда имкони истифодаи файлҳои матниро дар оянда маҳкам намекунад. Илова кардани таҳлилгар ва валидатор кифоя аст, ки ҳамон навъи баромадро истеҳсол мекунад. Config, ва шумо метавонед файлҳои матниро истифода баред. Дарҳол чунин бармеояд, ки мураккабии система бо конфигуратсияи тартибдодашуда аз мураккабии системае, ки бо истифода аз файлҳои матнӣ истифода мебарад, каме камтар аст, зеро файлҳои матнӣ рамзи иловагӣ талаб мекунанд.)

Дӯкони мутамаркази арзиши калидӣ як механизми хуб барои паҳн кардани параметрҳои метаи барномаи тақсимшуда мебошад. Мо бояд муайян кунем, ки параметрҳои конфигуратсия чист ва чӣ танҳо маълумот аст. Биёед як функсия дошта бошем C => A => B, ва параметрҳо C кам тағйир меёбад, ва маълумот A - зуд-зуд. Дар ин маврид мо гуфта метавонем C - параметрҳои конфигуратсия, ва A - маълумот. Чунин ба назар мерасад, ки параметрҳои конфигуратсия аз маълумот бо он фарқ мекунанд, ки онҳо одатан нисбат ба додаҳо камтар тағйир меёбанд. Инчунин, маълумот одатан аз як манбаъ (аз корбар) ва параметрҳои конфигуратсия аз дигараш (аз маъмури система) меояд.

Агар параметрҳои кам-кам ивазшаванда бе аз нав оғоз кардани барнома навсозӣ карда шаванд, пас ин аксар вақт метавонад боиси мушкилии барнома гардад, зеро ба мо лозим меояд, ки бо ягон роҳ параметрҳоро интиқол диҳем, арзишҳои нодурустро нигоҳ дорем, таҳлил ва тафтиш кунем. Аз ин рӯ, аз нуқтаи назари кам кардани мураккабии барнома, кам кардани шумораи параметрҳое, ки дар ҷараёни кори барнома метавонанд тағир ёбанд (ё ин гуна параметрҳоро тамоман дастгирӣ накунанд) маъно дорад.

Барои мақсадҳои ин мақола, мо байни параметрҳои статикӣ ва динамикӣ фарқ мекунем. Агар мантиқи хадамот ҳангоми кори барнома тағир додани параметрҳоро талаб кунад, он гоҳ мо чунин параметрҳоро динамикӣ меномем. Дар акси ҳол, интихобҳо статикӣ мебошанд ва онҳоро бо истифода аз конфигуратсияи тартибдодашуда танзим кардан мумкин аст. Барои аз нав конфигуратсияи динамикӣ, ба мо шояд механизме лозим шавад, ки қисматҳои барномаро бо параметрҳои нав аз нав оғоз кунем, ба он монанде, ки равандҳои системаи амалиётӣ аз нав оғоз мешаванд. (Ба андешаи мо, тавсия дода мешавад, ки аз реконфигуратсия дар вақти воқеӣ худдорӣ намоед, зеро ин мураккабии системаро зиёд мекунад. Агар имконпазир бошад, беҳтар аст, ки имкониятҳои стандартии ОС-ро барои аз нав оғоз кардани равандҳо истифода баред).

Як ҷанбаи муҳими истифодаи конфигуратсияи статикӣ, ки одамонро водор месозад, ки аз нав конфигуратсияи динамикӣ ба назар гиранд, вақти аз нав ба кор даровардани система пас аз навсозии конфигуратсия (вақти бекор) мебошад. Дар асл, агар ба мо лозим ояд, ки ба конфигуратсияи статикӣ тағирот ворид кунем, мо бояд системаро бозоғоз кунем, то ки арзишҳои нав эътибор пайдо кунанд. Мушкилоти бекорӣ барои системаҳои гуногун аз ҷиҳати шиддат фарқ мекунад. Дар баъзе ҳолатҳо, шумо метавонед бозоғозро дар замоне ба нақша гиред, ки сарборӣ ҳадди ақалл аст. Агар ба шумо хидмати доимӣ ниёз дошта бошед, шумо метавонед татбиқ кунед Дренажии пайвасти AWS ELB. Дар айни замон, вақте ки ба мо лозим аст, ки системаро бозоғоз кунем, мо як мисоли мувозии ин системаро ба кор меандозем, мувозинатро ба он иваз мекунем ва то анҷом ёфтани пайвастҳои кӯҳна интизор мешавем. Пас аз қатъ шудани ҳама пайвастҳои кӯҳна, мо намунаи кӯҳнаи системаро хомӯш мекунем.

Биёед ҳоло масъалаи нигоҳ доштани конфигуратсияро дар дохили артефакт ё берун аз он дида бароем. Агар мо конфигуратсияро дар дохили артефакт нигоҳ дорем, пас ҳадди аққал мо имкон доштем, ки дурустии конфигуратсияро ҳангоми васл кардани артефакт тафтиш кунем. Агар конфигуратсия берун аз артефакти идорашаванда бошад, пайгирӣ кардан душвор аст, ки кӣ ба ин файл тағирот ворид кардааст ва чаро. То чӣ андоза муҳим аст? Ба фикри мо, барои бисьёр системахои истехсолй конфигурациям устувор ва хушсифат мухим аст.

Версияи артефакт ба шумо имкон медиҳад, ки муайян кунед, ки он кай сохта шудааст, кадом арзишҳоро дар бар мегирад, кадом функсияҳо фаъол/фаъол шудаанд ва барои тағирот дар конфигуратсия кӣ масъул аст. Албатта, нигоҳ доштани конфигуратсия дар дохили артефакт каме кӯшишро талаб мекунад, бинобар ин шумо бояд қарори огоҳона қабул кунед.

Тарафҳо ва манфиатҳо

Ман мехостам дар бораи мусбат ва манфии технологияи пешниҳодшуда таваққуф кунам.

афзалияти

Дар зер рӯйхати хусусиятҳои асосии конфигуратсияи тақсимшудаи система оварда шудааст:

  1. Санҷиши конфигуратсияи статикӣ. Ба шумо имкон медиҳад, ки боварӣ ҳосил кунед
    конфигуратсия дуруст аст.
  2. Забони бойи конфигуратсия. Одатан, усулҳои дигари конфигуратсия аксаран бо ивазкунии тағирёбандаи сатр маҳдуданд. Ҳангоми истифодаи Scala, доираи васеи хусусиятҳои забон барои беҳтар кардани конфигуратсияи шумо дастрасанд. Масалан, мо метавонем истифода барем
    хусусиятҳо барои арзишҳои пешфарз, бо истифода аз объектҳо барои гурӯҳбандии параметрҳо, мо метавонем ба валҳое, ки танҳо як маротиба (DRY) дар доираи фарогир эълон шудаанд, муроҷиат кунем. Шумо метавонед ҳама гуна синфҳоро мустақиман дар дохили конфигуратсия эҷод кунед (Seq, Map, синфҳои фармоишӣ).
  3. DSL. Scala дорои як қатор хусусиятҳои забон мебошад, ки сохтани DSL-ро осонтар мекунад. Аз ин хусусиятҳо истифода бурдан ва забони конфигуратсияеро татбиқ кардан мумкин аст, ки барои гурӯҳи мавриди ҳадафи корбарон қулайтар бошад, то конфигуратсияро ҳадди аққал коршиносони домен хондан мумкин бошад. Масалан, мутахассисон метавонанд дар раванди баррасии конфигуратсия иштирок кунанд.
  4. Беайбӣ ва ҳамоҳангӣ байни гиреҳҳо. Яке аз бартариҳои доштани конфигуратсияи тамоми системаи тақсимшуда дар як нуқта дар он аст, ки ҳама арзишҳо маҳз як маротиба эълон карда мешаванд ва сипас дар ҳар ҷое, ки лозиманд, дубора истифода мешаванд. Истифодаи намудҳои фантом барои эълони портҳо кафолат медиҳад, ки гиреҳҳо дар ҳама конфигуратсияҳои дурусти система протоколҳои мувофиқро истифода мебаранд. Доштани вобастагии ҳатмии ҳатмӣ байни гиреҳҳо кафолат медиҳад, ки ҳама хидматҳо пайваст мешаванд.
  5. Тағироти сифати баланд. Ворид намудани тағйирот ба конфигуратсия бо истифода аз раванди умумии таҳия имкон медиҳад, ки ба стандартҳои баланди сифат барои конфигуратсия низ ноил гарданд.
  6. Навсозии конфигуратсияи ҳамзамон. Ҷойгиркунии автоматии система пас аз тағир додани конфигуратсия кафолат медиҳад, ки ҳама гиреҳҳо нав карда мешаванд.
  7. Оддӣ кардани барнома. Барнома ба таҳлил, тафтиши конфигуратсия ё коркарди арзишҳои нодуруст ниёз надорад. Ин мураккабии барномаро коҳиш медиҳад. (Баъзе мураккабии конфигуратсияҳое, ки дар мисоли мо мушоҳида мешаванд, атрибути конфигуратсияи тартибдодашуда нест, балки танҳо як қарори бошууронаест, ки бо хоҳиши таъмини бехатарии навъи бештар асос ёфтааст.) Бозгаштан ба конфигуратсияи муқаррарӣ хеле осон аст - танҳо иҷро кардани чизи гумшуда. қисмҳо. Аз ин рӯ, шумо метавонед, масалан, аз конфигуратсияи тартибдодашуда оғоз кунед ва иҷрои қисмҳои нолозимро то лаҳзае, ки воқеан лозим аст, ба таъхир андозед.
  8. Конфигуратсияи тасдиқшуда. Азбаски тағироти конфигуратсия сарнавишти муқаррарии ҳама гуна тағиротро пайгирӣ мекунад, натиҷае, ки мо ба даст меорем, артефакт бо версияи беназир аст. Ин ба мо имкон медиҳад, масалан, агар лозим бошад, ба версияи пешинаи конфигуратсия баргардем. Мо ҳатто метавонем конфигуратсияи як сол пешро истифода барем ва система маҳз ҳамин тавр кор хоҳад кард. Конфигуратсияи устувор пешгӯӣ ва эътимоднокии системаи тақсимшударо беҳтар мекунад. Азбаски конфигуратсия дар марҳилаи тартибдиҳӣ муқаррар карда мешавад, дар истеҳсолот қалбакӣ кардан хеле душвор аст.
  9. Модулият. Чаҳорчӯбаи пешниҳодшуда модулӣ аст ва модулҳоро бо роҳҳои гуногун барои сохтани системаҳои гуногун муттаҳид кардан мумкин аст. Аз ҷумла, шумо метавонед системаро танзим кунед, ки дар як гиреҳ дар як таҷассум ва дар гиреҳҳои сершумор дар дигараш кор кунад. Шумо метавонед якчанд конфигуратсияҳоро барои намунаҳои истеҳсолии система эҷод кунед.
  10. Санҷиш. Бо иваз кардани хидматҳои инфиродӣ бо объектҳои тақаллубӣ, шумо метавонед якчанд версияи системаро, ки барои санҷиш мувофиқанд, гиред.
  11. Санҷиши ҳамгироӣ. Доштани конфигуратсияи ягона барои тамоми системаи тақсимшуда имкон медиҳад, ки ҳама ҷузъҳо дар муҳити назоратшаванда ҳамчун як қисми санҷиши ҳамгироӣ иҷро карда шаванд. Масалан, ба вазъияте, ки баъзе гиреҳҳо дастрас мешаванд, тақлид кардан осон аст.

Камбудиҳо ва маҳдудиятҳо

Конфигуратсияи тартибдодашуда аз дигар равишҳои конфигуратсия фарқ мекунад ва метавонад барои баъзе барномаҳо мувофиқ набошад. Дар зер баъзе камбудиҳо мавҷуданд:

  1. Конфигуратсияи статикӣ. Баъзан ба шумо лозим аст, ки конфигуратсияро дар истеҳсолот зуд ислоҳ кунед, бо гузашти тамоми механизмҳои муҳофизатӣ. Бо ин равиш, он метавонад душвортар бошад. Ҳадди ақалл, таҳия ва ҷойгиркунии автоматӣ ҳанӯз ҳам талаб карда мешавад. Ин ҳам як хусусияти муфиди равиш аст ва ҳам дар баъзе мавридҳо камбуди.
  2. Насли конфигуратсия. Дар ҳолате, ки файли конфигуратсия тавассути асбоби худкор тавлид шуда бошад, метавонад барои ҳамгиро кардани скрипти сохтмон кӯшишҳои иловагӣ талаб карда шаванд.
  3. Воситаҳо. Дар айни замон, утилитаҳо ва усулҳое, ки барои кор бо конфигуратсия пешбинӣ шудаанд, ба файлҳои матнӣ асос ёфтаанд. На ҳама чунин утилитҳо/техникаҳо дар конфигуратсияи тартибдодашуда дастрас хоҳанд буд.
  4. Тағйир додани муносибат талаб карда мешавад. Таҳиягарон ва DevOps ба файлҳои матнӣ одат кардаанд. Худи идеяи тартиб додани конфигуратсия метавонад то ҳадде ғайричашмдошт ва ғайриоддӣ бошад ва боиси рад карда шавад.
  5. Раванди баландсифати рушд талаб карда мешавад. Барои истифодаи бароҳати конфигуратсияи тартибдодашуда, автоматикунонии пурраи раванди сохтан ва ҷойгиркунии барнома (CI/CD) зарур аст. Дар акси ҳол, он хеле нороҳат хоҳад буд.

Биёед инчунин дар бораи як қатор маҳдудиятҳои мисоли баррасӣшуда, ки ба идеяи конфигуратсияи тартибдодашуда алоқаманд нестанд, таваққуф кунем:

  1. Агар мо маълумоти конфигуратсияи нолозимро, ки аз ҷониби гиреҳ истифода намешавад, пешниҳод кунем, пас компилятор ба мо дар ошкор кардани татбиқи гумшуда кӯмак намекунад. Ин мушкилотро тавассути даст кашидан аз намунаи торт ва истифодаи навъҳои сахттар ҳал кардан мумкин аст, масалан, HList ё намудҳои алгебравии додаҳо (синфҳои парвандаҳо) барои муаррифии конфигуратсия.
  2. Дар файли конфигуратсия сатрҳо мавҷуданд, ки ба худи конфигуратсия алоқаманд нестанд: (package, import, эъломияҳои объектҳо; override def's барои параметрҳое, ки арзишҳои пешфарз доранд). Инро метавон қисман пешгирӣ кард, агар шумо DSL-и худро амалӣ кунед. Илова бар ин, дигар намудҳои конфигуратсия (масалан, XML) низ ба сохтори файл маҳдудиятҳои муайяне ҷорӣ мекунанд.
  3. Барои мақсадҳои ин мақола, мо конфигуратсияи динамикии кластери гиреҳҳои шабеҳро баррасӣ намекунем.

хулоса

Дар ин паём, мо идеяи муаррифии конфигуратсияро дар коди сарчашма бо истифода аз қобилиятҳои пешрафтаи системаи навъи Scala омӯхтаем. Ин равишро метавон дар барномаҳои гуногун ҳамчун ивази усулҳои конфигуратсияи анъанавӣ дар асоси xml ё файлҳои матнӣ истифода бурд. Гарчанде ки мисоли мо дар Scala амалӣ карда мешавад, ҳамон ғояҳоро метавон ба дигар забонҳои тартибдодашуда интиқол дод (ба монанди Kotlin, C#, Swift, ...). Шумо метавонед ин равишро дар яке аз лоиҳаҳои зерин санҷед ва агар он кор накунад, ба файли матнӣ гузаред ва қисмҳои гумшударо илова кунед.

Табиист, ки конфигуратсияи тартибдодашуда раванди баландсифати таҳияро талаб мекунад. Дар навбати худ, сифат ва эътимоднокии конфигуратсияҳо таъмин карда мешавад.

Равиши баррасишавандаро васеъ кардан мумкин аст:

  1. Шумо метавонед макросҳоро барои анҷом додани санҷишҳои вақти тартибдиҳӣ истифода баред.
  2. Шумо метавонед DSL-ро татбиқ кунед, то конфигуратсияро тавре пешниҳод кунад, ки барои корбарони ниҳоӣ дастрас бошад.
  3. Шумо метавонед идоракунии динамикии захираҳоро бо танзими автоматии конфигуратсия амалӣ кунед. Масалан, тағир додани шумораи гиреҳҳо дар кластер талаб мекунад, ки (1) ҳар як гиреҳ конфигуратсияи каме дигарро қабул кунад; (2) мудири кластер дар бораи гиреҳҳои нав маълумот гирифт.

Эътирофҳо

Мехохам ба Андрей Саксонов, Павел Попов ва Антон Нехаев барои танкиди конструктивиашон нисбат ба лоихаи модда ташаккур баён кунам.

Манбаъ: will.com

Илова Эзоҳ