Безсървърни изчисления с AWS Lambda, част 1

Безсървърните изчисления може да са най-горещото нещо в облачните изчисления днес, но какво всъщност е? Този урок от две части започва с общ преглед на безсървърните изчисления - от това, което е, до това защо се счита за разрушително за традиционните изчисления в облак и как можете да го използвате в Java-базираното програмиране.

След прегледа ще получите практическо въведение в AWS Lambda, което се смята от мнозина премиерното Java-базирано решение за безсървърни изчисления днес. В част 1 ще използвате AWS Lambda, за да изградите, внедрите и тествате първата си функция Lambda в Java. В част 2 ще интегрирате вашата Lambda функция с DynamoDB, след което ще използвате AWS SDK, за да извикате Lambda функции в Java приложение.

Какво представлява изчисляването без сървър?

Миналата година разговарях с фирмен стажант за различни архитектурни модели и споменах безсървърна архитектура. Той бързо забеляза, че всички приложения се нуждаят от сървър и не могат да работят на тънък въздух. Стажантът имаше точка, дори да му липсваше моята. Безсървърните изчисления не са магическа платформа за стартиране на приложения.

Всъщност безсървърните изчисления просто означават, че вие, разработчикът, не трябва да се занимавате със сървъра. Безсървърна изчислителна платформа като AWS Lambda ви позволява да изградите своя код и да го внедрите, без да е необходимо да конфигурирате или управлявате основните сървъри. Вашата единица за разполагане е вашият код; не контейнерът, който хоства кода, или сървъра, който изпълнява кода, а просто самия код. От гледна точка на производителността има очевидни ползи от разтоварването на подробностите за това къде се съхранява кодът и как се управлява средата за изпълнение. Безсървърните изчисления също се определят на базата на показатели за изпълнение, така че има и финансово предимство.

Какво струва AWS Lambda?

По време на това писане ценовият ред на AWS Lambda се основава на броя на изпълнението и продължителността на изпълнението:

  • Първите ви милиони екзекуции на месец са безплатни, след което плащате 0,20 долара на милион екзекуции след това (0,0000002 на заявка).
  • Продължителността се изчислява от момента, в който кодът започва да се изпълнява, докато не върне резултат, закръглен до най-близките 100 ms. Заредената сума се основава на количеството RAM, разпределено за функцията, където цената е $ 0,00001667 за всяка GB-секунда.

Подробностите за ценообразуването и разпределението на безплатни нива са малко по-сложни, отколкото предполага обзорът. Посетете ценовото ниво, за да преминете през няколко ценови сценария.

За да получите представа за това как работят безсървърните изчисления, нека започнем с модела за изпълнение на безсървърните изчисления, който е илюстриран на фигура 1

Стивън Хейнс

Ето накратко модел за изпълнение без сървър:

  1. Клиент отправя заявка до безсървърната изчислителна платформа за изпълнение на определена функция.
  2. Безсървърната изчислителна платформа първо проверява дали функцията се изпълнява на някой от нейните сървъри. Ако функцията вече не се изпълнява, тогава платформата зарежда функцията от хранилище за данни.
  3. След това платформата разполага функцията на един от своите сървъри, които са предварително конфигурирани с среда за изпълнение, която може да изпълнява функцията.
  4. Той изпълнява функцията и улавя резултата.
  5. Той връща резултата обратно на клиента.

Понякога безсървърните изчисления се наричат ​​Функция като услуга (FaaS), тъй като детайлността на кода, който изграждате, е функция . Платформата изпълнява вашата функция на собствен сървър и организира процеса между заявките за функции и отговорите на функциите.

Наноуслуги, мащабируемост и цена

Три неща наистина имат значение за безсървърните изчисления: неговата наносервисна архитектура; фактът, че е практически безкрайно мащабируем; и ценовия модел, свързан с тази почти безкрайна мащабируемост. Ще разгледаме всеки от тези фактори.

Наноуслуги

Чували сте за микроуслуги и вероятно знаете за 12-факторни приложения, но безсървърните функции извеждат парадигмата на разбиване на компонент до съставните му части на съвсем ново ниво. Терминът "наноуслуги" не е признат в индустрията термин, но идеята е проста: всяка наноуслуга трябва да изпълнява едно действие или отговорност. Например, ако искате да създадете приспособление, актът на създаване ще бъде собствена наноуслуга; ако искате да изтеглите джаджа, актът на извличане също ще бъде наноуслуга; и ако искате да направите поръчка за приспособление, тази поръчка ще бъде поредната наноуслуга.

Архитектурата на наноуслугите ви позволява да дефинирате приложението си на много фино ниво. Подобно на разработеното от тестове (което ви помага да избегнете нежелани странични ефекти, като пишете кода си на ниво индивидуални тестове), архитектурата на nanoservices насърчава дефинирането на вашето приложение по отношение на много фини и специфични функции. Този подход увеличава яснотата за това, което изграждате и намалява нежеланите странични ефекти от новия код.

Микроуслуги срещу наноуслуги

Microservices ни насърчава да разделим едно приложение на колекция от услуги, които изпълняват определена задача. Предизвикателството е, че никой наистина не е определил количествено обхвата на една микрослужба. В резултат на това в крайна сметка определяме микроуслугите като съвкупност от свързани услуги, всички взаимодействащи с един и същ модел на данни. Концептуално, ако имате функционалност на ниско ниво, взаимодействаща с даден модел на данни, тогава функционалността трябва да влезе в една от свързаните с нея услуги. Взаимодействията на високо ниво трябва да извършват повиквания към услугата, вместо директно да заявяват базата данни.

Продължава дебатът в безсървърните изчисления за това дали да се изграждат ламбда функции на ниво микроуслуги или наноуслуги. Добрата новина е, че можете доста лесно да изградите функциите си при една или друга детайлност, но стратегията за микроуслуги ще изисква малко допълнителна логика за маршрутизиране във вашия обработващ заявки.

От гледна точка на дизайна, безсървърните приложения трябва да бъдат много добре дефинирани и изчистени. От гледна точка на внедряване ще трябва да управлявате значително повече внедрявания, но също така ще имате възможност да разгръщате нови версии на вашите функции поотделно, без да засягате други функции. Безсървърните изчисления са особено подходящи за разработка в големи екипи, където могат да помогнат за улесняване на процеса на разработка и по-малко склонност към грешки в кода.

Мащабируемост

В допълнение към въвеждането на нова архитектурна парадигма, безсървърните изчислителни платформи осигуряват практически безкрайна мащабируемост. Казвам „практически“, защото няма такова нещо като истинскибезкрайна мащабируемост. За всички практически цели обаче безсървърните компютърни доставчици като Amazon могат да се справят с повече натоварване, отколкото бихте могли да им хвърлите. Ако трябваше да управлявате мащабирането на собствените си сървъри (или базирани на облак виртуални машини), за да отговорите на увеличеното търсене, ще трябва да наблюдавате използването, да идентифицирате кога да стартирате повече сървъри и да добавяте повече сървъри към вашия клъстер в точното време. По същия начин, когато търсенето намалява, ще трябва да намалите ръчно. С безсървърните изчисления вие казвате на вашата безсървърна изчислителна платформа максималния брой едновременни заявки за функции, които искате да стартирате и платформата прави мащабирането вместо вас.

Ценообразуване

Finally, the serverless computing pricing model allows you to scale your cloud bill based on usage. When you have light usage, your bill will be low (or nil if you stay in the free range). Of course, your bill will increase with usage, but hopefully you will also have new revenue to support your higher cloud bill. For contrast, if you were to manage your own servers, you would have to pay a base cost to run the minimum number of servers required. As usage increased, you would scale up in increments of entire servers, rather than increments of individual function calls. The serverless computing pricing model is directly proportional to your usage.

AWS Lambda for serverless computing

AWS Lambda е безсървърна изчислителна платформа, внедрена върху платформите на Amazon Web Services като EC2 и S3. AWS Lambda кодира и съхранява вашия код в S3. Когато се иска функция да се изпълни, тя създава "контейнер", използвайки вашите спецификации за изпълнение, изпраща я в един от екземплярите на EC2 в своята изчислителна ферма и изпълнява тази функция. Процесът е показан на фигура 2.

Стивън Хейнс

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. 

изтегляне Вземете кода Изходен код за примерното приложение за този урок „Изчисляване без сървър с AWS Lambda“. Създадено от Стивън Хейнс за JavaWorld.

Внедряване на ламбда функции

Можете да напишете ламбда функция по един от двата начина:

  • Функцията може да получава входящ поток към клиента и да записва в изходен поток обратно към клиента.
  • Функцията може да използва предварително зададен интерфейс, като в този случай AWS Lambda автоматично ще десериализира входния поток към обект, ще го предаде на вашата функция и ще сериализира отговора на вашата функция, преди да го върне на клиента.

Най-лесният начин да внедрите AWS Lambda функция е да използвате предварително зададен интерфейс. За Java първо трябва да включите следната основна библиотека на AWS Lambda във вашия проект (имайте предвид, че този пример използва 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.