Usanidi Uliokusanywa wa Mfumo Uliosambazwa

Ningependa kukuambia utaratibu mmoja wa kuvutia wa kufanya kazi na usanidi wa mfumo uliosambazwa. Usanidi unawakilishwa moja kwa moja katika lugha iliyokusanywa (Scala) kwa kutumia aina salama. Chapisho hili linatoa mfano wa usanidi kama huu na kujadili vipengele mbalimbali vya kutekeleza usanidi uliokusanywa katika mchakato wa jumla wa maendeleo.

Usanidi Uliokusanywa wa Mfumo Uliosambazwa

(Kiingereza)

Utangulizi

Kujenga mfumo unaoaminika unaosambazwa ina maana kwamba nodi zote hutumia usanidi sahihi, uliosawazishwa na nodi nyingine. Teknolojia za DevOps (terraform, ansible au kitu kama hicho) kawaida hutumiwa kutengeneza faili za usanidi kiotomatiki (mara nyingi ni maalum kwa kila nodi). Tungependa pia kuwa na uhakika kwamba nodi zote za mawasiliano zinatumia itifaki zinazofanana (pamoja na toleo lile lile). Vinginevyo, kutopatana kutajengwa kwenye mfumo wetu uliosambazwa. Katika ulimwengu wa JVM, tokeo moja la hitaji hili ni kwamba toleo lile lile la maktaba iliyo na ujumbe wa itifaki lazima litumike kila mahali.

Vipi kuhusu kupima mfumo uliosambazwa? Bila shaka, tunadhania kuwa vipengele vyote vina majaribio ya vipimo kabla ya kuendelea na majaribio ya ujumuishaji. (Ili tuongeze matokeo ya mtihani hadi wakati wa utekelezaji, ni lazima pia tutoe seti inayofanana ya maktaba katika hatua ya majaribio na wakati wa utekelezaji.)

Wakati wa kufanya kazi na vipimo vya ujumuishaji, mara nyingi ni rahisi kutumia njia ya darasa sawa kila mahali kwenye nodi zote. Tunachopaswa kufanya ni kuhakikisha kuwa njia sawa ya darasa inatumika wakati wa kukimbia. (Ingawa inawezekana kabisa kuendesha nodi tofauti zilizo na njia tofauti za darasa, hii haiongezei utata kwa usanidi wa jumla na shida na majaribio ya uwekaji na ujumuishaji.) Kwa madhumuni ya chapisho hili, tunachukulia kuwa nodi zote zitatumia njia sawa ya darasa.

Usanidi hubadilika na programu. Tunatumia matoleo kutambua hatua tofauti za mageuzi ya programu. Inaonekana ni sawa kutambua matoleo tofauti ya usanidi. Na uweke usanidi yenyewe katika mfumo wa udhibiti wa toleo. Ikiwa kuna usanidi mmoja tu katika uzalishaji, basi tunaweza kutumia nambari ya toleo. Ikiwa tunatumia matukio mengi ya uzalishaji, basi tutahitaji kadhaa
matawi ya usanidi na lebo ya ziada kwa kuongeza toleo (kwa mfano, jina la tawi). Kwa njia hii tunaweza kutambua kwa uwazi usanidi halisi. Kila kitambulisho cha usanidi kinalingana kipekee na mchanganyiko maalum wa nodi zilizosambazwa, bandari, rasilimali za nje na matoleo ya maktaba. Kwa madhumuni ya chapisho hili tutachukulia kuwa kuna tawi moja tu na tunaweza kutambua usanidi kwa njia ya kawaida kwa kutumia nambari tatu zilizotenganishwa na nukta (1.2.3).

Katika mazingira ya kisasa, faili za usanidi hazijaundwa kwa mikono. Mara nyingi zaidi hutolewa wakati wa kupelekwa na haziguswi tena (ili usivunje chochote) Swali la asili linatokea: kwa nini bado tunatumia umbizo la maandishi kuhifadhi usanidi? Njia mbadala inayofaa inaonekana kuwa uwezo wa kutumia nambari ya kawaida kwa usanidi na kufaidika na ukaguzi wa wakati wa kukusanya.

Katika chapisho hili tutachunguza wazo la kuwakilisha usanidi ndani ya vizalia vya programu vilivyokusanywa.

Usanidi uliokusanywa

Sehemu hii inatoa mfano wa usanidi tuli uliokusanywa. Huduma mbili rahisi zinatekelezwa - huduma ya echo na mteja wa huduma ya echo. Kulingana na huduma hizi mbili, chaguzi mbili za mfumo zinakusanyika. Katika chaguo moja, huduma zote mbili ziko kwenye node moja, kwa chaguo jingine - kwenye nodes tofauti.

Kawaida mfumo uliosambazwa una nodi kadhaa. Unaweza kutambua nodi kwa kutumia maadili ya aina fulani NodeId:

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

au

case class NodeId(hostName: String)

au hata

object Singleton
type NodeId = Singleton.type

Nodi hufanya majukumu mbalimbali, huendesha huduma na miunganisho ya TCP/HTTP inaweza kuanzishwa kati yao.

Ili kuelezea muunganisho wa TCP tunahitaji angalau nambari ya mlango. Tungependa pia kuonyesha itifaki inayotumika kwenye mlango huo ili kuhakikisha kuwa mteja na seva hutumia itifaki sawa. Tutaelezea unganisho kwa kutumia darasa lifuatalo:

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

ambapo Port - nambari kamili tu Int inayoonyesha anuwai ya maadili yanayokubalika:

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

Aina zilizosafishwa

Tazama maktaba iliyosafishwa ΠΈ wangu ripoti. Kwa kifupi, maktaba hukuruhusu kuongeza vizuizi kwa aina ambazo huangaliwa kwa wakati wa kukusanya. Katika kesi hii, nambari halali za nambari ya mlango ni nambari 16-bit. Kwa usanidi uliokusanywa, kutumia maktaba iliyosafishwa sio lazima, lakini inaboresha uwezo wa mkusanyaji kuangalia usanidi.

Kwa itifaki za HTTP (REST), pamoja na nambari ya bandari, tunaweza pia kuhitaji njia ya huduma:

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

Aina za Phantom

Ili kutambua itifaki wakati wa kukusanya, tunatumia parameter ya aina ambayo haitumiwi ndani ya darasa. Uamuzi huu unatokana na ukweli kwamba hatutumii mfano wa itifaki wakati wa utekelezaji, lakini tungependa mkusanyaji aangalie upatanifu wa itifaki. Kwa kubainisha itifaki, hatutaweza kupitisha huduma isiyofaa kama tegemezi.

Mojawapo ya itifaki za kawaida ni REST API na usanifu wa Json:

sealed trait JsonHttpRestProtocol[RequestMessage, ResponseMessage]

ambapo RequestMessage - aina ya ombi, ResponseMessage - aina ya majibu.
Bila shaka, tunaweza kutumia maelezo mengine ya itifaki ambayo hutoa usahihi wa maelezo tunayohitaji.

Kwa madhumuni ya chapisho hili, tutatumia toleo lililorahisishwa la itifaki:

sealed trait SimpleHttpGetRest[RequestMessage, ResponseMessage]

Hapa ombi ni mfuatano ulioambatishwa kwa url na jibu ni mfuatano uliorejeshwa katika kiini cha jibu la HTTP.

Usanidi wa huduma unaelezewa na jina la huduma, bandari, na vitegemezi. Vipengele hivi vinaweza kuwakilishwa katika Scala kwa njia kadhaa (kwa mfano, HList-s, aina za data za aljebra). Kwa madhumuni ya chapisho hili, tutatumia Mchoro wa Keki na kuwakilisha moduli kwa kutumia trait'ov. (Mchoro wa Keki sio kipengele kinachohitajika cha mbinu hii. Ni utekelezaji mmoja tu unaowezekana.)

Mategemeo kati ya huduma yanaweza kuwakilishwa kama njia zinazorudisha bandari EndPointya nodi zingine:

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

Ili kuunda huduma ya mwangwi, unachohitaji ni nambari ya bandari na ishara kwamba bandari inasaidia itifaki ya mwangwi. Huenda tusibainishe bandari maalum, kwa sababu... sifa hukuruhusu kutangaza njia bila utekelezaji (mbinu za kufikirika). Katika kesi hii, wakati wa kuunda usanidi halisi, mkusanyaji atatuhitaji kutoa utekelezaji wa njia ya kufikirika na kutoa nambari ya bandari. Kwa kuwa tumetekeleza njia, wakati wa kuunda usanidi maalum, hatuwezi kutaja bandari tofauti. Thamani chaguo-msingi itatumika.

Katika usanidi wa mteja tunatangaza utegemezi kwenye huduma ya mwangwi:

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

Utegemezi ni wa aina sawa na huduma iliyosafirishwa echoService. Hasa, katika mteja wa echo tunahitaji itifaki sawa. Kwa hiyo, wakati wa kuunganisha huduma mbili, tunaweza kuwa na uhakika kwamba kila kitu kitafanya kazi kwa usahihi.

Utekelezaji wa huduma

Chaguo la kukokotoa linahitajika ili kuanza na kusimamisha huduma. (Uwezo wa kusimamisha huduma ni muhimu kwa majaribio.) Tena, kuna chaguo kadhaa za kutekeleza kipengele kama hicho (kwa mfano, tunaweza kutumia aina za madarasa kulingana na aina ya usanidi). Kwa madhumuni ya chapisho hili tutatumia muundo wa keki. Tutawakilisha huduma kwa kutumia darasa cats.Resource, kwa sababu Darasa hili tayari linatoa njia za kuhakikisha utolewaji wa rasilimali kwa usalama ikiwa kuna shida. Ili kupata rasilimali, tunahitaji kutoa usanidi na muktadha wa wakati wa utekelezaji ulio tayari. Kazi ya kuanzisha huduma inaweza kuonekana kama hii:

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

ambapo

  • Config β€” aina ya usanidi wa huduma hii
  • AddressResolver - kitu cha wakati wa kukimbia ambacho hukuruhusu kujua anwani za nodi zingine (tazama hapa chini)

na aina zingine kutoka kwa maktaba cats:

  • F[_] - aina ya athari (katika kesi rahisi F[A] inaweza tu kuwa kazi () => A. Katika chapisho hili tutatumia cats.IO.)
  • Reader[A,B] - zaidi au chini ya sawa na kazi A => B
  • cats.Resource - rasilimali ambayo inaweza kupatikana na kutolewa
  • Timer - kipima saa (hukuruhusu kulala kwa muda na kupima vipindi vya muda)
  • ContextShift - analog ExecutionContext
  • Applicative - darasa la aina ya athari ambayo hukuruhusu kuchanganya athari za mtu binafsi (karibu monad). Katika maombi magumu zaidi inaonekana bora kutumia Monad/ConcurrentEffect.

Kwa kutumia saini hii ya kazi tunaweza kutekeleza huduma kadhaa. Kwa mfano, huduma ambayo haifanyi chochote:

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

(Sentimita. msimbo wa chanzo, ambapo huduma zingine zinatekelezwa - huduma ya mwangwi, mteja echo
ΠΈ watawala wa maisha.)

Nodi ni kitu ambacho kinaweza kuzindua huduma kadhaa (uzinduzi wa mlolongo wa rasilimali unahakikishwa na Mchoro wa Keki):

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

Tafadhali kumbuka kuwa tunabainisha aina halisi ya usanidi ambayo inahitajika kwa nodi hii. Ikiwa tunasahau kutaja moja ya aina za usanidi zinazohitajika na huduma fulani, kutakuwa na hitilafu ya mkusanyiko. Pia, hatutaweza kuanzisha nodi isipokuwa tutoe baadhi ya kitu cha aina inayofaa na data zote muhimu.

Azimio la Jina la Mwenyeji

Ili kuunganisha kwa seva pangishi ya mbali, tunahitaji anwani halisi ya IP. Inawezekana kwamba anwani itajulikana baadaye kuliko usanidi uliobaki. Kwa hivyo tunahitaji kazi inayoweka kitambulisho cha nodi kwa anwani:

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

Kuna njia kadhaa za kutekeleza kazi hii:

  1. Ikiwa anwani zitajulikana kwetu kabla ya kupelekwa, basi tunaweza kutoa msimbo wa Scala kwa
    anwani na kisha endesha ujenzi. Hii itakusanya na kuendesha majaribio.
    Katika hali hii, chaguo la kukokotoa litajulikana kitakwimu na linaweza kuwakilishwa katika msimbo kama ramani Map[NodeId, NodeAddress].
  2. Katika baadhi ya matukio, anwani halisi inajulikana tu baada ya node kuanza.
    Katika kesi hii, tunaweza kutekeleza "huduma ya ugunduzi" inayoendesha kabla ya nodes nyingine na nodes zote zitajiandikisha na huduma hii na kuomba anwani za nodes nyingine.
  3. Ikiwa tunaweza kurekebisha /etc/hosts, basi unaweza kutumia majina ya mwenyeji yaliyofafanuliwa (kama my-project-main-node ΠΈ echo-backend) na uunganishe tu majina haya
    na anwani za IP wakati wa kupeleka.

Katika chapisho hili hatutazingatia kesi hizi kwa undani zaidi. Kwa ajili yetu
katika mfano wa toy, nodi zote zitakuwa na anwani sawa ya IP - 127.0.0.1.

Ifuatayo, tunazingatia chaguzi mbili za mfumo uliosambazwa:

  1. Kuweka huduma zote kwenye node moja.
  2. Na kukaribisha huduma ya echo na mteja wa mwangwi kwenye nodi tofauti.

Usanidi wa nodi moja:

Usanidi wa nodi moja

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

Kitu hutekelezea usanidi wa mteja na seva. Configuration ya muda wa kuishi pia hutumiwa ili baada ya muda lifetime kusitisha programu. (Ctrl-C pia hufanya kazi na kuachilia rasilimali zote kwa usahihi.)

Seti sawa ya sifa za usanidi na utekelezaji zinaweza kutumika kuunda mfumo unaojumuisha nodi mbili tofauti:

Usanidi wa nodi mbili

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

Muhimu! Angalia jinsi huduma zinavyounganishwa. Tunabainisha huduma inayotekelezwa na nodi moja kama utekelezaji wa mbinu ya utegemezi ya nodi nyingine. Aina ya utegemezi inakaguliwa na mkusanyaji, kwa sababu ina aina ya itifaki. Inapoendeshwa, utegemezi utakuwa na kitambulisho sahihi cha nodi ya lengo. Shukrani kwa mpango huu, tunabainisha nambari ya bandari mara moja na tunahakikishiwa daima kurejelea bandari sahihi.

Utekelezaji wa nodi mbili za mfumo

Kwa usanidi huu, tunatumia utekelezaji wa huduma sawa bila mabadiliko. Tofauti pekee ni kwamba sasa tuna vitu viwili vinavyotekeleza seti tofauti za huduma:

  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
  }

Nodi ya kwanza inatekeleza seva na inahitaji usanidi wa seva pekee. Nodi ya pili inatekeleza mteja na hutumia sehemu tofauti ya usanidi. Pia nodi zote mbili zinahitaji usimamizi wa maisha yote. Nodi ya seva huendesha kwa muda usiojulikana hadi ikomeshwe SIGTERM'om, na nodi ya mteja huisha baada ya muda fulani. Sentimita. programu ya kuzindua.

Mchakato wa maendeleo ya jumla

Wacha tuone jinsi mbinu hii ya usanidi inathiri mchakato mzima wa ukuzaji.

Mipangilio itakusanywa pamoja na msimbo uliosalia na vizalia vya programu (.jar) vitatolewa. Inaonekana kuwa na maana kuweka usanidi katika mabaki tofauti. Hii ni kwa sababu tunaweza kuwa na usanidi mwingi kulingana na msimbo sawa. Tena, inawezekana kutoa mabaki yanayolingana na matawi tofauti ya usanidi. Utegemezi wa matoleo mahususi ya maktaba huhifadhiwa pamoja na usanidi, na matoleo haya huhifadhiwa milele wakati wowote tunapoamua kupeleka toleo hilo la usanidi.

Mabadiliko yoyote ya usanidi hubadilika kuwa mabadiliko ya nambari. Na kwa hivyo, kila mmoja
mabadiliko yatafunikwa na mchakato wa kawaida wa uhakikisho wa ubora:

Tikiti katika kifuatilia hitilafu -> PR -> kagua -> unganisha na matawi husika ->
ushirikiano -> kupeleka

Matokeo kuu ya kutekeleza usanidi uliokusanywa ni:

  1. Usanidi utakuwa sawa katika nodi zote za mfumo uliosambazwa. Kwa sababu ya ukweli kwamba nodi zote hupokea usanidi sawa kutoka kwa chanzo kimoja.

  2. Ni shida kubadilisha usanidi katika nodi moja tu. Kwa hivyo, "kuteleza kwa usanidi" hakuna uwezekano.

  3. Inakuwa vigumu zaidi kufanya mabadiliko madogo kwenye usanidi.

  4. Mabadiliko mengi ya usanidi yatatokea kama sehemu ya mchakato mzima wa usanidi na yatachunguzwa.

Je, ninahitaji hazina tofauti ili kuhifadhi usanidi wa uzalishaji? Usanidi huu unaweza kuwa na manenosiri na maelezo mengine nyeti ambayo tungependa kuzuia ufikiaji. Kwa msingi wa hii, inaonekana kuwa na maana kuhifadhi usanidi wa mwisho katika hazina tofauti. Unaweza kugawanya usanidi katika sehemu mbili-moja iliyo na mipangilio ya usanidi inayoweza kufikiwa na umma na moja iliyo na mipangilio iliyowekewa vikwazo. Hii itawawezesha watengenezaji wengi kufikia mipangilio ya kawaida. Utengano huu ni rahisi kufikia kwa kutumia sifa za kati zilizo na maadili chaguo-msingi.

Tofauti zinazowezekana

Wacha tujaribu kulinganisha usanidi uliojumuishwa na chaguzi zingine za kawaida:

  1. Faili ya maandishi kwenye mashine inayolengwa.
  2. Duka kuu la thamani kuu (etcd/zookeeper).
  3. Vipengee vya mchakato vinavyoweza kusanidiwa upya/kuanzishwa upya bila kuanzisha upya mchakato.
  4. Kuhifadhi usanidi nje ya vizalia vya programu na udhibiti wa toleo.

Faili za maandishi hutoa kubadilika kwa kiasi kikubwa katika suala la mabadiliko madogo. Msimamizi wa mfumo anaweza kuingia kwenye node ya mbali, kufanya mabadiliko kwenye faili zinazofaa na kuanzisha upya huduma. Kwa mifumo mikubwa, hata hivyo, kubadilika vile kunaweza kusiwe na kuhitajika. Mabadiliko yaliyofanywa hayaacha athari katika mifumo mingine. Hakuna anayekagua mabadiliko. Ni vigumu kuamua ni nani hasa alifanya mabadiliko na kwa sababu gani. Mabadiliko hayajaribiwi. Ikiwa mfumo unasambazwa, basi msimamizi anaweza kusahau kufanya mabadiliko yanayofanana kwenye nodes nyingine.

(Inapaswa pia kuzingatiwa kuwa kutumia usanidi uliojumuishwa hakufungi uwezekano wa kutumia faili za maandishi katika siku zijazo. Itatosha kuongeza kichanganuzi na kihalalisha ambacho hutoa aina sawa na pato. Config, na unaweza kutumia faili za maandishi. Inafuata mara moja kwamba ugumu wa mfumo ulio na usanidi uliojumuishwa ni kidogo kuliko ugumu wa mfumo unaotumia faili za maandishi, kwa sababu. faili za maandishi zinahitaji nambari ya ziada.)

Duka kuu la thamani ya ufunguo ni utaratibu mzuri wa kusambaza vigezo vya meta vya programu iliyosambazwa. Tunahitaji kuamua ni vigezo gani vya usanidi na ni data gani tu. Hebu tuwe na kazi C => A => B, na vigezo C mara chache hubadilika, na data A - mara nyingi. Katika kesi hii tunaweza kusema hivyo C - vigezo vya usanidi, na A - data. Inaonekana kwamba vigezo vya usanidi hutofautiana na data kwa kuwa kwa ujumla hubadilika mara chache kuliko data. Pia, data kawaida hutoka kwa chanzo kimoja (kutoka kwa mtumiaji), na vigezo vya usanidi kutoka kwa mwingine (kutoka kwa msimamizi wa mfumo).

Ikiwa mara chache kubadilisha vigezo vinahitaji kusasishwa bila kuanzisha upya programu, basi hii inaweza mara nyingi kusababisha matatizo ya programu, kwa sababu tutahitaji kwa namna fulani kutoa vigezo, kuhifadhi, kuchunguza na kuangalia, na kusindika maadili yasiyo sahihi. Kwa hiyo, kutoka kwa mtazamo wa kupunguza ugumu wa programu, ni mantiki kupunguza idadi ya vigezo vinavyoweza kubadilika wakati wa uendeshaji wa programu (au sio kuunga mkono vigezo hivyo kabisa).

Kwa madhumuni ya chapisho hili, tutatofautisha kati ya vigezo vya tuli na vya nguvu. Ikiwa mantiki ya huduma inahitaji kubadilisha vigezo wakati wa uendeshaji wa programu, basi tutaita vigezo vile vya nguvu. Vinginevyo chaguzi ni tuli na zinaweza kusanidiwa kwa kutumia usanidi uliokusanywa. Kwa urekebishaji unaobadilika, tunaweza kuhitaji utaratibu wa kuanzisha upya sehemu za programu kwa kutumia vigezo vipya, sawa na jinsi michakato ya mfumo wa uendeshaji inavyoanzishwa upya. (Kwa maoni yetu, inashauriwa kuepuka usanidi upya wa wakati halisi, kwa kuwa hii huongeza utata wa mfumo. Ikiwezekana, ni bora kutumia uwezo wa kawaida wa OS kwa kuanzisha upya michakato.)

Kipengele kimoja muhimu cha kutumia usanidi tuli ambao huwafanya watu kuzingatia usanidi upya unaobadilika ni wakati unaochukua kwa mfumo kuwasha upya baada ya sasisho la usanidi (muda wa chini). Kwa kweli, ikiwa tunahitaji kufanya mabadiliko kwenye usanidi tuli, tutalazimika kuanzisha upya mfumo ili maadili mapya yaanze kutumika. Tatizo la muda wa chini hutofautiana katika ukali kwa mifumo tofauti. Katika baadhi ya matukio, unaweza kupanga upya upya wakati ambapo mzigo ni mdogo. Ikiwa unahitaji kutoa huduma ya kuendelea, unaweza kutekeleza Utoaji wa muunganisho wa AWS ELB. Wakati huo huo, tunapohitaji kuanzisha upya mfumo, tunazindua mfano wa sambamba wa mfumo huu, ubadilishe kusawazisha kwake, na kusubiri miunganisho ya zamani ili kukamilisha. Baada ya miunganisho yote ya zamani kumalizika, tunafunga mfano wa zamani wa mfumo.

Wacha sasa tuzingatie suala la kuhifadhi usanidi ndani au nje ya vizalia. Ikiwa tutahifadhi usanidi ndani ya artifact, basi angalau tulipata fursa ya kuthibitisha usahihi wa usanidi wakati wa mkusanyiko wa artifact. Ikiwa usanidi uko nje ya vizalia vya programu vinavyodhibitiwa, ni vigumu kufuatilia ni nani aliyefanya mabadiliko kwenye faili hii na kwa nini. Je, ni muhimu kiasi gani? Kwa maoni yetu, kwa mifumo mingi ya uzalishaji ni muhimu kuwa na usanidi thabiti na wa hali ya juu.

Toleo la vizalia vya programu hukuruhusu kubainisha lini liliundwa, ni thamani gani iliyomo, ni utendakazi gani umewashwa/kuzimwa, na ni nani anayewajibika kwa mabadiliko yoyote katika usanidi. Bila shaka, kuhifadhi usanidi ndani ya vizalia vya programu kunahitaji juhudi fulani, kwa hivyo unahitaji kufanya uamuzi sahihi.

Faida na hasara

Ningependa kukaa juu ya faida na hasara za teknolojia iliyopendekezwa.

Faida

Ifuatayo ni orodha ya sifa kuu za usanidi wa mfumo uliosambazwa:

  1. Cheki cha usanidi tuli. Inakuruhusu kuwa na uhakika kuwa
    usanidi ni sahihi.
  2. Lugha tajiri ya usanidi. Kwa kawaida, mbinu zingine za usanidi huwa na kikomo cha ubadilishaji wa vibadilishio vya kamba zaidi. Unapotumia Scala, anuwai ya vipengele vya lugha vinapatikana ili kuboresha usanidi wako. Kwa mfano tunaweza kutumia
    sifa za maadili chaguo-msingi, kwa kutumia vitu kupanga vigezo vya kikundi, tunaweza kurejelea vali zilizotangazwa mara moja tu (KUKAUSHA) katika wigo unaoambatanisha. Unaweza kusisitiza madarasa yoyote moja kwa moja ndani ya usanidi (Seq, Map, madarasa maalum).
  3. DSL. Scala ina idadi ya vipengele vya lugha vinavyorahisisha kuunda DSL. Inawezekana kuchukua fursa ya vipengele hivi na kutekeleza lugha ya usanidi ambayo inafaa zaidi kwa kundi lengwa la watumiaji, ili usanidi uweze kusomeka angalau na wataalamu wa kikoa. Wataalamu wanaweza, kwa mfano, kushiriki katika mchakato wa ukaguzi wa usanidi.
  4. Uadilifu na usawazishaji kati ya nodi. Moja ya faida za kuwa na usanidi wa mfumo mzima uliosambazwa kuhifadhiwa katika sehemu moja ni kwamba maadili yote yanatangazwa mara moja na kisha kutumika tena popote yanahitajika. Kutumia aina za phantom kutangaza bandari huhakikisha kuwa nodi zinatumia itifaki zinazooana katika usanidi wote sahihi wa mfumo. Kuwa na utegemezi wa lazima kati ya nodi huhakikisha kuwa huduma zote zimeunganishwa.
  5. Mabadiliko ya ubora wa juu. Kufanya mabadiliko kwa usanidi kwa kutumia mchakato wa kawaida wa ukuzaji huwezesha kufikia viwango vya juu vya usanidi pia.
  6. Sasisho la usanidi kwa wakati mmoja. Usambazaji wa mfumo kiotomatiki baada ya mabadiliko ya usanidi huhakikisha kuwa nodi zote zimesasishwa.
  7. Kurahisisha maombi. Programu haihitaji kuchanganuliwa, kukagua usanidi, au kushughulikia thamani zisizo sahihi. Hii inapunguza ugumu wa programu. (Baadhi ya utata wa usanidi unaozingatiwa katika mfano wetu sio sifa ya usanidi uliokusanywa, lakini ni uamuzi wa fahamu tu unaoendeshwa na hamu ya kutoa usalama wa aina kubwa zaidi.) Ni rahisi sana kurudi kwenye usanidi wa kawaida - tekeleza tu kukosa. sehemu. Kwa hivyo, unaweza, kwa mfano, kuanza na usanidi uliojumuishwa, kuahirisha utekelezaji wa sehemu zisizo za lazima hadi wakati inahitajika.
  8. Usanidi ulioidhinishwa. Kwa kuwa mabadiliko ya usanidi hufuata hatima ya kawaida ya mabadiliko mengine yoyote, matokeo tunayopata ni vizalia vya programu vilivyo na toleo la kipekee. Hii inaruhusu sisi, kwa mfano, kurudi kwenye toleo la awali la usanidi ikiwa ni lazima. Tunaweza hata kutumia usanidi kutoka mwaka mmoja uliopita na mfumo utafanya kazi sawa sawa. Usanidi thabiti huboresha kutabirika na kutegemewa kwa mfumo uliosambazwa. Kwa kuwa usanidi umewekwa katika hatua ya ujumuishaji, ni ngumu sana kuidanganya katika uzalishaji.
  9. Modularity. Mfumo uliopendekezwa ni wa msimu na moduli zinaweza kuunganishwa kwa njia tofauti kuunda mifumo tofauti. Hasa, unaweza kusanidi mfumo wa kukimbia kwenye nodi moja katika embodiment moja, na kwenye nodes nyingi katika nyingine. Unaweza kuunda usanidi kadhaa kwa matukio ya uzalishaji wa mfumo.
  10. Kupima. Kwa kubadilisha huduma za kibinafsi na vitu vya kejeli, unaweza kupata matoleo kadhaa ya mfumo ambayo yanafaa kwa majaribio.
  11. Mtihani wa ujumuishaji. Kuwa na usanidi mmoja wa mfumo mzima unaosambazwa huwezesha kuendesha vipengele vyote katika mazingira yanayodhibitiwa kama sehemu ya majaribio ya ujumuishaji. Ni rahisi kuiga, kwa mfano, hali ambapo baadhi ya nodi zinapatikana.

Hasara na mapungufu

Usanidi uliokusanywa hutofautiana na mbinu zingine za usanidi na huenda usifae kwa baadhi ya programu. Zifuatazo ni baadhi ya hasara:

  1. Usanidi wa tuli. Wakati mwingine unahitaji kusahihisha haraka usanidi katika uzalishaji, kupitisha mifumo yote ya kinga. Kwa njia hii inaweza kuwa ngumu zaidi. Angalau, mkusanyiko na uwekaji kiotomatiki bado utahitajika. Hii ni kipengele muhimu cha mbinu na hasara katika baadhi ya matukio.
  2. Kizazi cha usanidi. Ikiwa faili ya usanidi itatolewa na zana ya kiotomatiki, juhudi za ziada zinaweza kuhitajika ili kuunganisha hati ya ujenzi.
  3. Zana. Hivi sasa, huduma na mbinu iliyoundwa kufanya kazi na usanidi zinatokana na faili za maandishi. Sio huduma/mbinu zote kama hizo zitapatikana katika usanidi uliokusanywa.
  4. Mabadiliko ya mitazamo yanahitajika. Wasanidi programu na DevOps wamezoea faili za maandishi. Wazo lenyewe la kuandaa usanidi linaweza kuwa lisilotarajiwa na lisilo la kawaida na kusababisha kukataliwa.
  5. Mchakato wa maendeleo ya ubora wa juu unahitajika. Ili kutumia kwa urahisi usanidi uliokusanywa, otomatiki kamili ya mchakato wa kujenga na kupeleka programu (CI/CD) ni muhimu. Vinginevyo itakuwa haifai kabisa.

Wacha pia tukae juu ya mapungufu kadhaa ya mfano unaozingatiwa ambao hauhusiani na wazo la usanidi uliokusanywa:

  1. Ikiwa tutatoa maelezo yasiyo ya lazima ya usanidi ambayo haitumiwi na nodi, basi mkusanyaji hatatusaidia kutambua utekelezaji unaokosekana. Shida hii inaweza kutatuliwa kwa kuacha muundo wa Keki na kutumia aina ngumu zaidi, kwa mfano, HList au aina za data za aljebra (kesi madarasa) ili kuwakilisha usanidi.
  2. Kuna mistari kwenye faili ya usanidi ambayo haihusiani na usanidi yenyewe: (package, import,matangazo ya kitu; override def's kwa vigezo ambavyo vina maadili chaguo-msingi). Hii inaweza kuepukwa ikiwa utatumia DSL yako mwenyewe. Kwa kuongeza, aina nyingine za usanidi (kwa mfano, XML) pia huweka vikwazo fulani kwenye muundo wa faili.
  3. Kwa madhumuni ya chapisho hili, hatuzingatii urekebishaji dhabiti wa kundi la nodi zinazofanana.

Hitimisho

Katika chapisho hili, tulichunguza wazo la kuwakilisha usanidi katika msimbo wa chanzo kwa kutumia uwezo wa juu wa mfumo wa aina ya Scala. Mbinu hii inaweza kutumika katika programu mbalimbali kama mbadala wa mbinu za usanidi wa jadi kulingana na xml au faili za maandishi. Ingawa mfano wetu unatekelezwa katika Scala, maoni sawa yanaweza kuhamishiwa kwa lugha zingine zilizokusanywa (kama vile Kotlin, C #, Swift, ...). Unaweza kujaribu mbinu hii katika mojawapo ya miradi ifuatayo, na, ikiwa haifanyi kazi, endelea kwenye faili ya maandishi, na kuongeza sehemu zilizopotea.

Kwa kawaida, usanidi uliokusanywa unahitaji mchakato wa maendeleo ya ubora wa juu. Kwa kurudi, ubora wa juu na uaminifu wa usanidi huhakikishwa.

Njia inayozingatiwa inaweza kupanuliwa:

  1. Unaweza kutumia macros kufanya ukaguzi wa wakati wa kukusanya.
  2. Unaweza kutekeleza DSL ili kuwasilisha usanidi kwa njia ambayo inaweza kufikiwa na watumiaji wa mwisho.
  3. Unaweza kutekeleza usimamizi wa rasilimali wenye nguvu na urekebishaji wa usanidi wa kiotomatiki. Kwa mfano, kubadilisha idadi ya nodi kwenye nguzo kunahitaji (1) kila nodi kupokea usanidi tofauti kidogo; (2) msimamizi wa nguzo alipokea taarifa kuhusu nodi mpya.

Shukrani

Ningependa kuwashukuru Andrei Saksonov, Pavel Popov na Anton Nekhaev kwa ukosoaji wao mzuri wa kifungu cha rasimu.

Chanzo: mapenzi.com

Kuongeza maoni