Тархсан програмуудын барилгын блокууд. Хоёр дахь ойролцоо

Зарлал

Хамт ажиллагсад аа, зуны дундуур би дарааллын системийн дизайны талаар өөр нэг цуврал нийтлэл гаргахаар төлөвлөж байна: "VTrade Experiment" - худалдааны системийн хүрээ бичих оролдлого. Цуврал нь бирж, дуудлага худалдаа, дэлгүүр байгуулах онол, практикийг судлах болно. Өгүүллийн төгсгөлд би таныг хамгийн их сонирхож буй сэдвүүдэд санал өгөхийг урьж байна.

Тархсан програмуудын барилгын блокууд. Хоёр дахь ойролцоо

Энэ бол Erlang/Elixir дахь тархсан реактив хэрэглээний тухай цувралын эцсийн нийтлэл юм. IN анхны нийтлэл та реактив архитектурын онолын үндсийг олж болно. Хоёр дахь нийтлэл Ийм системийг бий болгох үндсэн загвар, механизмыг харуулсан болно.

Өнөөдөр бид кодын бааз, ерөнхийдөө төслүүдийг хөгжүүлэх асуудлыг хөндөх болно.

Үйлчилгээний зохион байгуулалт

Бодит амьдрал дээр үйлчилгээг хөгжүүлэхдээ хэд хэдэн харилцан үйлчлэлийн загварыг нэг хянагч дээр нэгтгэх шаардлагатай болдог. Жишээлбэл, төслийн хэрэглэгчийн профайлыг удирдах асуудлыг шийддэг хэрэглэгчийн үйлчилгээ нь req-resp хүсэлтэд хариу өгөх, pub-sub-ээр дамжуулан профайлын шинэчлэлтийг мэдээлэх ёстой. Энэ тохиолдол маш энгийн: мессежийн ард үйлчилгээний логикийг хэрэгжүүлж, шинэчлэлтүүдийг нийтэлдэг нэг хянагч байдаг.

Бид алдааг тэсвэрлэх чадвартай түгээх үйлчилгээг хэрэгжүүлэх шаардлагатай үед нөхцөл байдал улам төвөгтэй болдог. Хэрэглэгчдэд тавигдах шаардлага өөрчлөгдсөн гэж төсөөлье.

  1. Одоо үйлчилгээ нь 5 кластер зангилаа дээрх хүсэлтийг боловсруулах ёстой.
  2. суурь боловсруулах ажлыг гүйцэтгэх чадвартай байх,
  3. мөн профайлын шинэчлэлтийн захиалгын жагсаалтыг динамикаар удирдах боломжтой.

Сэтгэгдэл бичих: Бид өгөгдлийг тогтмол хадгалах, хуулбарлах асуудлыг авч үзэхгүй. Эдгээр асуудлууд өмнө нь шийдэгдсэн бөгөөд систем нь найдвартай, өргөтгөх боломжтой хадгалах давхаргатай, зохицуулагчид түүнтэй харилцах механизмтай болсон гэж бодъё.

Хэрэглэгчийн үйлчилгээний албан ёсны тайлбар нь илүү төвөгтэй болсон. Програмистын үүднээс авч үзвэл, мессежийг ашигласнаар өөрчлөлтүүд хамгийн бага байдаг. Эхний шаардлагыг хангахын тулд бид req-resp солилцооны цэг дээр тэнцвэржүүлэх тохиргоог хийх хэрэгтэй.

Суурь даалгавруудыг боловсруулах шаардлага байнга гардаг. Хэрэглэгчдийн хувьд энэ нь хэрэглэгчийн баримт бичгийг шалгах, татаж авсан мультимедиа боловсруулах эсвэл олон нийтийн мэдээллийн хэрэгсэлтэй өгөгдлийг синхрончлох явдал байж болно. сүлжээнүүд. Эдгээр ажлыг кластер дотор ямар нэгэн байдлаар хуваарилж, гүйцэтгэлийн явцыг хянах шаардлагатай. Тиймээс, бидэнд хоёр шийдлийн сонголт байна: өмнөх нийтлэлийн даалгаврын хуваарилалтын загварыг ашиглах, эсвэл тохирохгүй бол процессоруудын санг бидэнд хэрэгтэй байдлаар удирдах захиалгат даалгавар төлөвлөгчийг бичих.

3-р цэг нь pub-sub загварын өргөтгөлийг шаарддаг. Хэрэгжүүлэхийн тулд паб-суб солилцооны цэгийг үүсгэсний дараа бид энэ цэгийн хянагчийг үйлчилгээндээ нэмж ажиллуулах хэрэгтэй. Тиймээс бид захиалгыг боловсруулах логикийг мессежийн давхаргаас хэрэглэгчдийн хэрэгжилт рүү шилжүүлж байгаа юм шиг байна.

Үүний үр дүнд асуудлын задаргаа нь шаардлагыг хангахын тулд өөр өөр зангилаанууд дээр үйлчилгээний 5 тохиолдлыг ажиллуулж, захиалгыг хариуцах нэмэлт нэгж болох паб-дэд хянагч үүсгэх шаардлагатай байгааг харуулж байна.
5 зохицуулагч ажиллуулахын тулд үйлчилгээний кодыг өөрчлөх шаардлагагүй. Цорын ганц нэмэлт арга хэмжээ бол солилцооны цэг дээр тэнцвэржүүлэх дүрмийг бий болгох явдал бөгөөд бид үүнийг дараа нь ярих болно.
Мөн нэмэлт төвөгтэй байдал бий: паб-дэд хянагч болон захиалгат даалгавар төлөвлөгч нь нэг хуулбараар ажиллах ёстой. Дахин хэлэхэд мессежийн үйлчилгээ нь үндсэн үйлчилгээнийхээ хувьд удирдагчийг сонгох механизмыг хангах ёстой.

Удирдагч сонгох

Тархсан системд удирдагчийн сонгууль гэдэг нь зарим ачааллын хуваарилагдсан боловсруулалтыг төлөвлөх үүрэгтэй нэг процессыг томилох журам юм.

Төвлөрөлд өртөмтгий биш системүүдэд paxos эсвэл raft гэх мэт бүх нийтийн болон зөвшилцөлд суурилсан алгоритмуудыг ашигладаг.
Мессеж нь зуучлагч, гол элемент учраас бүх үйлчилгээний хянагч - нэр дэвшигч удирдагчдын талаар мэддэг. Мессеж нь санал өгөхгүйгээр удирдагчийг томилж болно.

Солилцооны цэгийг эхлүүлж, холбогдсоны дараа бүх үйлчилгээ нь системийн мессежийг хүлээн авдаг #'$leader'{exchange = ?EXCHANGE, pid = LeaderPid, servers = Servers}. Хэрэв LeaderPid давхцаж байна pid одоогийн үйл явц, энэ нь удирдагчаар томилогдсон, жагсаалт Servers бүх зангилаа болон тэдгээрийн параметрүүдийг багтаана.
Одоогийн байдлаар шинээр гарч ирэх ба ажиллаж байгаа кластерийн зангилаа салгагдсан үед бүх үйлчилгээний хянагч хүлээн авдаг. #'$slave_up'{exchange = ?EXCHANGE, pid = SlavePid, options = SlaveOpts} и #'$slave_down'{exchange = ?EXCHANGE, pid = SlavePid, options = SlaveOpts} тус тусдаа.

Ингэснээр бүх бүрэлдэхүүн хэсгүүд бүх өөрчлөлтийг мэддэг бөгөөд кластер нь ямар ч үед нэг удирдагчтай байх баталгаатай болно.

Зуучлагч

Нарийн төвөгтэй тархсан боловсруулалтын процессыг хэрэгжүүлэх, түүнчлэн одоо байгаа архитектурыг оновчтой болгох асуудалд зуучлагчдыг ашиглах нь тохиромжтой.
Үйлчилгээний кодыг өөрчлөхгүй байх, жишээлбэл, мессежийг нэмэлт боловсруулах, чиглүүлэх, бүртгэх зэрэг асуудлыг шийдэхгүйн тулд та үйлчилгээний өмнө прокси зохицуулагчийг идэвхжүүлж, бүх нэмэлт ажлыг гүйцэтгэх боломжтой.

Pub-sub оновчлолын сонгодог жишээ бол зах зээл дээрх үнийн өөрчлөлт гэх мэт шинэчлэлтийн үйл явдлуудыг бий болгодог бизнесийн цөм бүхий тархсан програм ба вэб үйлчлүүлэгчдэд зориулсан websocket API-г хангадаг хандалтын давхарга - N сервер юм.
Хэрэв та шууд шийдсэн бол харилцагчийн үйлчилгээ дараах байдалтай байна.

  • үйлчлүүлэгч платформтой холбоо тогтоодог. Траффикийг зогсоож буй серверийн талд энэ холболтод үйлчлэх процессыг эхлүүлнэ.
  • Үйлчилгээний үйл явцын хүрээнд зөвшөөрөл авах, шинэчлэлтийг захиалах явдал гардаг. Уг процесс нь сэдвүүдийг захиалах аргыг дууддаг.
  • Цөмд үйл явдал үүсгэсний дараа холболтуудад үйлчилдэг процессуудад хүргэдэг.

Бид "мэдээ" сэдвийг 50000 захиалагчтай гэж төсөөлөөд үз дээ. Захиалагчдыг 5 серверт жигд хуваарилдаг. Үүний үр дүнд солилцооны цэг дээр ирсэн шинэчлэлт бүр 50000 удаа давтагдах болно: сервер тус бүр дээр түүн дээрх захиалагчдын тоогоор 10000 удаа. Маш үр дүнтэй схем биш, тийм үү?
Нөхцөл байдлыг сайжруулахын тулд солилцооны цэгтэй ижил нэртэй проксиг нэвтрүүлье. Дэлхийн нэр бүртгэгч нь хамгийн ойрын процессыг нэрээр нь буцаах боломжтой байх ёстой, энэ нь чухал юм.

Энэ прокси-г хандалтын түвшний серверүүд дээр ажиллуулъя, тэгвэл вэбсокет api-д үйлчилдэг бидний бүх процессууд цөм дэх анхны pub-sub солилцооны цэгт биш харин үүнтэй бүртгүүлэх болно. Прокси нь зөвхөн өвөрмөц захиалгатай тохиолдолд л үндсэн дээр бүртгүүлж, ирж буй мессежийг бүх захиалагчдаа хуулбарладаг.
Үүний үр дүнд цөм болон хандалтын серверүүдийн хооронд 5 биш 50000 мессеж илгээгдэх болно.

Чиглүүлэлт ба тэнцвэржүүлэх

Req-Resp

Одоогийн мессежийн хэрэгжилтэд хүсэлтийг түгээх 7 стратеги байдаг:

  • default. Хүсэлтийг бүх хянагч руу илгээдэг.
  • round-robin. Хүсэлтүүдийг тоолж, хянагчийн хооронд мөчлөгөөр хуваарилдаг.
  • consensus. Үйлчилгээнд үйлчилдэг хянагчдыг удирдагч, боол гэж хуваадаг. Хүсэлтийг зөвхөн удирдагч руу илгээдэг.
  • consensus & round-robin. Бүлэг нь удирдагчтай боловч хүсэлтийг бүх гишүүдэд хуваарилдаг.
  • sticky. Хэш функцийг тооцоолж, тодорхой зохицуулагчид хуваарилдаг. Энэ гарын үсэг бүхий дараагийн хүсэлтүүд ижил зохицуулагч руу очно.
  • sticky-fun. Солилцооны цэгийг эхлүүлэх үед хэш тооцоолох функц sticky тэнцвэржүүлэх.
  • fun. Наалттай-хөгжилтэй адил, зөвхөн та үүнийг дахин чиглүүлэх, татгалзах эсвэл урьдчилан боловсруулах боломжтой.

Солилцооны цэгийг эхлүүлэх үед түгээлтийн стратеги тогтоогддог.

Тэнцвэржүүлэхээс гадна мессеж нь аж ахуйн нэгжүүдийг шошголох боломжийг олгодог. Систем дэх шошгын төрлүүдийг харцгаая.

  • Холболтын шошго. Үйл явдал ямар холболтоор ирснийг ойлгох боломжийг танд олгоно. Хянагч процесс нь ижил солилцооны цэгт холбогдсон боловч өөр өөр чиглүүлэлтийн түлхүүртэй үед ашиглагддаг.
  • Үйлчилгээний шошго. Нэг үйлчилгээнд зориулж зохицуулагчдыг бүлэг болгон нэгтгэж, чиглүүлэлт болон тэнцвэржүүлэх чадварыг өргөжүүлэх боломжийг танд олгоно. req-resp загварын хувьд чиглүүлэлт нь шугаман байна. Бид солилцооны цэг рүү хүсэлт илгээж, дараа нь үйлчилгээ рүү дамжуулдаг. Гэхдээ хэрэв бид зохицуулагчдыг логик бүлгүүдэд хуваах шаардлагатай бол хуваах нь шошго ашиглан хийгддэг. Тагийг зааж өгөхдөө хүсэлтийг тодорхой бүлэг хянагч руу илгээнэ.
  • Хүсэлтийн шошго. Хариултуудыг ялгах боломжийг танд олгоно. Манай систем асинхрон учраас үйлчилгээний хариуг боловсруулахын тулд хүсэлт илгээхдээ RequestTag-г зааж өгөх хэрэгтэй. Үүнээс бид ямар хүсэлт бидэнд ирсэн хариултыг ойлгох болно.

Pub-sub

Pub-sub-ийн хувьд бүх зүйл арай хялбар байдаг. Бидэнд мессеж нийтлэх солилцооны цэг бий. Солилцооны цэг нь өөрт хэрэгтэй чиглүүлэлтийн түлхүүрүүдийг захиалсан захиалагчдын дунд мессежийг түгээдэг (энэ нь сэдвүүдийн аналог гэж хэлж болно).

Өргөтгөх чадвар ба алдааг тэсвэрлэх чадвар

Системийн өргөтгөх чадвар нь системийн давхарга болон бүрэлдэхүүн хэсгүүдийн өргөтгөх чадвараас хамаарна.

  • Энэ үйлчилгээний зохицуулагчтай кластерт нэмэлт зангилаа нэмэх замаар үйлчилгээг масштабтай болгодог. Туршилтын явцад та тэнцвэржүүлэх оновчтой бодлогыг сонгож болно.
  • Тусдаа кластер доторх мессежийн үйлчилгээ нь ихэвчлэн ачаалал ихтэй солилцооны цэгүүдийг салангид кластерын зангилаанууд руу шилжүүлэх, эсвэл кластерын ачаалал ихтэй хэсэгт прокси процессуудыг нэмэх замаар ерөнхийдөө масштабтай байдаг.
  • Бүхэл системийн шинж чанар нь архитектурын уян хатан байдал, тусдаа кластеруудыг нийтлэг логик нэгж болгон нэгтгэх чадвараас хамаарна.

Төслийн амжилт нь ихэвчлэн масштабын энгийн, хурдаас хамаардаг. Одоогийн хувилбар дахь мессеж нь аппликешныг дагаж өсдөг. 50-60 машинтай кластер дутагдсан ч холбоонд хандаж болно. Харамсалтай нь холбооны сэдэв энэ нийтлэлийн хүрээнээс хэтэрсэн байна.

Захиалга

Ачаалал тэнцвэржүүлэхэд дүн шинжилгээ хийхдээ бид үйлчилгээний хянагчдыг нэмэгдүүлэх талаар аль хэдийн ярилцсан. Гэсэн хэдий ч мессежийг мөн нөөцлөх ёстой. Зангилаа эсвэл машин эвдэрсэн тохиолдолд мессеж автоматаар сэргээгдэх бөгөөд хамгийн богино хугацаанд.

Миний төслүүдэд би унах үед ачааллыг авдаг нэмэлт зангилаа ашигладаг. Erlang нь OTP програмуудад зориулсан стандарт тархсан горимын хэрэгжилттэй. Тархсан горим нь бүтэлгүйтсэн програмыг өмнө нь эхлүүлсэн өөр зангилаан дээр ажиллуулснаар бүтэлгүйтсэн тохиолдолд сэргээх ажиллагааг гүйцэтгэдэг. Процесс нь ил тод бөгөөд алдаа гарсны дараа програм автоматаар шилжүүлгийн зангилаа руу шилждэг. Та энэ функцын талаар илүү ихийг уншиж болно энд.

Бүтээмж

Ядаж rabbitmq болон бидний захиалгат мессежийн гүйцэтгэлийг ойролцоогоор харьцуулахыг хичээцгээе.
би олсон албан ёсны үр дүн Openstack багийн rabbitmq тест.

6.14.1.2.1.2.2-д. Анхны баримт бичиг нь RPC CAST-ийн үр дүнг харуулж байна:
Тархсан програмуудын барилгын блокууд. Хоёр дахь ойролцоо

Бид OS цөм эсвэл erlang VM дээр нэмэлт тохиргоог урьдчилан хийхгүй. Туршилт хийх нөхцөл:

  • erl сонголт: +A1 +sbtu.
  • Нэг эрлангийн зангилаа доторх тестийг гар утасны хувилбарт хуучин i7-тэй зөөврийн компьютер дээр ажиллуулдаг.
  • Кластер туршилтыг 10G сүлжээтэй серверүүд дээр явуулдаг.
  • Код нь докер контейнерт ажилладаг. NAT горимд байгаа сүлжээ.

Туршилтын код:

req_resp_bench(_) ->
  W = perftest:comprehensive(10000,
    fun() ->
      messaging:request(?EXCHANGE, default, ping, self()),
      receive
        #'$msg'{message = pong} -> ok
      after 5000 ->
        throw(timeout)
      end
    end
  ),
  true = lists:any(fun(E) -> E >= 30000 end, W),
  ok.

Хувилбар 1: Туршилтыг хуучин i7 гар утасны хувилбартай зөөврийн компьютер дээр явуулдаг. Туршилт, мессеж, үйлчилгээг нэг Docker контейнерийн нэг зангилаа дээр гүйцэтгэдэг.

Sequential 10000 cycles in ~0 seconds (26987 cycles/s)
Sequential 20000 cycles in ~1 seconds (26915 cycles/s)
Sequential 100000 cycles in ~4 seconds (26957 cycles/s)
Parallel 2 100000 cycles in ~2 seconds (44240 cycles/s)
Parallel 4 100000 cycles in ~2 seconds (53459 cycles/s)
Parallel 10 100000 cycles in ~2 seconds (52283 cycles/s)
Parallel 100 100000 cycles in ~3 seconds (49317 cycles/s)

Хувилбар 2: Докер (NAT) дор өөр өөр машинууд дээр ажилладаг 3 зангилаа.

Sequential 10000 cycles in ~1 seconds (8684 cycles/s)
Sequential 20000 cycles in ~2 seconds (8424 cycles/s)
Sequential 100000 cycles in ~12 seconds (8655 cycles/s)
Parallel 2 100000 cycles in ~7 seconds (15160 cycles/s)
Parallel 4 100000 cycles in ~5 seconds (19133 cycles/s)
Parallel 10 100000 cycles in ~4 seconds (24399 cycles/s)
Parallel 100 100000 cycles in ~3 seconds (34517 cycles/s)

Бүх тохиолдолд CPU-ийн ашиглалт 250% -иас хэтрэхгүй байна.

Үр дүн

Энэ мөчлөг нь оюун ухааны хомсдол шиг харагдахгүй байгаа бөгөөд миний туршлага тараасан системийн судлаачид болон бизнесийн системдээ хуваарилагдсан архитектурыг бүтээх ажлын эхэнд байгаа, Erlang/Elixir-ийг сонирхож буй мэргэжилтнүүдэд бодит ашиг тустай байх болно гэж найдаж байна. , гэхдээ энэ нь үнэ цэнэтэй гэдэгт эргэлзэж байна ...

Фото зураг @chuttersnap

Зөвхөн бүртгэлтэй хэрэглэгчид санал асуулгад оролцох боломжтой. Нэвтрэх, гуйя.

VTrade Experiment цувралын нэг хэсэг болгон би ямар сэдвүүдийг илүү нарийвчлан авч үзэх ёстой вэ?

  • Онол: Зах зээл, захиалга, тэдгээрийн цаг хугацаа: ӨДӨР, GTD, GTC, ОУОХ, FOK, MOO, MOC, LOO, LOC

  • Захиалгын ном. Бүлэглэл бүхий номыг хэрэгжүүлэх онол практик

  • Арилжааны дүрслэл: Хачиг, баар, тогтоол. Хэрхэн хадгалах, яаж наах вэ

  • Арын алба. Төлөвлөлт ба хөгжил. Ажилчдын хяналт, ослын судалгаа

  • API. Ямар интерфейс хэрэгтэй, тэдгээрийг хэрхэн хэрэгжүүлэх талаар олж мэдье

  • Мэдээллийн хадгалалт: Худалдааны систем дэх PostgreSQL, Timescale, Tarantool

  • Худалдааны систем дэх реактив байдал

  • Бусад. Би сэтгэгдэл дээр бичнэ

6 хэрэглэгч санал өгсөн. 4 хэрэглэгч түдгэлзсэн.

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх