గతం లో
- అభ్యర్థన-ప్రతిస్పందన
- అభ్యర్థన-చంక్డ్ ప్రతిస్పందన
- అభ్యర్థనతో ప్రతిస్పందన
- ప్రచురించు-చందా
- విలోమ ప్రచురణ-చందా
- విధి పంపిణీ
SOA, MSA మరియు మెసేజింగ్
SOA, MSA అనేవి సిస్టమ్ ఆర్కిటెక్చర్లు, ఇవి బిల్డింగ్ సిస్టమ్ల కోసం నియమాలను నిర్వచిస్తాయి, అయితే మెసేజింగ్ వాటి అమలు కోసం ఆదిమాలను అందిస్తుంది.
నేను ఈ లేదా ఆ సిస్టమ్ ఆర్కిటెక్చర్ని ప్రోత్సహించాలనుకోవడం లేదు. నేను నిర్దిష్ట ప్రాజెక్ట్ మరియు వ్యాపారం కోసం అత్యంత ప్రభావవంతమైన మరియు ఉపయోగకరమైన పద్ధతులను ఉపయోగిస్తున్నాను. మనం ఎంచుకున్న నమూనా ఏమైనప్పటికీ, Unix-wayని దృష్టిలో ఉంచుకుని సిస్టమ్ బ్లాక్లను సృష్టించడం ఉత్తమం: కనీస కనెక్టివిటీతో కూడిన భాగాలు, వ్యక్తిగత ఎంటిటీలకు బాధ్యత వహిస్తాయి. API పద్ధతులు ఎంటిటీలతో సాధ్యమైనంత సరళమైన చర్యలను చేస్తాయి.
మెసేజింగ్ అనేది పేరు సూచించినట్లుగా, మెసేజ్ బ్రోకర్. సందేశాలను స్వీకరించడం మరియు పంపడం దీని ప్రధాన ఉద్దేశ్యం. సమాచారాన్ని పంపే ఇంటర్ఫేస్లు, సిస్టమ్లోని సమాచారాన్ని ప్రసారం చేయడానికి తార్కిక ఛానెల్ల ఏర్పాటు, రూటింగ్ మరియు బ్యాలెన్సింగ్, అలాగే సిస్టమ్ స్థాయిలో తప్పు నిర్వహణకు ఇది బాధ్యత వహిస్తుంది.
మేము అభివృద్ధి చేస్తున్న సందేశం rabbitmqతో పోటీ పడేందుకు లేదా భర్తీ చేయడానికి ప్రయత్నించడం లేదు. దీని ప్రధాన లక్షణాలు:
- పంపిణీ.
ఎక్స్ఛేంజ్ పాయింట్లను అన్ని క్లస్టర్ నోడ్లలో, వాటిని ఉపయోగించే కోడ్కు వీలైనంత దగ్గరగా సృష్టించవచ్చు. - సింప్లిసిటీ.
బాయిలర్ప్లేట్ కోడ్ను తగ్గించడం మరియు వాడుకలో సౌలభ్యంపై దృష్టి పెట్టండి. - మంచి పనితీరు.
మేము rabbitmq యొక్క ఫంక్షనాలిటీని పునరావృతం చేయడానికి ప్రయత్నించడం లేదు, అయితే ఆర్కిటెక్చరల్ మరియు ట్రాన్స్పోర్ట్ లేయర్ను మాత్రమే హైలైట్ చేస్తాము, ఇది మేము వీలైనంత సులభంగా OTPకి సరిపోతాయి, ఖర్చులను తగ్గిస్తుంది. - వశ్యత.
ప్రతి సేవ అనేక మార్పిడి టెంప్లేట్లను కలపవచ్చు. - డిజైన్ ద్వారా స్థితిస్థాపకత.
- స్కేలబిలిటీ.
అప్లికేషన్తో మెసేజింగ్ పెరుగుతుంది. లోడ్ పెరిగినప్పుడు, మీరు ఎక్స్ఛేంజ్ పాయింట్లను వ్యక్తిగత యంత్రాలకు తరలించవచ్చు.
గమనిక. కోడ్ ఆర్గనైజేషన్ పరంగా, మెటా-ప్రాజెక్ట్లు సంక్లిష్టమైన ఎర్లాంగ్/ఎలిక్సర్ సిస్టమ్లకు బాగా సరిపోతాయి. అన్ని ప్రాజెక్ట్ కోడ్ ఒక రిపోజిటరీలో ఉంది - ఒక గొడుగు ప్రాజెక్ట్. అదే సమయంలో, మైక్రోసర్వీస్లు గరిష్టంగా వేరుచేయబడతాయి మరియు ప్రత్యేక సంస్థకు బాధ్యత వహించే సాధారణ కార్యకలాపాలను నిర్వహిస్తాయి. ఈ విధానంతో, మొత్తం సిస్టమ్ యొక్క APIని నిర్వహించడం సులభం, మార్పులు చేయడం సులభం, యూనిట్ మరియు ఇంటిగ్రేషన్ పరీక్షలు రాయడం సౌకర్యంగా ఉంటుంది.
సిస్టమ్ భాగాలు నేరుగా లేదా బ్రోకర్ ద్వారా పరస్పర చర్య చేస్తాయి. మెసేజింగ్ కోణం నుండి, ప్రతి సేవకు అనేక జీవిత దశలు ఉన్నాయి:
- సేవ ప్రారంభించడం.
ఈ దశలో, సేవను అమలు చేసే ప్రక్రియ మరియు డిపెండెన్సీలు కాన్ఫిగర్ చేయబడతాయి మరియు ప్రారంభించబడతాయి. - మార్పిడి పాయింట్ను సృష్టిస్తోంది.
సేవ నోడ్ కాన్ఫిగరేషన్లో పేర్కొన్న స్టాటిక్ ఎక్స్ఛేంజ్ పాయింట్ని ఉపయోగించవచ్చు లేదా డైనమిక్గా ఎక్స్ఛేంజ్ పాయింట్లను సృష్టించవచ్చు. - సేవ నమోదు.
సేవ అభ్యర్థనలను అందించడానికి, అది తప్పనిసరిగా మార్పిడి పాయింట్ వద్ద నమోదు చేయబడాలి. - సాధారణ పనితీరు.
సేవ ఉపయోగకరమైన పనిని ఉత్పత్తి చేస్తుంది. - షట్డౌన్.
2 రకాల షట్డౌన్ సాధ్యమే: సాధారణ మరియు అత్యవసర. సాధారణ ఆపరేషన్ సమయంలో, సేవ మార్పిడి పాయింట్ నుండి డిస్కనెక్ట్ చేయబడుతుంది మరియు ఆగిపోతుంది. అత్యవసర పరిస్థితుల్లో, మెసేజింగ్ ఫెయిల్ఓవర్ స్క్రిప్ట్లలో ఒకదాన్ని అమలు చేస్తుంది.
ఇది చాలా క్లిష్టంగా కనిపిస్తుంది, కానీ కోడ్ అంత భయానకంగా లేదు. వ్యాఖ్యలతో కూడిన కోడ్ ఉదాహరణలు కొంచెం తరువాత టెంప్లేట్ల విశ్లేషణలో ఇవ్వబడతాయి.
ఎక్స్చేంజెస్
ఎక్స్ఛేంజ్ పాయింట్ అనేది మెసేజింగ్ టెంప్లేట్లోని భాగాలతో పరస్పర చర్య యొక్క లాజిక్ను అమలు చేసే సందేశ ప్రక్రియ. దిగువ అందించబడిన అన్ని ఉదాహరణలలో, భాగాలు మార్పిడి పాయింట్ల ద్వారా పరస్పర చర్య చేస్తాయి, వీటి కలయిక సందేశాన్ని ఏర్పరుస్తుంది.
సందేశ మార్పిడి నమూనాలు (MEPలు)
ప్రపంచవ్యాప్తంగా, మార్పిడి నమూనాలను రెండు-మార్గం మరియు ఒక-మార్గంగా విభజించవచ్చు. మొదటిది ఇన్కమింగ్ సందేశానికి ప్రతిస్పందనను సూచిస్తుంది, రెండోది చేయదు. క్లయింట్-సర్వర్ ఆర్కిటెక్చర్లో రెండు-మార్గం నమూనాకు ఒక క్లాసిక్ ఉదాహరణ అభ్యర్థన-ప్రతిస్పందన నమూనా. టెంప్లేట్ మరియు దాని సవరణలను చూద్దాం.
అభ్యర్థన-ప్రతిస్పందన లేదా RPC
మేము మరొక ప్రక్రియ నుండి ప్రతిస్పందనను స్వీకరించవలసి వచ్చినప్పుడు RPC ఉపయోగించబడుతుంది. ఈ ప్రక్రియ ఒకే నోడ్లో రన్ అయి ఉండవచ్చు లేదా వేరే ఖండంలో ఉండవచ్చు. మెసేజింగ్ ద్వారా క్లయింట్ మరియు సర్వర్ మధ్య పరస్పర చర్య యొక్క రేఖాచిత్రం క్రింద ఉంది.
సందేశం పూర్తిగా అసమకాలికమైనందున, క్లయింట్ కోసం మార్పిడి 2 దశలుగా విభజించబడింది:
-
అభ్యర్థనను పంపుతోంది
messaging:request(Exchange, ResponseMatchingTag, RequestDefinition, HandlerProcess).
ఎక్స్చేంజ్ ‒ మార్పిడి పాయింట్ యొక్క ప్రత్యేక పేరు
ResponseMatchingTag ‒ ప్రతిస్పందనను ప్రాసెస్ చేయడానికి స్థానిక లేబుల్. ఉదాహరణకు, వేర్వేరు వినియోగదారులకు చెందిన అనేక సారూప్య అభ్యర్థనలను పంపే సందర్భంలో.
అభ్యర్థన నిర్వచనం - అభ్యర్థన శరీరం
హ్యాండ్లర్ ప్రాసెస్ హ్యాండ్లర్ యొక్క PID. ఈ ప్రక్రియ సర్వర్ నుండి ప్రతిస్పందనను అందుకుంటుంది. -
ప్రతిస్పందనను ప్రాసెస్ చేస్తోంది
handle_info(#'$msg'{exchange = EXCHANGE, tag = ResponseMatchingTag,message = ResponsePayload}, State)
ప్రతిస్పందన పేలోడ్ - సర్వర్ ప్రతిస్పందన.
సర్వర్ కోసం, ప్రక్రియ కూడా 2 దశలను కలిగి ఉంటుంది:
- మార్పిడి పాయింట్ను ప్రారంభించడం
- స్వీకరించిన అభ్యర్థనల ప్రాసెసింగ్
ఈ టెంప్లేట్ని కోడ్తో ఉదహరిద్దాం. మేము ఒకే ఖచ్చితమైన సమయ పద్ధతిని అందించే సరళమైన సేవను అమలు చేయాలని చెప్పండి.
సర్వర్ కోడ్
api.hrlలో సేవ APIని నిర్వచిద్దాం:
%% =====================================================
%% entities
%% =====================================================
-record(time, {
unixtime :: non_neg_integer(),
datetime :: binary()
}).
-record(time_error, {
code :: non_neg_integer(),
error :: term()
}).
%% =====================================================
%% methods
%% =====================================================
-record(time_req, {
opts :: term()
}).
-record(time_resp, {
result :: #time{} | #time_error{}
}).
time_controller.erlలో సర్వీస్ కంట్రోలర్ని నిర్వచిద్దాం
%% В примере показан только значимый код. Вставив его в шаблон gen_server можно получить рабочий сервис.
%% инициализация gen_server
init(Args) ->
%% подключение к точке обмена
messaging:monitor_exchange(req_resp, ?EXCHANGE, default, self())
{ok, #{}}.
%% обработка события потери связи с точкой обмена. Это же событие приходит, если точка обмена еще не запустилась.
handle_info(#exchange_die{exchange = ?EXCHANGE}, State) ->
erlang:send(self(), monitor_exchange),
{noreply, State};
%% обработка API
handle_info(#time_req{opts = _Opts}, State) ->
messaging:response_once(Client, #time_resp{
result = #time{ unixtime = time_utils:unixtime(now()), datetime = time_utils:iso8601_fmt(now())}
});
{noreply, State};
%% завершение работы gen_server
terminate(_Reason, _State) ->
messaging:demonitor_exchange(req_resp, ?EXCHANGE, default, self()),
ok.
క్లయింట్ కోడ్
సేవకు అభ్యర్థనను పంపడానికి, మీరు క్లయింట్లో ఎక్కడైనా సందేశ అభ్యర్థన APIకి కాల్ చేయవచ్చు:
case messaging:request(?EXCHANGE, tag, #time_req{opts = #{}}, self()) of
ok -> ok;
_ -> %% repeat or fail logic
end
పంపిణీ చేయబడిన సిస్టమ్లో, కాంపోనెంట్ల కాన్ఫిగరేషన్ చాలా భిన్నంగా ఉంటుంది మరియు అభ్యర్థన సమయంలో, సందేశం పంపడం ఇంకా ప్రారంభించకపోవచ్చు లేదా సర్వీస్ కంట్రోలర్ అభ్యర్థనను అందించడానికి సిద్ధంగా ఉండదు. అందువల్ల, మేము సందేశ ప్రతిస్పందనను తనిఖీ చేయాలి మరియు వైఫల్యం కేసును నిర్వహించాలి.
విజయవంతంగా పంపిన తర్వాత, క్లయింట్ సేవ నుండి ప్రతిస్పందన లేదా లోపాన్ని అందుకుంటారు.
హ్యాండిల్_ఇన్ఫోలో రెండు కేసులను పరిశీలిద్దాం:
handle_info(#'$msg'{exchange = ?EXCHANGE, tag = tag, message = #time_resp{result = #time{unixtime = Utime}}}, State) ->
?debugVal(Utime),
{noreply, State};
handle_info(#'$msg'{exchange = ?EXCHANGE, tag = tag, message = #time_resp{result = #time_error{code = ErrorCode}}}, State) ->
?debugVal({error, ErrorCode}),
{noreply, State};
అభ్యర్థన-చంక్డ్ ప్రతిస్పందన
భారీ మెసేజ్లు పంపకుండా ఉండటమే మంచిది. మొత్తం సిస్టమ్ యొక్క ప్రతిస్పందన మరియు స్థిరమైన ఆపరేషన్ దీనిపై ఆధారపడి ఉంటుంది. ప్రశ్నకు ప్రతిస్పందన చాలా మెమరీని తీసుకుంటే, దానిని భాగాలుగా విభజించడం తప్పనిసరి.
అటువంటి సందర్భాలలో నేను మీకు కొన్ని ఉదాహరణలు ఇస్తాను:
- భాగాలు ఫైల్స్ వంటి బైనరీ డేటాను మార్పిడి చేస్తాయి. ప్రతిస్పందనను చిన్న భాగాలుగా విభజించడం వలన మీరు ఏ పరిమాణంలోనైనా ఫైల్లతో సమర్థవంతంగా పని చేయడంలో మరియు మెమరీ ఓవర్ఫ్లోలను నివారించడంలో సహాయపడుతుంది.
- జాబితాలు. ఉదాహరణకు, మేము డేటాబేస్లోని భారీ పట్టిక నుండి అన్ని రికార్డులను ఎంచుకుని, వాటిని మరొక భాగానికి బదిలీ చేయాలి.
నేను ఈ ప్రతిస్పందనలను లోకోమోటివ్ అని పిలుస్తాను. ఏది ఏమైనప్పటికీ, 1024 GB యొక్క 1 సందేశాలు 1 GB యొక్క ఒక సందేశం కంటే మెరుగైనవి.
ఎర్లాంగ్ క్లస్టర్లో, మేము అదనపు ప్రయోజనాన్ని పొందుతాము - ఎక్స్ఛేంజ్ పాయింట్ మరియు నెట్వర్క్పై లోడ్ను తగ్గించడం, ప్రతిస్పందనలు వెంటనే స్వీకర్తకు పంపబడతాయి, మార్పిడి పాయింట్ను దాటవేస్తాయి.
అభ్యర్థనతో ప్రతిస్పందన
ఇది డైలాగ్ సిస్టమ్లను నిర్మించడానికి RPC నమూనా యొక్క అరుదైన మార్పు.
ప్రచురించు-చందా (డేటా పంపిణీ చెట్టు)
ఈవెంట్-ఆధారిత సిస్టమ్లు డేటా సిద్ధంగా ఉన్న వెంటనే వాటిని వినియోగదారులకు అందజేస్తాయి. అందువల్ల, సిస్టమ్లు పుల్ లేదా పోల్ మోడల్ కంటే పుష్ మోడల్కు ఎక్కువ అవకాశం ఉంది. డేటా కోసం నిరంతరం అభ్యర్థించడం మరియు వేచి ఉండటం ద్వారా వనరులను వృధా చేయకుండా ఉండటానికి ఈ ఫీచర్ మిమ్మల్ని అనుమతిస్తుంది.
నిర్దిష్ట అంశానికి సభ్యత్వం పొందిన వినియోగదారులకు సందేశాన్ని పంపిణీ చేసే ప్రక్రియను బొమ్మ చూపుతుంది.
ఈ నమూనాను ఉపయోగించడం యొక్క క్లాసిక్ ఉదాహరణలు రాష్ట్ర పంపిణీ: కంప్యూటర్ గేమ్లలో గేమ్ ప్రపంచం, ఎక్స్ఛేంజీలపై మార్కెట్ డేటా, డేటా ఫీడ్లలో ఉపయోగకరమైన సమాచారం.
చందాదారుల కోడ్ను చూద్దాం:
init(_Args) ->
%% подписываемся на обменник, ключ = key
messaging:subscribe(?SUBSCRIPTION, key, tag, self()),
{ok, #{}}.
handle_info(#exchange_die{exchange = ?SUBSCRIPTION}, State) ->
%% если точка обмена недоступна, то пытаемся переподключиться
messaging:subscribe(?SUBSCRIPTION, key, tag, self()),
{noreply, State};
%% обрабатываем пришедшие сообщения
handle_info(#'$msg'{exchange = ?SUBSCRIPTION, message = Msg}, State) ->
?debugVal(Msg),
{noreply, State};
%% при остановке потребителя - отключаемся от точки обмена
terminate(_Reason, _State) ->
messaging:unsubscribe(?SUBSCRIPTION, key, tag, self()),
ok.
ఏదైనా అనుకూలమైన ప్రదేశంలో సందేశాన్ని ప్రచురించడానికి మూలం ఫంక్షన్కు కాల్ చేయవచ్చు:
messaging:publish_message(Exchange, Key, Message).
ఎక్స్చేంజ్ - మార్పిడి పాయింట్ పేరు,
కీ - రూటింగ్ కీ
సందేశం - పేలోడ్
విలోమ ప్రచురణ-చందా
పబ్-సబ్ని విస్తరించడం ద్వారా, మీరు లాగింగ్ కోసం అనుకూలమైన నమూనాను పొందవచ్చు. మూలాలు మరియు వినియోగదారుల సమితి పూర్తిగా భిన్నంగా ఉండవచ్చు. ఫిగర్ ఒక వినియోగదారు మరియు బహుళ మూలాధారాలతో ఒక కేసును చూపుతుంది.
విధి పంపిణీ నమూనా
దాదాపు ప్రతి ప్రాజెక్ట్లో రిపోర్ట్లను రూపొందించడం, నోటిఫికేషన్లను అందించడం మరియు థర్డ్-పార్టీ సిస్టమ్ల నుండి డేటాను తిరిగి పొందడం వంటి వాయిదా వేసిన ప్రాసెసింగ్ టాస్క్లు ఉంటాయి. హ్యాండ్లర్లను జోడించడం ద్వారా ఈ విధులను నిర్వహిస్తున్న సిస్టమ్ యొక్క నిర్గమాంశను సులభంగా కొలవవచ్చు. ప్రాసెసర్ల సమూహాన్ని ఏర్పరచడం మరియు వాటి మధ్య పనులను సమానంగా పంపిణీ చేయడం మాత్రమే మాకు మిగిలి ఉంది.
3 హ్యాండ్లర్ల ఉదాహరణను ఉపయోగించి ఉత్పన్నమయ్యే పరిస్థితులను చూద్దాం. పని పంపిణీ దశలో కూడా, పంపిణీ యొక్క న్యాయత మరియు హ్యాండ్లర్ల ఓవర్ఫ్లో ప్రశ్న తలెత్తుతుంది. రౌండ్-రాబిన్ పంపిణీ న్యాయానికి బాధ్యత వహిస్తుంది మరియు హ్యాండ్లర్ల పొంగిపొర్లడాన్ని నివారించడానికి, మేము పరిమితిని ప్రవేశపెడతాము prefetch_limit. తాత్కాలిక పరిస్థితుల్లో prefetch_limit ఒక హ్యాండ్లర్ అన్ని టాస్క్లను స్వీకరించకుండా నిరోధిస్తుంది.
మెసేజింగ్ క్యూలు మరియు ప్రాసెసింగ్ ప్రాధాన్యతను నిర్వహిస్తుంది. ప్రాసెసర్లు టాస్క్లు వచ్చినప్పుడు వాటిని స్వీకరిస్తాయి. పని విజయవంతంగా పూర్తి కావచ్చు లేదా విఫలం కావచ్చు:
messaging:ack(Tack)
- సందేశం విజయవంతంగా ప్రాసెస్ చేయబడితే కాల్ చేయబడుతుందిmessaging:nack(Tack)
- అన్ని అత్యవసర పరిస్థితుల్లో పిలుస్తారు. టాస్క్ తిరిగి వచ్చిన తర్వాత, సందేశం దానిని మరొక హ్యాండ్లర్కు పంపుతుంది.
మూడు టాస్క్లను ప్రాసెస్ చేస్తున్నప్పుడు సంక్లిష్ట వైఫల్యం సంభవించిందని అనుకుందాం: ప్రాసెసర్ 1, టాస్క్ను స్వీకరించిన తర్వాత, ఎక్స్ఛేంజ్ పాయింట్కి ఏదైనా నివేదించడానికి సమయం లేకుండా క్రాష్ అయింది. ఈ సందర్భంలో, మార్పిడి పాయింట్ గడువు ముగిసిన తర్వాత టాస్క్ను మరొక హ్యాండ్లర్కు బదిలీ చేస్తుంది. కొన్ని కారణాల వల్ల, హ్యాండ్లర్ 3 టాస్క్ను విడిచిపెట్టి, నక్కి పంపాడు; ఫలితంగా, ఆ పనిని విజయవంతంగా పూర్తి చేసిన మరొక హ్యాండ్లర్కు కూడా బదిలీ చేయబడింది.
ప్రాథమిక సారాంశం
మేము పంపిణీ చేయబడిన సిస్టమ్ల యొక్క ప్రాథమిక బిల్డింగ్ బ్లాక్లను కవర్ చేసాము మరియు ఎర్లాంగ్/ఎలిక్సిర్లో వాటి ఉపయోగం గురించి ప్రాథమిక అవగాహనను పొందాము.
ప్రాథమిక నమూనాలను కలపడం ద్వారా, ఉద్భవిస్తున్న సమస్యలను పరిష్కరించడానికి మీరు సంక్లిష్ట నమూనాలను రూపొందించవచ్చు.
సిరీస్ యొక్క చివరి భాగంలో, మేము సేవలను నిర్వహించడం, రూటింగ్ మరియు బ్యాలెన్సింగ్ యొక్క సాధారణ సమస్యలను పరిశీలిస్తాము మరియు సిస్టమ్ల స్కేలబిలిటీ మరియు తప్పు సహనం యొక్క ఆచరణాత్మక వైపు గురించి కూడా మాట్లాడుతాము.
రెండవ భాగం ముగింపు.
ఫోటో
websequencediagrams.com ఉపయోగించి దృష్టాంతాలు సిద్ధం చేయబడ్డాయి
మూలం: www.habr.com