Računanje bez poslužitelja s AWS Lambda, 1. dio

Računanje bez poslužitelja možda je najzanimljivija stvar u računalstvu u oblaku danas, ali što je zapravo? Ovaj dvodijelni vodič započinje pregledom računala bez poslužitelja - od onoga što ono jest, do razloga zašto se smatra ometajućim za tradicionalno računanje u oblaku i kako biste ga mogli koristiti u programiranju zasnovanom na Javi.

Nakon pregleda, dobit ćete praktični uvod u AWS Lambda, koji danas mnogi smatraju premijernim rješenjem za računare bez poslužitelja temeljenim na Javi. U prvom ćete dijelu koristiti AWS Lambda za izgradnju, postavljanje i testiranje prve Lambda funkcije na Javi. U 2. dijelu integrirat ćete svoju Lambda funkciju s DynamoDB, a zatim upotrijebiti AWS SDK za pozivanje Lambda funkcija u Java aplikaciji.

Što je računalo bez poslužitelja?

Prošle godine razgovarao sam s kompanijom pripravnicom o različitim arhitektonskim uzorcima i spomenutoj arhitekturi bez servera. Brzo je primijetio da sve aplikacije zahtijevaju poslužitelj i da ne mogu raditi na zraku. Pripravnik je imao smisao, čak i ako mu je nedostajala moja. Računanje bez poslužitelja nije čarobna platforma za pokretanje aplikacija.

Zapravo, računalo bez poslužitelja jednostavno znači da vi, programer, ne morate imati posla s poslužiteljem. Računalna platforma bez poslužitelja poput AWS Lambda omogućuje vam izradu koda i njegovo postavljanje bez potrebe za konfiguriranjem ili upravljanjem temeljnim poslužiteljima. Vaša jedinica implementacije je vaš kôd; ne spremnik koji hostira kôd ili poslužitelj koji ga pokreće, već jednostavno sam kôd. Sa stajališta produktivnosti, očite su prednosti preopterećenja detalja o tome gdje se kôd pohranjuje i kako se upravlja izvršnim okruženjem. Izračunavanje računala bez poslužitelja također se temelji na mjernim podacima izvršenja, tako da postoji i financijska prednost.

Što košta AWS Lambda?

U vrijeme pisanja ovog članka, cjenovni nivo AWS Lambde temelji se na broju izvršenja i trajanju izvršenja:

  • Vaših prvih milijun ovrha mjesečno je besplatno, a nakon toga plaćate 0,20 USD po milijunu ovrha (0,0000002 USD po zahtjevu).
  • Trajanje se izračunava od trenutka kada započinje izvršavanje vašeg koda dok ne vrati rezultat, zaokružen na najbližih 100 ms. Naplaćeni iznos temelji se na količini RAM-a dodijeljenoj funkciji, gdje je trošak 0,00001667 USD za svaku GB-sekundu.

Pojedinosti o cijenama i besplatna raspodjela slogova nešto su složenije nego što to pretpostavlja pregled. Posjetite cjenovni nivo da biste prošli kroz nekoliko scenarija određivanja cijena.

Da bismo dobili ideju o tome kako funkcionira računalo bez poslužitelja, krenimo s modelom izvršavanja računala bez poslužitelja, koji je prikazan na slici 1.

Steven Haines

Evo ukratko modela izvršenja bez poslužitelja:

  1. Klijent upućuje zahtjev računalnoj platformi bez poslužitelja za izvršenje određene funkcije.
  2. Računalna platforma bez poslužitelja prvo provjerava radi li funkcija na nekom od svojih poslužitelja. Ako se funkcija već ne izvodi, tada platforma učitava funkciju iz spremišta podataka.
  3. Platforma zatim raspoređuje funkciju na jedan od svojih poslužitelja koji su unaprijed konfigurirani s izvršnim okruženjem koje može pokretati funkciju.
  4. Izvršava funkciju i bilježi rezultat.
  5. Vraća rezultat natrag klijentu.

Ponekad se računalo bez poslužitelja naziva Funkcija kao usluga (FaaS), jer je granularnost koda koji gradite funkcija . Platforma izvršava vašu funkciju na vlastitom poslužitelju i organizira proces između zahtjeva za funkcijama i odgovora na funkcije.

Nanousluge, skalabilnost i cijena

Tri su stvari bitne za računalo bez poslužitelja: njegova nanoservisna arhitektura; činjenica da je praktički beskrajno skalabilan; i model cijena povezan s tom gotovo beskonačnom skalabilnošću. Istražit ćemo svaki od tih čimbenika.

Nanoservisi

Čuli ste za mikrousluge i vjerojatno znate za aplikacije od 12 faktora, ali funkcije bez poslužitelja uzimaju paradigmu razbijanja komponente na sastavne dijelove na potpuno novu razinu. Izraz "nanousluge" nije industrijski prepoznat pojam, ali ideja je jednostavna: svaka nanousluga treba provoditi jednu radnju ili odgovornost. Na primjer, ako želite stvoriti widget, čin stvaranja bio bi vlastiti nanoservis; ako želite pristupiti widgetu, čin dohvaćanja također bi bio nanousluga; a ako želite naručiti widget, ta bi narudžba bila još jedna nanousluga.

Arhitektura nanoservisa omogućuje vam definiranje vaše aplikacije na vrlo finoj razini. Slično razvoju temeljenom na testovima (koji vam pomaže da izbjegnete neželjene nuspojave pisanjem koda na razini pojedinačnih testova), arhitektura nanoservisa potiče definiranje vaše aplikacije u smislu vrlo sitnih i specifičnih funkcija. Ovaj pristup povećava jasnoću onoga što gradite i smanjuje neželjene nuspojave novog koda.

Mikroservisi vs nanoservisi

Microservices nas potiče da razbijemo aplikaciju na zbirku usluga koje svaka izvršavaju određeni zadatak. Izazov je u tome što nitko doista nije kvantificirao opseg mikrousluge. Kao rezultat, na kraju definiramo mikrousluge kao zbirku povezanih usluga, koje sve komuniciraju s istim podatkovnim modelom. Konceptualno, ako imate funkcionalnost niske razine u interakciji s danim podatkovnim modelom, tada bi funkcionalnost trebala ući u jednu od srodnih usluga. Interakcije na visokoj razini trebaju upućivati ​​pozive usluzi, a ne izravno postavljati upite u bazu podataka.

U toku je rasprava u poslužiteljima bez poslužitelja o tome treba li graditi Lambda funkcije na razini mikroservisa ili nanoservisa. Dobra vijest je da svoje funkcije možete prilično lako graditi na bilo kojoj granularnosti, ali strategija mikrousluga zahtijevat će malo dodatne logike usmjeravanja u vašem obrađivaču zahtjeva.

Iz perspektive dizajna, aplikacije bez poslužitelja trebale bi biti vrlo dobro definirane i čiste. Iz perspektive implementacije morat ćete upravljati znatno većim brojem implementacija, ali imat ćete i mogućnost pojedinačnog postavljanja novih verzija svojih funkcija, bez utjecaja na druge funkcije. Računanje bez poslužitelja posebno je pogodno za razvoj u velikim timovima, gdje može olakšati razvojni proces i kôd manje podložan pogreškama.

Skalabilnost

Uz uvođenje nove arhitektonske paradigme, računalne platforme bez poslužitelja pružaju praktički beskonačnu skalabilnost. Kažem "praktično", jer ne postoji nešto takvo uistinubeskonačna skalabilnost. U sve praktične svrhe, pružatelji računala bez poslužitelja poput Amazona mogu podnijeti više tereta nego što biste im mogli baciti. Ako biste upravljali skaliranjem vlastitih poslužitelja (ili virtualnih strojeva temeljenih na oblaku) kako biste zadovoljili povećanu potražnju, morat ćete nadgledati upotrebu, utvrditi kada pokrenuti više poslužitelja i dodati više poslužitelja u klaster u pravo vrijeme. Isto tako, kad se potražnja smanjila, morat ćete ručno smanjiti. S računalom bez poslužitelja svojoj računalnoj platformi bez poslužitelja kažete maksimalan broj istodobnih zahtjeva za funkcijama koje želite pokrenuti i platforma vrši skaliranje umjesto vas.

Cijene

Napokon, model određivanja cijena bez poslužitelja omogućuje vam skaliranje računa u oblaku na temelju upotrebe. Kada malo upotrebljavate, račun će vam biti nizak (ili ništa ako ostanete u slobodnom dometu). Naravno, vaš će se račun povećavati s upotrebom, ali nadamo se da ćete imati i novi prihod koji će podržati vaš veći račun u oblaku. Suprotno tome, ako biste upravljali vlastitim poslužiteljima, morali biste platiti osnovni trošak za pokretanje minimalnog broja potrebnih poslužitelja. Kako se upotreba povećavala, povećavali biste se u koracima cijelih poslužitelja, a ne u povećanjima pojedinačnih poziva funkcije. Model računanja bez poslužitelja izravno je proporcionalan vašoj upotrebi.

AWS Lambda za računalo bez servera

AWS Lambda je računalna platforma bez poslužitelja koja je implementirana na platforme Amazon Web Services poput EC2 i S3. AWS Lambda šifrira i pohranjuje vaš kôd u S3. Kada se od funkcije zatraži da se izvodi, ona stvara "spremnik" koristeći vaše runtime specifikacije, raspoređuje je na jednu od EC2 instanci u svojoj izračunavajućoj farmi i izvršava tu funkciju. Proces je prikazan na slici 2.

Steven Haines

When you create a Lambda function, you configure it in AWS Lambda, specifying things like the runtime environment (we'll use Java 8 for this article), how much memory to allocate to it, identity and access management roles, and the method to execute. AWS Lambda uses your configuration to setup a container and deploy the container to an EC2 instance. It then executes the method that you've specified, in the order of package, class, and method.

At the time of this writing, you can build Lambda functions in Node, Java, Python, and most recently, C#. For the purposes of this article we will use Java.

What is a Lambda function?

When you write code designed to run in AWS Lambda, you are writing functions. The term functions comes from functional programming, which originated in lambda calculus. The basic idea is to compose an application as a collection of functions, which are methods that accept arguments, compute a result, and have no unwanted side-effects. Functional programming takes a mathematical approach to writing code that can be proven to be correct. While it's good to keep functional programming in mind when you are writing code for AWS Lambda, all you really need to understand is that the function is a single-method entry-point that accepts an input object and returns an output object.

Serverless execution modes

While Lambda functions can run synchronously, as described above, they can also run asynchronously and in response to events. For example, you could configure a Lambda to run whenever a file was uploaded to an S3 bucket. This configuration is sometimes used for image or video processing: when a new image is uploaded to an S3 bucket, a Lambda function is invoked with a reference to the image to process it.

I worked with a very large company that leveraged this solution for photographers covering a marathon. The photographers were on the course taking photographs. Once their memory cards were full, they loaded the images onto a laptop and uploaded the files to S3. As images were uploaded, Lambda functions were executed to resize, watermark, and add a reference for each image to its runner in the database.

All of this would take a lot of work to accomplish manually, but in this case the work not only processed faster because of AWS Lambda's horizontal scalability, but also seamlessly scaled up and back down, thus optimizing the company's cloud bill.

In addition to responding to files uploaded to S3, lambdas can be triggered by other sources, such as records being inserted into a DynamoDB database and analytic information streaming from Amazon Kinesis. We'll look at an example featuring DynamoDB in Part 2.

AWS Lambda functions in Java

Now that you know a little bit about serverless computing and AWS Lambda, I'lll walk you through building an AWS Lambda function in Java. 

preuzimanje Preuzmite izvorni kod koda za primjer aplikacije za ovaj vodič, "Računanje bez poslužitelja s AWS Lambda." Stvorio Steven Haines za JavaWorld.

Implementacija Lambda funkcija

Lambda funkciju možete napisati na jedan od dva načina:

  • Funkcija može primati ulazni tok klijentu i upisivati ​​u izlazni tok natrag klijentu.
  • Funkcija može koristiti unaprijed definirano sučelje, u tom će slučaju AWS Lambda automatski deserijalizirati ulazni tok na objekt, proslijediti ga vašoj funkciji i serializirati odgovor vaše funkcije prije nego što ga vrati klijentu.

Najlakši način implementacije funkcije AWS Lambda je korištenje unaprijed definiranog sučelja. Za Javu u svoj projekt prvo trebate uključiti sljedeću knjižnicu jezgre AWS Lambda (imajte na umu da ovaj primjer koristi Maven):

 com.amazonaws aws-lambda-java-core 1.1.0  

Next, have your class implement the following interface:

Listing 1. RequestHandler.java

 public interface RequestHandler { /** * Handles a Lambda function request * @param input The Lambda function input * @param context The Lambda execution environment context object. * @return The Lambda function output */ public O handleRequest(I input, Context context); } 

The RequestHandler interface defines a single method: handleRequest(), which is passed an input object and a Context object, and returns an output object. For example, if you were to define a Request class and a Response class, you could implement your lambda as follows:

 public class MyHandler implements RequestHandler { public Response handleRequest(Request request, Context context) { ... } } 

Alternatively, if you wanted to bypass the predefined interface, you could manually handle the InputStream and OutputStream yourself, by implementing a method with the following signature:

 public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { ... } 

The Context object provides information about your function and the environment in which it is running, such as the function name, its memory limit, its logger, and the amount of time remaining, in milliseconds, that the function has to complete before AWS Lambda kills it.