Funkció zászlók tavasszal

1. Áttekintés

Ebben a cikkben röviden meghatározzuk a funkciók jelzőit, és javaslatot teszünk egy megfontolt és pragmatikus megközelítésre, hogy ezeket a Spring Boot alkalmazásokban megvalósítsuk. Ezután kifinomultabb iterációkba fogunk ásni, kihasználva a Spring Boot különböző funkcióit.

Megbeszéljük a különböző forgatókönyveket, amelyek funkciók megjelölését igényelhetik, és beszélünk a lehetséges megoldásokról. Ezt egy Bitcoin Miner példaalkalmazással fogjuk megtenni.

2. Feature Flags

A Feature Flags - néha funkcióváltásnak nevezzük - olyan mechanizmus, amely lehetővé teszi számunkra, hogy engedélyezzük vagy letiltsuk alkalmazásunk bizonyos funkcióit anélkül, hogy módosítanunk kellene a kódot, vagy ideális esetben az alkalmazást újra kell telepítenünk.

Az adott jellemzőjelző által igényelt dinamikától függően szükség lehet globális, alkalmazás-példányonkénti vagy részletesebb - esetleg felhasználó vagy kérés - konfigurálására.

Mint a szoftvertervezés számos helyzetében, itt is fontos megpróbálni a lehető legegyszerűbb megközelítést alkalmazni, amely felesleges bonyolultság nélkül kezeli a problémát.

A jellemző zászlók hatékony eszköz, amely okos használatával megbízhatóságot és stabilitást kölcsönöz rendszerünknek. Viszont, ha visszaélnek velük vagy nem tartják fenn őket, gyorsan összetettség és fejfájás forrásaivá válhatnak.

Sok olyan forgatókönyv létezik, ahol a szolgáltatásjelzők jól jöhetnek:

Trunk-alapú fejlesztés és nem triviális funkciók

A csomagtér-alapú fejlesztésekben, különösen amikor folyamatosan szeretnénk folytatni az integrációt, előfordulhat, hogy nem vagyunk készek kiadni egy bizonyos funkciót. A funkciójelzők jól jöhetnek annak lehetővé tétele érdekében, hogy folyamatosan kiadhassuk, anélkül, hogy a változtatásokat a befejezésig elérhetővé tennénk.

Környezet-specifikus konfiguráció

Előfordulhat, hogy bizonyos funkciókra van szükségünk a DB visszaállításához egy E2E tesztelési környezethez.

Alternatív megoldásként előfordulhat, hogy a nem gyártási környezetekhez más biztonsági konfigurációt kell használnunk, mint a gyártási környezetben.

Ezért kihasználhatnánk a funkciók jelzőit, hogy a megfelelő beállításokat a megfelelő környezetben váltsuk át.

A / B tesztelés

Több megoldás kiadása ugyanarra a problémára és a hatás mérése olyan meggyőző technika, amelyet megvalósíthatnánk a jellemző zászlók használatával.

Kanári felszabadítás

Új funkciók telepítésekor dönthetünk úgy, hogy ezt fokozatosan fogjuk megtenni, kezdve a felhasználók egy kis csoportjával, és kiterjesztve az elfogadását, miközben igazoljuk a viselkedés helyességét. A jellemző zászlók lehetővé teszik ennek elérését.

A következő szakaszokban megpróbálunk gyakorlati megközelítést nyújtani a fent említett forgatókönyvek kezeléséhez.

Bontjunk le különféle stratégiákat a megjelölés jellemzésére, kezdve a legegyszerűbb forgatókönyvvel, hogy aztán áttérjünk egy részletesebb és összetettebb beállításra.

3. Alkalmazásszintű jellemzők

Ha az első két felhasználási eset bármelyikével foglalkoznunk kell, akkor az alkalmazásszintű funkciók jelzői a dolgok működésének egyszerű módját jelentik.

Egy egyszerű szolgáltatásjelző általában tartalmaz egy tulajdonságot és bizonyos konfigurációt az adott tulajdonság értéke alapján.

3.1. Funkciós zászlók tavaszi profilok használatával

Tavasszal kihasználhatjuk a profilokat. Kényelmesen a profilok lehetővé teszik bizonyos babok szelektív konfigurálását. Néhány körülöttük lévő konstrukcióval gyorsan létrehozhatunk egy egyszerű és elegáns megoldást az alkalmazásszintű szolgáltatásjelzőkre.

Tegyük fel, hogy BitCoin bányászati ​​rendszert építünk. A szoftverünk már készül, és feladatunk egy kísérleti, továbbfejlesztett bányászati ​​algoritmus létrehozása.

Miénkben JavaConfig áttekinthetjük az összetevőket:

@Configuration public class ProfiledMiningConfig {@Bean @Profile ("! Experimental-bányász") public BitcoinMiner defaultMiner () {return new DefaultBitcoinMiner (); } @Bean @Profile ("kísérleti-bányász") nyilvános BitcoinMiner experimentalMiner () {return new ExperimentalBitcoinMiner (); }}

Azután, a korábbi konfigurációval egyszerűen be kell írnunk a profilunkat, hogy feliratkozhassunk új funkcióinkra. Rengeteg módja van az alkalmazásunk általában konfigurálásának és a profilok engedélyezésének. Hasonlóképpen vannak tesztelési segédprogramok is, amelyek megkönnyítik az életünket.

Amíg a rendszerünk elég egyszerű, ezután létrehozhatunk egy környezeti alapú konfigurációt, hogy meghatározzuk, mely funkciókat kell alkalmazni, és melyeket hagyjuk figyelmen kívül.

Képzeljük el, hogy van egy új felhasználói felületünk, amely táblák helyett kártyákon alapul, az előző kísérleti bányásszal együtt.

Szeretnénk mindkét funkciót engedélyezni az elfogadási környezetünkben (UAT). Hozhatnánk létre egy application-uat.yml fájl:

tavasz: profilok: include: kísérleti-bányász, ui-kártyák # További konfiguráció itt

Az előző fájl helyénél csak engedélyeznünk kell az UAT profilt az UAT környezetben, hogy megszerezzük a kívánt funkciókat.

Fontos megérteni, hogyan lehet kihasználni tavasz.profilok.beleértve. Összehasonlítva spring.profiles.active, az előbbi lehetővé teszi számunkra, hogy profilokat adjunk hozzá.

Esetünkben azt akarjuk uat profil tartalmaznia kell a kísérleti bányász és az ui-kártyákat is.

3.2. Feature Flags az egyéni tulajdonságok használatával

A profilok nagyszerű és egyszerű módszer a munka elvégzésére. Előfordulhat, hogy más célokra is szükségünk lesz a profilokra. Vagy talán érdemes lehet egy strukturáltabb jellemzőkkel rendelkező infrastruktúra kiépítését.

Ezen esetekben az egyéni tulajdonságok lehetnek kívánatos lehetőségek.

Írjuk át kihasználva az előző példánkat @ConditionalOnProperty és a névterünk:

@Configuration public class CustomPropsMiningConfig {@Bean @ConditionalOnProperty (name = "features.miner.experimental", matchIfMissing = true) public BitcoinMiner defaultMiner () {return new DefaultBitcoinMiner (); } @Bean @ConditionalOnProperty (name = "features.miner.experimental") public BitcoinMiner experimentalMiner () {return new ExperimentalBitcoinMiner (); }}

Az előző példa a Spring Boot feltételes konfigurációjára épít és konfigurálja az egyik vagy másik összetevőt, attól függően, hogy a tulajdonság értéke igaz vagy hamis (vagy teljesen elhagyják).

Az eredmény nagyon hasonlít a 3.1-esre, de most megvan a névterünk. A névtér birtokában értelmes YAML / tulajdonság fájlokat hozhatunk létre:

# [...] Néhány tavaszi konfigurációs jellemző: miner: experimental: true ui: cards: true # [...] Egyéb jellemzők

Ez az új beállítás lehetővé teszi számunkra a jellemző zászlók előtagozását - esetünkben a jellemzők előtag.

Apró részletnek tűnhet, de ahogy növekszik alkalmazásunk és bonyolultabbá válik, ez az egyszerű iteráció segít abban, hogy a funkció zászlainkat ellenőrzés alatt tartsuk.

Beszéljünk ennek a megközelítésnek más előnyeiről.

3.3. A @ használataConfigurationProperties

Amint megkapjuk az előtagolt tulajdonságkészletet, létrehozhatunk egy POJO-t, amelyet @ConfigurationProperties díszít, hogy programozási kezelést kapjunk a kódunkban.

Folyamatos példánkat követve:

@Component @ConfigurationProperties (prefix = "features") public class ConfigProperties {private MinerProperties miner; privát UIProperties ui; // szabványos mérőeszközök és beállítók nyilvános statikus osztály MinerProperties {privát logikai kísérlet; // standard getterek és beállítók} public static class UIProperties {private boolean cards; // szokásos mérőeszközök és beállítók}}

Azáltal, hogy a jellemző zászlók állapotát egy összetartó egységbe helyezzük, új lehetőségeket nyitunk meg, lehetővé téve számunkra, hogy ezeket az információkat könnyen kitegyük a rendszerünk más részeire, például a felhasználói felületre, vagy a downstream rendszerek felé.

3.4. A szolgáltatás konfigurációjának bemutatása

A Bitcoin bányászati ​​rendszerünk egy felhasználói felület frissítést kapott, amely még nem teljesen kész. Ezért úgy döntöttünk, hogy megjelöljük. Előfordulhat, hogy egyoldalas alkalmazásunk van a React, Angular vagy Vue használatával.

A technológiától függetlenül tudnunk kell, hogy milyen funkciók vannak engedélyezve, hogy ennek megfelelően tudjuk megjeleníteni az oldalunkat.

Hozzunk létre egy egyszerű végpontot a konfigurációnk kiszolgálására, hogy felhasználói felületünk szükség esetén lekérdezhesse a háttérprogramot:

@RestController public class FeaturesConfigController {private ConfigProperties tulajdonságok; // konstruktor @GetMapping ("/ feature-flags") public ConfigProperties getProperties () {return tulajdonságok; }}

Kifinomultabb módon lehet kiszolgálni ezeket az információkat, például létrehozni egyéni működtető végpontokat. De ennek az útmutatónak a kedvéért a vezérlő végpontja elég jó megoldásnak érzi magát.

3.5. A tábor tisztán tartása

Bár nyilvánvalóan hangozhat, amint átgondoltan megvalósítottuk a funkciós zászlóinkat, ugyanolyan fontos, hogy fegyelmezetten megőrizzük a megszabadulást, ha már nincs rá szükség.

Az első használatra vonatkozó jellemzők - csomagtér-alapú fejlesztés és nem triviális jellemzők - általában rövid életűek. Ez azt jelenti, hogy meg kell győződnünk arról, hogy a mi ConfigProperties, a Java konfigurációnk és a YAML a fájlok tiszták és naprakészek maradnak.

4. Több szemcsés tulajdonságú zászló

Néha összetettebb forgatókönyvekbe kerülünk. Az A / B teszteléshez vagy a kanári kibocsátásokhoz a korábbi megközelítésünk egyszerűen nem elég.

A funkciók megjelöléseinek részletesebb megszerzéséhez szükség lehet a megoldásunk létrehozására. Ez magában foglalhatja felhasználói entitásunk testreszabását a jellemzőspecifikus információk beillesztésével, vagy esetleg kibővítheti webes keretrendszerünket.

Lehetséges, hogy felhasználóink ​​szennyezése jellemző zászlókkal nem mindenki számára vonzó ötlet, és vannak más megoldások is.

Alternatívaként kihasználhatnánk néhány beépített eszközt, például a Togglz-t. Ez az eszköz ad némi bonyolultságot, de szép, out-of-the-box megoldást kínál, és első osztályú integrációt biztosít a Spring Boot-tal.

A Togglz különböző aktiválási stratégiákat támogat:

  1. Felhasználónév: Meghatározott felhasználókhoz társított megjelölések
  2. Fokozatos bevezetés: Jelölések engedélyezve vannak a felhasználói bázis százalékában. Ez akkor hasznos például a Kanári-szigeteki kiadásoknál, amikor érvényesíteni szeretnénk a funkcióink viselkedését
  3. Kiadási dátum: Ütemezhetjük, hogy egy bizonyos időpontban engedélyezzük a zászlók engedélyezését. Ez hasznos lehet termékbemutató, összehangolt kiadás, illetve ajánlatok és kedvezmények esetén
  4. Kliens IP: Jelölt szolgáltatások az ügyfelek IP-címei alapján. Ezek jól jöhetnek, ha az adott konfigurációt meghatározott ügyfeleknek alkalmazzák, mivel statikus IP-vel rendelkeznek
  5. Szerver IP: Ebben az esetben a kiszolgáló IP-jét használják annak meghatározására, hogy engedélyezni kell-e egy funkciót. Ez hasznos lehet a kanári kiadások esetében is, kissé eltérő megközelítéssel, mint a fokozatos bevezetés - például amikor a teljesítményhatásokat szeretnénk felmérni az eseteinkben
  6. ScriptEngine: Engedélyezhetjük a funkciók megjelölését tetszőleges szkriptek alapján. Ez vitathatatlanul a legrugalmasabb lehetőség
  7. Rendszer tulajdonságai: Beállíthatunk bizonyos rendszer tulajdonságokat a jellemző jelző állapotának meghatározásához. Ez meglehetősen hasonlít ahhoz, amit a legegyenesebb megközelítéssel elértünk

5. Összefoglalás

Ebben a cikkben volt alkalmunk beszélni a jellemző zászlókról. Ezenkívül megvitattuk, hogy a Spring miként segíthet elérni e funkciók egy részét új könyvtárak hozzáadása nélkül.

Azzal kezdtük, hogy meghatároztuk, hogyan segíthet ez a minta néhány gyakori használati esetben.

Ezután néhány egyszerű megoldást építettünk a Spring and Spring Boot dobozon kívüli eszközökkel. Ezzel előálltunk egy egyszerű, ám mégis erőteljes szolgáltatás-megjelölő konstrukcióval.

Alul összehasonlítottunk pár alternatívát. Áttérés az egyszerűbb és kevésbé rugalmas megoldásról egy kifinomultabb, bár összetettebb mintára.

Végül röviden bemutattunk néhány irányelvet a robusztusabb megoldások felépítéséhez. Ez akkor hasznos, ha nagyobb fokú részletességre van szükségünk.


$config[zx-auto] not found$config[zx-overlay] not found