Orphan services: de keerzijde van (micro)servicearchitectuur

Directeur Operaties van het Banki.ru-portaal Andrey Nikolsky sprak vorig jaar op de conferentie DevOpsDays Moskou over verweesde diensten: hoe identificeer je een wees in de infrastructuur, waarom verweesde diensten slecht zijn, wat je ermee moet doen en wat je moet doen als niets helpt.

Onder de uitsnede vindt u een tekstversie van het rapport.


Hallo collega's! Mijn naam is Andrey, ik leid de activiteiten bij Banki.ru.

We hebben grote diensten, dit zijn zulke monolithische diensten, er zijn diensten in een meer klassieke zin, en er zijn hele kleine. In mijn arbeiders-boerenterminologie zeg ik: als een dienst eenvoudig en klein is, dan is het micro, en als het niet heel eenvoudig en klein is, dan is het gewoon een dienst.

Voordelen van diensten

Ik zal snel de voordelen van de diensten bespreken.

Orphan services: de keerzijde van (micro)servicearchitectuur

De eerste is schaalvergroting. Je kunt snel iets aan de service doen en de productie starten. Je hebt verkeer ontvangen, je hebt de dienst gekloond. Je hebt meer verkeer, je hebt het gekloond en leeft ermee. Dit is een goede bonus, en toen we begonnen, werd het in principe als het belangrijkste voor ons beschouwd: waarom we dit allemaal doen.

Orphan services: de keerzijde van (micro)servicearchitectuur

Ten tweede, geïsoleerde ontwikkeling, waarbij je meerdere ontwikkelteams hebt, met in elk team meerdere verschillende ontwikkelaars, en elk team zijn eigen dienst ontwikkelt.

Bij teams is er een nuance. Ontwikkelaars zijn anders. En er zijn bijv. sneeuwvlok mensen. Ik zag dit voor het eerst bij Maxim Dorofeev. Soms zitten sneeuwvlokmensen in sommige teams en niet in andere. Dit maakt de verschillende diensten die binnen het bedrijf worden gebruikt een beetje ongelijk.

Orphan services: de keerzijde van (micro)servicearchitectuur

Kijk naar de foto: dit is een goede ontwikkelaar, hij heeft grote handen, hij kan veel. Het grootste probleem is waar deze handen vandaan komen.

Orphan services: de keerzijde van (micro)servicearchitectuur

Diensten maken het mogelijk om verschillende programmeertalen te gebruiken die geschikter zijn voor verschillende taken. Sommige diensten zijn in Go, sommige zijn in Erlang, sommige zijn in Ruby, iets is in PHP, iets is in Python. Over het algemeen kun je heel breed uitbreiden. Ook hier zijn er nuances.

Orphan services: de keerzijde van (micro)servicearchitectuur

Servicegerichte architectuur gaat vooral over devops. Dat wil zeggen: als je geen automatisering hebt, is er geen implementatieproces. Als je het handmatig configureert, kunnen je configuraties van service-instantie tot instantie veranderen, en moet je daarheen om iets te doen, dan zit je in de hel.

Je hebt bijvoorbeeld 20 services en moet deze handmatig implementeren, je hebt 20 consoles en je drukt tegelijkertijd op "enter" als een ninja. Het is niet erg goed.

Als je na het testen een service hebt (als er getest wordt natuurlijk), en je moet deze nog afmaken met een bestand zodat het in productie werkt, dan heb ik ook slecht nieuws voor je.

Als je afhankelijk bent van specifieke Amazon-diensten en in Rusland werkt, dan had je twee maanden geleden ook: “Alles rondom staat in brand, met mij gaat het goed, alles is cool.”

Orphan services: de keerzijde van (micro)servicearchitectuur

We gebruiken Ansible om de implementatie te automatiseren, Puppet voor convergentie, Bamboo om de implementatie te automatiseren en Confluence om het allemaal op de een of andere manier te beschrijven.

Ik zal hier niet in detail op ingaan, omdat het rapport meer over interactiepraktijken gaat, en niet over de technische implementatie.

Orphan services: de keerzijde van (micro)servicearchitectuur

We hebben bijvoorbeeld problemen gehad waarbij Puppet op de server met Ruby 2 werkte, maar sommige applicaties zijn geschreven voor Ruby 1.8 en deze werken niet samen. Daar gaat iets mis. En als je meerdere versies van Ruby op één machine moet draaien, krijg je meestal problemen.

We geven elke ontwikkelaar bijvoorbeeld een platform waarop ongeveer alles staat wat we hebben, alle diensten die ontwikkeld kunnen worden, zodat hij een geïsoleerde omgeving heeft, die hij kan afbreken en bouwen zoals hij wil.

Het komt voor dat je een speciaal samengesteld pakket nodig hebt met ondersteuning voor iets daar. Het is behoorlijk zwaar. Ik heb naar een rapport geluisterd waarin de Docker-image 45 GB weegt. In Linux is het natuurlijk eenvoudiger, daar is alles kleiner, maar toch zal er niet genoeg ruimte zijn.

Welnu, er zijn tegenstrijdige afhankelijkheden: wanneer een deel van het project afhankelijk is van een bibliotheek van de ene versie, hangt een ander deel van het project af van een andere versie, en de bibliotheken zijn helemaal niet samen geïnstalleerd.

Orphan services: de keerzijde van (micro)servicearchitectuur

We hebben sites en services in PHP 5.6, we schamen ons ervoor, maar wat kunnen we doen? Dit is onze enige site. Er zijn sites en diensten op PHP 7, er zijn er meer, we schamen ons er niet voor. En elke ontwikkelaar heeft zijn eigen basis waar hij met plezier mee zaagt.

Als je in een bedrijf in één taal schrijft, dan klinken drie virtuele machines per ontwikkelaar normaal. Als je verschillende programmeertalen hebt, wordt de situatie erger.

Orphan services: de keerzijde van (micro)servicearchitectuur

Je hebt sites en services hierop, hierop, dan nog een site voor Go, een site voor Ruby en nog een andere Redis ernaast. Als gevolg hiervan verandert dit alles in een groot veld voor ondersteuning, en de hele tijd kan een deel ervan breken.

Orphan services: de keerzijde van (micro)servicearchitectuur

Daarom hebben we de voordelen van de programmeertaal vervangen door het gebruik van verschillende frameworks, aangezien PHP-frameworks behoorlijk verschillend zijn, ze verschillende mogelijkheden, verschillende communities en verschillende ondersteuning hebben. En je kunt een dienst schrijven zodat je er al iets voor klaar hebt liggen.

Elke dienst heeft zijn eigen team

Orphan services: de keerzijde van (micro)servicearchitectuur

Ons belangrijkste voordeel, dat zich in de loop der jaren heeft uitgekristalliseerd, is dat elke dienst zijn eigen team heeft. Dit is handig voor een groot project, u kunt tijd besparen op documentatie, managers kennen hun project goed.

U kunt eenvoudig taken indienen vanuit ondersteuning. Zo ging de verzekeringsdienst kapot. En onmiddellijk gaat het team dat zich met de verzekeringen bezighoudt, het repareren.

Er worden snel nieuwe features gecreëerd, want als je één atoomdienst hebt, kun je er snel iets in schroeven.

En als je je service verbreekt, en dit gebeurt onvermijdelijk, heb je geen invloed op de services van anderen, en komen ontwikkelaars van andere teams niet met stukjes naar je toe rennen en zeggen: "Ay-ay, doe dat niet."

Orphan services: de keerzijde van (micro)servicearchitectuur

Zoals altijd zijn er nuances. We hebben stabiele teams, managers zitten aan het team vastgenageld. Er zijn duidelijke documenten, managers houden alles nauwlettend in de gaten. Elk team met een manager beschikt over meerdere diensten en er is een specifiek competentiepunt.

Als de teams zweven (dit gebruiken we ook wel eens), is er een goede methode die de “sterrenkaart” wordt genoemd.

Orphan services: de keerzijde van (micro)servicearchitectuur

Je hebt een lijst met diensten en mensen. Een asterisk betekent dat de persoon een expert is in deze dienst, een boek betekent dat de persoon deze dienst bestudeert. De taak van de persoon is om het boekje te vervangen door een asterisk. En als er niets voor de dienst wordt geschreven, beginnen de problemen, waarover ik verder zal praten.

Hoe verschijnen weesdiensten?

Orphan services: de keerzijde van (micro)servicearchitectuur

Het eerste probleem, de eerste manier om een ​​weesdienst in uw infrastructuur te krijgen, is door mensen te ontslaan. Heeft iemand ooit een bedrijf de deadlines laten halen voordat de taken werden beoordeeld? Soms komt het voor dat de deadlines krap zijn en dat er simpelweg niet genoeg tijd is voor documentatie. “We moeten de service overdragen aan de productie, en dan voegen we deze toe.”

Als het team klein is, komt het voor dat er één ontwikkelaar is die alles schrijft, de rest staat in de coulissen. “Ik heb de basisarchitectuur geschreven, laten we de interfaces toevoegen.” Dan vertrekt op een gegeven moment bijvoorbeeld de manager. En gedurende deze periode, wanneer de manager is vertrokken en er nog geen nieuwe is aangesteld, beslissen de ontwikkelaars zelf waar de dienst naartoe gaat en wat daar gebeurt. En zoals we weten (laten we een paar dia's teruggaan), zijn er in sommige teams sneeuwvlokmensen, soms een sneeuwvlokteamleider. Dan stopt hij en krijgen we een weesopvang.

Orphan services: de keerzijde van (micro)servicearchitectuur

Tegelijkertijd verdwijnen taken vanuit de ondersteuning en vanuit het bedrijfsleven niet, maar komen ze in de achterstand terecht. Mochten er tijdens de ontwikkeling van de dienst architectuurfouten zijn gemaakt, dan komen deze ook in de backlog terecht. De service gaat langzaam achteruit.

Hoe herken je een wees?

Deze lijst beschrijft de situatie goed. Wie heeft iets geleerd over hun infrastructuur?

Orphan services: de keerzijde van (micro)servicearchitectuur

Over gedocumenteerde oplossingen: er is een service en over het algemeen werkt deze, er is een handleiding van twee pagina's over hoe ermee te werken, maar niemand weet hoe het binnenin werkt.

Of er is bijvoorbeeld een soort linkverkorter. Zo hebben we momenteel bijvoorbeeld drie linkverkorters in gebruik voor verschillende doeleinden in verschillende diensten. Dit zijn slechts de gevolgen.

Orphan services: de keerzijde van (micro)servicearchitectuur

Nu zal ik de kapitein zijn van het voor de hand liggende. Wat moet er gedaan worden? Eerst moeten we de service overdragen aan een andere manager, een ander team. Als uw teamleider nog niet is gestopt, moet u in dit andere team, als u begrijpt dat de dienst als een wees is, iemand opnemen die er op zijn minst iets van begrijpt.

Het belangrijkste: u moet de overdrachtsprocedures in bloed laten schrijven. In ons geval houd ik dit meestal in de gaten, omdat ik alles nodig heb om te werken. Managers hebben behoefte aan een snelle levering, en wat er later mee gebeurt, is voor hen niet meer zo belangrijk.

Orphan services: de keerzijde van (micro)servicearchitectuur

De volgende manier om een ​​weeskind te maken is: “We doen het uitbesteed, het gaat sneller, en dan dragen we het over aan het team.” Het is duidelijk dat iedereen een aantal plannen heeft in het team, een beurt. Vaak denkt een zakelijke klant dat de uitbesteder hetzelfde gaat doen als de technische afdeling die het bedrijf heeft. Hoewel hun motivatoren verschillend zijn. Er zijn vreemde technologische oplossingen en vreemde algoritmische oplossingen in outsourcing.

Orphan services: de keerzijde van (micro)servicearchitectuur

Zo hadden we bijvoorbeeld een dienst waarbij Sphinx op diverse onverwachte plekken stond. Ik vertel je later wat ik moest doen.

Uitbesteders hebben zelfgeschreven raamwerken. Dit is gewoon kale PHP met copy-paste van een vorig project, waar je van alles kunt vinden. Implementatiescripts zijn een groot nadeel als je een aantal complexe Bash-scripts moet gebruiken om verschillende regels in een bestand te wijzigen, en deze implementatiescripts worden aangeroepen door een derde script. Als gevolg hiervan verander je het implementatiesysteem, kies je iets anders, hop, maar je service werkt niet. Omdat het daar nodig was om nog 8 links tussen verschillende mappen te plaatsen. Of het gebeurt dat duizend records werken, maar honderdduizend niet meer werken.

Ik blijf kapitein. Het accepteren van een uitbestede dienst is een verplichte procedure. Heeft iemand ooit een uitbestede service meegemaakt die nergens werd geaccepteerd? Dit is natuurlijk niet zo populair als een weesservice, maar toch.

Orphan services: de keerzijde van (micro)servicearchitectuur

De dienst moet worden gecontroleerd, de dienst moet worden beoordeeld, wachtwoorden moeten worden gewijzigd. We hadden een geval toen ze ons een dienst verleenden, er is een beheerderspaneel “if login == 'admin' && wachtwoord == 'admin'...', het staat rechtstreeks in de code geschreven. We zitten en denken, en mensen schrijven dit in 2018?

Het testen van de opslagcapaciteit is ook een noodzakelijk iets. Je moet kijken naar wat er op honderdduizend platen gebeurt, nog voordat je deze dienst ergens in productie gaat nemen.

Orphan services: de keerzijde van (micro)servicearchitectuur

Het mag geen schande zijn om een ​​dienst ter verbetering te sturen. Als je zegt: "We accepteren deze dienst niet, we hebben twintig taken, doe ze, dan accepteren we", is dit normaal. Uw geweten mag niet gekwetst worden door het feit dat u een manager aan het aanstellen bent of dat het bedrijf geld verspilt. Het bedrijf zal dan meer uitgeven.

We hadden een geval toen we besloten een pilotproject uit te besteden.

Orphan services: de keerzijde van (micro)servicearchitectuur

Het werd op tijd geleverd en dit was het enige kwaliteitscriterium. Daarom hebben we nog een proefproject gemaakt, dat niet eens echt een pilot meer was. Deze diensten werden geaccepteerd en via administratieve middelen zeiden ze: hier is uw code, hier is het team, hier is uw manager. De diensten zijn feitelijk al begonnen winst te maken. Tegelijkertijd zijn ze in feite nog steeds wezen, niemand begrijpt hoe ze werken en managers doen hun best om hun taken te verloochenen.

Orphan services: de keerzijde van (micro)servicearchitectuur

Er is nog een geweldig concept: guerrilla-ontwikkeling. Wanneer een afdeling, meestal de marketingafdeling, een hypothese wil testen en de hele dienst uitbesteedt. Het verkeer begint er binnen te stromen, ze sluiten de documenten, ondertekenen documenten met de aannemer, treden in werking en zeggen: "Mannen, we hebben hier een dienst, er is al verkeer, het levert ons geld op, laten we het accepteren." We hadden zoiets van: 'Oppa, hoe kan dat nou zijn.'

Orphan services: de keerzijde van (micro)servicearchitectuur

En nog een manier om een ​​verweesde dienst te krijgen: wanneer een team plotseling beladen raakt, zegt het management: “Laten we de dienst van dit team overdragen aan een ander team, die heeft een kleinere last.” En dan dragen we het over aan een derde team en veranderen we van manager. En uiteindelijk hebben we weer een weesje.

Wat is het probleem met weeskinderen?

Orphan services: de keerzijde van (micro)servicearchitectuur

Wie weet het niet, dit is het slagschip Wasa dat in Zweden is opgegroeid en beroemd is vanwege het feit dat het 5 minuten na de lancering zonk. En de koning van Zweden heeft hiervoor trouwens niemand geëxecuteerd. Het werd gebouwd door twee generaties ingenieurs die niet wisten hoe ze dergelijke schepen moesten bouwen. Natuurlijk effect.

Het schip had overigens veel erger kunnen zinken, bijvoorbeeld toen de koning er ergens in een storm al op reed. En dus verdronk hij meteen, volgens Agile is het goed om vroeg te falen.

Als we vroegtijdig falen, zijn er meestal geen problemen. Tijdens de acceptatie is het bijvoorbeeld ter revisie verzonden. Maar als we al falen in de productie, wanneer er geld wordt geïnvesteerd, kunnen er problemen ontstaan. Gevolgen, zoals dat in het bedrijfsleven heet.

Waarom weesdiensten gevaarlijk zijn:

  • De service kan plotseling worden verbroken.
  • De service duurt lang om te repareren of wordt helemaal niet gerepareerd.
  • Veiligheidsproblemen.
  • Problemen met verbeteringen en updates.
  • Als een belangrijke dienst kapot gaat, heeft de reputatie van het bedrijf daaronder te lijden.

Wat te doen met weesdiensten?

Orphan services: de keerzijde van (micro)servicearchitectuur

Ik zal herhalen wat ik nog een keer moet doen. Ten eerste moet er documentatie zijn. 7 jaar bij Banki.ru heeft me geleerd dat testers niet het woord van de ontwikkelaars moeten geloven, en dat operations niet het woord van iedereen moeten geloven. We moeten het controleren.

Orphan services: de keerzijde van (micro)servicearchitectuur

Ten tweede is het noodzakelijk om interactiediagrammen te schrijven, omdat het voorkomt dat diensten die niet erg goed worden ontvangen afhankelijkheden bevatten waar niemand over heeft gesproken. De ontwikkelaars hebben de service bijvoorbeeld op hun sleutel voor sommige Yandex.Maps of Dadata geïnstalleerd. Je hebt geen vrije limiet meer, alles is kapot en je weet helemaal niet wat er is gebeurd. Al dergelijke harken moeten worden beschreven: de dienst maakt gebruik van Dadata, SMS, iets anders.

Orphan services: de keerzijde van (micro)servicearchitectuur

Ten derde: werken met technische schulden. Als je op een of andere manier met krukken loopt of een dienst accepteert en zegt dat er iets moet gebeuren, moet je ervoor zorgen dat het ook gebeurt. Want dan kan blijken dat het gaatje toch niet zo klein is, en val je er doorheen.

Bij architectonische opdrachten hadden we een verhaal over Sfinx. Eén van de diensten gebruikte Sphinx om lijsten in te voeren. Gewoon een gepagineerde lijst, maar deze werd elke nacht opnieuw geïndexeerd. Het was samengesteld uit twee indexen: elke nacht werd er één grote geïndexeerd, en er was ook een kleine index die eraan vastgeschroefd werd. Elke dag, met een kans van 50% op een bombardement of niet, crashte de index tijdens de berekening en werd ons nieuws niet meer bijgewerkt op de hoofdpagina. In eerste instantie duurde het 5 minuten voordat de index opnieuw werd geïndexeerd, daarna groeide de index en op een gegeven moment begon het 40 minuten te duren om opnieuw te indexeren. Toen we dit eruit haalden, slaakten we een zucht van verlichting, omdat het duidelijk was dat er nog wat tijd zou verstrijken en dat onze index fulltime opnieuw zou worden geïndexeerd. Dit wordt een mislukking voor ons portaal, er is acht uur lang geen nieuws - dat is alles, de zaken zijn gestopt.

Plan voor het werken met een weesdienst

Orphan services: de keerzijde van (micro)servicearchitectuur

In feite is dit heel moeilijk om te doen, omdat devops over communicatie gaat. U wilt op goede voet staan ​​met uw collega's, en als u uw collega's en managers over het hoofd slaat met regelgeving, kunnen zij tegenstrijdige gevoelens hebben tegenover de mensen die dit doen.

Naast al deze punten is er nog iets belangrijks: er moeten specifieke mensen verantwoordelijk zijn voor elke specifieke dienst, voor elk specifiek onderdeel van de inzetprocedure. Als er geen mensen zijn en je moet wat andere mensen aantrekken om deze hele kwestie te bestuderen, wordt het moeilijk.

Orphan services: de keerzijde van (micro)servicearchitectuur

Als dit allemaal niet heeft geholpen en uw weesdienst nog steeds een wees is, wil niemand het overnemen, is de documentatie niet geschreven, het team dat bij deze dienst is geroepen, weigert iets te doen, er is een eenvoudige manier om het opnieuw te doen alles.

Dat wil zeggen, je neemt de vereisten voor de dienst opnieuw en schrijft een nieuwe dienst, beter, op een beter platform, zonder vreemde technologische oplossingen. En je migreert ernaartoe in de strijd.

Orphan services: de keerzijde van (micro)servicearchitectuur

We hadden een situatie waarin we een dienst op Yii 1 namen en beseften dat we deze niet verder konden ontwikkelen, omdat we geen ontwikkelaars meer hadden die goed konden schrijven op Yii 1. Alle ontwikkelaars schrijven goed op Symfony XNUMX. Wat moeten we doen? We hebben tijd toegewezen, een team toegewezen, een manager toegewezen, het project herschreven en er soepel verkeer naartoe gestuurd.

Hierna kan de oude dienst verwijderd worden. Dit is mijn favoriete procedure, waarbij je wat service uit het configuratiebeheersysteem moet halen en opschonen en dan door moet gaan en zien dat alle auto's in productie zijn uitgeschakeld, zodat de ontwikkelaars geen sporen meer hebben. De repository blijft in Git.

Dit is alles waar ik over wilde praten, ik ben klaar om te bespreken, het onderwerp is holivar, velen hebben erin gezwommen.

Op de dia's stond dat jullie talen verenigden. Een voorbeeld hiervan was het vergroten/verkleinen van afbeeldingen. Is het echt nodig om het strikt tot één taal te beperken? Omdat het formaat van afbeeldingen in PHP eigenlijk in Golang zou kunnen worden gedaan.

In feite is het optioneel, zoals alle praktijken. Misschien is het in sommige gevallen zelfs ongewenst. Maar je moet begrijpen dat als je een technische afdeling hebt in een bedrijf met 50 mensen, 45 van hen PHP-specialisten zijn, nog eens 3 devops die Python, Ansible, Puppet en iets dergelijks kennen, en slechts één van hen schrijft in sommige soort taal, een of andere Go-service voor het wijzigen van de grootte van afbeeldingen, en als deze weggaat, gaat de expertise mee. En tegelijkertijd moet je op zoek gaan naar een marktspecifieke ontwikkelaar die deze taal kent, vooral als deze zeldzaam is. Vanuit organisatorisch oogpunt is dit dus problematisch. Vanuit het oogpunt van devops zul je niet alleen een kant-en-klare set playbooks moeten klonen die je gebruikt om services te implementeren, maar je zult ze helemaal opnieuw moeten schrijven.

We bouwen momenteel een dienst op Node.js, en dit zal slechts een platform in de buurt zijn voor elke ontwikkelaar met een aparte taal. Maar we zaten en dachten dat het spel de kaars waard was. Dat wil zeggen, dit is een vraag waar u over moet nadenken.

Hoe monitort u uw dienstverlening? Hoe verzamel en monitor je logs?

We verzamelen logs in Elasticsearch en plaatsen deze in Kibana, en afhankelijk van of het om productie- of testomgevingen gaat, worden daar verschillende verzamelaars gebruikt. Ergens Houthakker, ergens anders iets anders, ik weet het niet meer. En er zijn nog steeds enkele plaatsen in bepaalde diensten waar we Telegraf installeren en ergens anders afzonderlijk filmen.

Hoe kun je samenleven met Puppet en Ansible in dezelfde omgeving?

In feite hebben we nu twee omgevingen: de ene is Puppet en de andere is Ansible. We werken eraan om ze te hybridiseren. Ansible is een goed raamwerk voor de eerste installatie, Puppet is een slecht raamwerk voor de eerste installatie omdat het praktijkgericht werk rechtstreeks op het platform vereist, en Puppet zorgt voor configuratieconvergentie. Dit betekent dat het platform zichzelf in een up-to-date staat houdt, en om de geansibiliseerde machine up-to-date te houden, moet je er met enige regelmaat voortdurend playbooks op draaien. Dat is het verschil.

Hoe zorg je voor compatibiliteit? Heb je configuraties in zowel Ansible als Puppet?

Dit is onze grote pijn, we behouden de compatibiliteit met onze handen en denken na over hoe we hier nu ergens mee verder kunnen gaan. Het blijkt dat Puppet pakketten uitrolt en daar enkele links onderhoudt, en dat Ansible bijvoorbeeld de code uitrolt en daar de nieuwste applicatieconfiguraties aanpast.

De presentatie ging over verschillende versies van Ruby. Welke oplossing?

We zijn dit op één plek tegengekomen en we moeten het de hele tijd in ons hoofd houden. We hebben eenvoudigweg het gedeelte dat op de Ruby draaide en dat niet compatibel was met de applicaties, uitgeschakeld en gescheiden gehouden.

De conferentie van dit jaar DevOpsDays Moskou vindt plaats op 7 december in Technopolis. We accepteren aanvragen voor rapporten tot 11 november. schrijven ons als u wilt spreken.

De inschrijving voor deelnemers is geopend, doe mee!

Bron: www.habr.com

Voeg een reactie