Mikroteenused, mis suhtlevad Axoni kaudu

Selles lihtsas juhendis loome paar mikroteenust Spring Bootiga ja korraldame nendevahelise suhtluse Axoni raamistikuga.

Mikroteenused, mis suhtlevad Axoni kaudu


Oletame, et meil on selline ĂŒlesanne.

On olemas tehingute allikas aktsiaturul. See allikas edastab meile tehingud REST-liidese kaudu.

Me peame need tehingud kÀtte saama, salvestama andmebaasi ja looma mugava mÀlu salvestuse.

See salvestus peab tÀitma jÀrgmisi funktsioone:

  • tagastama tehingute nimekirja;
  • tagastama tĂ€ieliku positsiooni, st tabeli „instrument” — „kehtiv aktsiate arv”;
  • tagastama positsiooni mÀÀratud instrumendi kohta.

Kuidas me selle ĂŒlesande lahendamisele lĂ€heneme?

Mikroteenuste trendide kohaselt peame ĂŒlesande jagama mikroteenusteks:

  • tehingute saamine REST-i kaudu;
  • tehingute salvestamine andmebaasi;
  • mĂ€lu salvestus andmete esitamiseks positsiooni kohta.

Teeme selle juhendi raames esimesed ja kolmanda teenuse, teise jÀtame teise osa jaoks (kirjutage kommentaaridesse, kui see on huvitav).

Nii et meil on kaks mikroteenust.

Esimene saab andmeid vÀljastpoolt.

Teine töötleb neid andmeid ja vastab sissetulevatele pÀringutele.

Me tÔepoolest soovime horisontaalset skaleerimist, katkematut uuendamist ja teisi mikroteenuste eeliseid.

Milline, ĂŒsna keeruline, ĂŒlesanne meie ees seisab?

Tegelikult on neid palju, aga rÀÀgime praegu, kuidas andmed nende mikroteenuste vahel liiguvad. Nende vahel saab samuti teha Rest-i, kasutada mingit jÀrjekorda, leiutada palju asju, millel on omad plussid ja miinused.

Vaatame ĂŒht vĂ”imalikku lĂ€henemist – asĂŒnkroonset suhtlemist kaudu Axon-raamistiku.

Millised on sellise lahenduse eelised?

Esiteks, asĂŒnkroonse suhtlemisega suureneb paindlikkus (jah, siin on ka miinus, aga rÀÀgime praegu ainult plussidest).

Teiseks, saame otse vÀlja pakutud lahenduse. Event Sourcing ja CQRS.
Kolmandaks, Axon pakub valmis infrastruktuuri, ja meie peame keskenduma ainult Àriloogika arendamisele.

Alustame.

Meie projekt pÔhineb gradle-l. See sisaldab kolme moodulit:

  • common. moodul, kus on ĂŒhised andmestruktuurid (me ei armasta kopeerimist);
  • tradeCreator. moodul mikroteenusega tehingute vastuvĂ”tmiseks Rest-i kaudu;
  • tradeQueries. moodul mikroteenusega positsiooni kuvamiseks.

VĂ”tame Spring Booti aluseks ja ĂŒhendame Axon starter-i.

Axon töötab vÀga hÀsti ka ilma Springita, kuid me kasutame neid koos.

Siin tasub peatuda ja paar sÔna Axonist rÀÀkida.

See on kliendiserveri sĂŒsteem. On server – see on eraldi rakendus, mille kĂ€ivitame Dockeris.

Ja on kliendid, mis integreeruvad mikroteenustesse.
Saame sellise pildi. Esiteks kÀivitatakse Axon-server (Dockeris), seejÀrel meie mikroteenused.

Mikroteenused otsivad serverit ja hakkavad temaga suhtlema. Suhtlemine jaguneb tinglikult kaheks: tehniliseks ja Àriliseks.

Tehniline – see on teadevahetus, et "ma olen elus" (selliseid teateid vĂ”ib nĂ€ha debug-logimise reĆŸiimis).

Äriline – see on teadevahetus, kus on midagi nagu "uus tehing".

Oluline omadus on see, et pĂ€rast kĂ€ivitamist vĂ”ib mikroteenus kĂŒsida Axon-serverilt "mida juhtus" ja server edastab mikroteenusele kogunenud sĂŒndmused. Nii vĂ”ib mikroteenust suhteliselt ohutult taaskĂ€ivitada ilma andmete kaotuseta.
Sellise vahetusskeemi korral saame vÀga lihtsalt kÀivitada palju mikroteenuste eksemplare,
ja isegi erinevates hostides.

Jah, ĂŒks eksemplar Axon-serverist – see pole usaldusvÀÀrne, aga praegu on see nii.

Me töötame Event Sourcing ja CQRS paradigmas. See tĂ€hendab, et meil peavad olema „kĂ€sklused”, „sĂŒndmused” ja „valimised”.

Meil on ĂŒks kĂ€sklus: „luua tehing”, ĂŒks sĂŒndmus „tehing loodud” ja kolm valikut: „nĂ€ita kĂ”iki tehinguid”, „nĂ€ita positsiooni”, „nĂ€ita positsiooni instrumendi jĂ€rgi”.

Töö skeem on jÀrgmine:

  1. Mikroteenus tradeCreator vastutab tehingu vastuvÔtmise eest Rest'i kaudu.
  2. Mikroteenus tradeCreator loob kĂ€su „luua tehing” ja saadab selle Axon-serverisse.
  3. Axon-server aktsepteerib kÀsku ja edastab selle huvitatud vastuvÔtjale, meie puhul mikroteenusele tradeCreator.
  4. Mikroteenus tradeCreator saab kĂ€su, loob sĂŒndmuse „tehing loodud” ja saadab selle Axon-serverisse.
  5. Axon-server aktsepteerib sĂŒndmuse ja edastab selle ettevaatlikult huvitatud tellijatele.
  6. Praegu on meil ainult ĂŒks huvitatud vastuvĂ”tja – mikroteenus tradeQueries.
  7. Mikroteenus tradeQueries saab sĂŒndmuse ja vĂ€rskendab sisemisi andmeid.

(Oluline on, et sĂŒndmuse loomise hetkel vĂ”ib mikroteenus tradeQueries olla mitteaktiivne, kuid kui see kĂ€ivitatakse, saab ta koheselt sĂŒndmuse).

Jah, axon-server seisab suhtluse keskmes, kÔik sÔnumid liiguvad lÀbi selle.

Liigume koodimise juurde.

Kuna postitust ei ole mÔtet koormata koodiga, toon allpool vaid osad, lingi tÀismahud on allpool.

Alustame ĂŒldmoduuliga common.

Selles on ĂŒhised osad – sĂŒndmus (class CreatedTradeEvent). Pange tĂ€hele, et nimetus on tegelikult selle meeskonna nimi, mis pĂ”hjustas selle sĂŒndmuse, kuid minevikus. Minevikus, kuna alguses esineb meeskond, mis viib sĂŒndmuse loomisele.

Teiste ĂŒldiste struktuuride hulka kuuluvad klassid positsiooni (class Position), tehingu (class Trade) ja tehingu pool (enum Side) kirjeldamiseks, st ost vĂ”i mĂŒĂŒk.

Liigume mooduli tradeCreator juurde.

Sellel moodulil on Rest-liides (class TradeController) tehingute vastuvÔtmiseks.
Saadud tehingust moodustatakse kÀsk 'looge tehing' ja saadetakse axon-serverisse.

    @PostMapping("/trade")
    public ResponseEntity create(@RequestBody Trade trade) {
        var createTradeCommand = CreateTradeCommand.builder()
                .tradeId(trade.getTradeId())
	...
                .build();
        var result = commandGateway.sendAndWait(createTradeCommand, 3, TimeUnit.SECONDS);
        return ResponseEntity.ok(result.get().toString());
    }

KÀsu töötlemiseks kasutatakse klassi class TradeAggregate.
Kuna Axon peab seda leidma, paneme annotatsiooni @Aggregate.
KĂ€skude töötlemise meetod nĂ€eb vĂ€lja selline (lĂŒhendatult):

    @CommandHandler
    public TradeAggregate(CreateTradeCommand command) {
        log.info("kÀsk: {}", command);
        var event = CreatedTradeEvent.builder()
                .tradeId(command.tradeId())
                ....
                .build();
        AggregateLifecycle.apply(event);
    }

KĂ€sust moodustatakse sĂŒndmus ja saadetakse serverisse.
KĂ€sk asub klassis CreateTradeCommand.

NĂŒĂŒd vaatame viimasest moodulist tradeQueries.

Valikud on kirjeldatud paketis queries.
Selles moodulis on samuti Rest-liides.
public class TradeController.

NÀitena vaatame pÀringu töötlemist: "nÀita kÔiki tehinguid."

    @GetMapping("/trade/all")
    public List findAllTrades() {
        return queryGateway.query(new FindAllTradesQuery(),
                ResponseTypes.multipleInstancesOf(Trade.class)).join();
    }

KÀiakse pÀring ja saadetakse serverisse.

PÀringu töötlemiseks kasutatakse klassi TradesEventHandler.
Seal on meetod, millele on lisatud annotatsioon.

   @QueryHandler
    public List handleFindCurrentPositionQuery(FindCurrentPositionQuery query)

Just tema vastutab andmete valimise eest in-memory salvestusest.

KĂŒsimus on, kuidas selles salvestuses teave uuendatakse.

Alustame faktist, et see on lihtsalt komplekt ConcurrentHashMap'e, mis on kohandatud konkreetsete valikute jaoks.
Nende vÀrskendamiseks rakendatakse meetodit:

    @EventHandler
    public void on(CreatedTradeEvent event) {
        log.info("event:{}", event);

        var trade = Trade.builder()
	...
                .build();
        trades.put(event.tradeId(), trade);
        position.merge(event.shortName(), event.size(),
                (oldValue, value) -> event.side() == Side.BUY ? oldValue + value : oldValue - value);
    }

Ta aktsepteerib sĂŒndmust 'tehing loodud' ja uuendab kaarte.

Need on mikroteenuste arenduse pÔhijooned.

Mida saab öelda Axoni puuduste kohta?

Esiteks, see keerustab infrastruktuuri, tekib tĂ”rke koht – Axon-server, kĂ”ik suhtlused kĂ€ivad lĂ€bi selle.

Teiseks, ilmneb selgelt sarnaste jaotatud sĂŒsteemide puudujÀÀk – andmete ajutine jĂ€rjepidevus. Meie puhul vĂ”ib uue tehingu saamise ja andmete uuendamise vahel minna lubamatult palju aega.

Mis jÀi varju?

Ei ole midagi öeldud Event Sourcingi ja CQRS-i kohta, mis need on ja milleks neid vajatakse.
Ilma nende mÔistete selgitamiseta vÔivad mÔned punktid jÀÀda arusaamatuks.

VÔib-olla vajavad ka mÔned koodifragmentid selgitamist.

Sellest rÀÀgime avatud veebinaril 21. septembril.

TÀielik nÀide.

Allikas: habr.com

Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster