Abstract
Serverless computing, also known as Functions-as-a-Service, is a recent paradigm aimed at simplifying the programming of cloud applications. The idea is that developers design applications in terms of functions, which are then deployed on a cloud infrastructure. The infrastructure takes care of executing the functions whenever requested by remote clients, dealing automatically with distribution and scaling with respect to inbound traffic.
While vendors already support a variety of programming languages for serverless computing (e.g. Go, Java, Javascript, Python), as far as we know there is no reference model yet to formally reason on this paradigm. In this paper, we propose the first core formal programming model for serverless computing, which combines ideas from both the \(\lambda \)-calculus (for functions) and the \(\pi \)-calculus (for communication). To illustrate our proposal, we model a real-world serverless system. Thanks to our model, we capture limitations of current vendors and formalise possible amendments.
You have full access to this open access chapter, Download conference paper PDF
Similar content being viewed by others
1 Introduction
Serverless computing [24], also known as Functions-as-a-Service, narrows the development of Cloud applications to the definition and composition of stateless functions, while the provider handles the deployment, scaling, and balancing of the host infrastructure. Hence, although a bit of a misnomer—as servers are of course involved—the “less” in serverless refers to the removal of some server-related concerns, namely, their maintenance, scaling, and expenses related to a sub-optimal management (e.g. idle servers). Essentially, serverless pushes to the extreme the per-usage model of Cloud Computing: in serverless, users pay only for the computing resources used at each function invocation. This is why recent reports [18, 24] address serverless computing as the actual realisation of the long-standing promise of the Cloud to deliver computation as a commodity. AWS Lambda [4], launched in 2014, is the first and most widely-used serverless implementation, however many players like Google, Microsoft, Apache, IBM, and also open-source communities recently joined the serverless market [3, 16, 19, 21, 22, 29]. Current serverless proposals support the definition of functions—written in mainstream languages such as Go, Java, Javascript or Python—activated by specific events in the system, like a user request to a web gateway, the delivery of content from a message broker or a notification from a database. The serverless infrastructure transparently handles the instantiation of functions, as well as monitoring, logging, and fault tolerance.
Serverless offerings have become more and more common, yet the technology is still in its infancy and presents limitations [6, 18, 24] which hinder its wide adoption. For example, current serverless implementations favour operational flexibility (asynchrony and scalability) over developer control (function composition). Concretely, they do not support the direct composition of functions, which must call some stateful service in the infrastructure (e.g. a message broker) which will take care of triggering an event bound to the callee. On the one hand, that limitation is beneficial, since programmers must develop their functions as highly fine-grained, re-usable components (reminiscent of service-oriented architectures and microservices [12]). On the other hand, such openness and fine granularity increases the complexity of the system: programmers cannot assume sequential consistency or serialisability among their functions, which complicates reasoning on the semantics of the transformations applied to the global state of their architecture. This holds true also when estimating resource usage/costs, due to the complexity of unfolding all possible concurrent computations.
The above criticisms pushed us to investigate a core calculus for serverless computing, to reason on the paradigm, to model desirable features of future implementations, and to formalise guarantees over programs. In Sect. 2 we introduce the Serverless Kernel Calculus (SKC); as far as we know, the first core formal model for serverless computing. SKC combines ideas from both the \(\lambda \)-calculus (for functions) and the \(\pi \)-calculus (for communication). In Sect. 2, we also extend SKC to capture limitations of current serverless implementations. In Sect. 3 we use our extension to model a real-world serverless architecture [1], implemented on AWS Lambda. Finally, in Sect. 4 we discuss future developments of SKC.
2 A Serverless Kernel Calculus
Our kernel calculus defines a serverless architecture as a pair , where S is the system of running functions and \(\mathcal D\) is a definition repository, containing function definitions. The repository \(\mathcal D\) is a partial function from function names to function bodies M. M includes function application ( ), asynchronous execution of new functions ( ), function names , and values V. Values include variables , \(\lambda \)-abstractions , named futures [5, 17, 32] , and the unit value . A system S contains running functions , where c will contain the result of the computation of the function M. Systems can be composed in parallel \(\mathbin {\texttt {|}}\) and include the empty system . Futures can be restricted in systems via \(\mathop {\nu c}S\).
We assume futures to appear only at runtime and not in initial systems. Moreover, we consider a standard structural congruence \(\equiv \) that supports changing the scope of restrictions to avoid name capture, and where parallel composition is associative, commutative, and has as neutral element.
We define the semantics of our calculus using evaluation contexts \(\mathcal {E}\) and \(\mathcal {E}_{\lambda }\), to evaluate, respectively, systems and functions.
We report in Fig. 1 the semantics of serverless architectures , expressed as reduction rules. Rule is the traditional function application of \(\lambda \)-calculus. Rule retrieves the body of function from the definition repository \(\mathcal {D}\). Rule models the execution of new functions: it creates a fresh future c and, in parallel, it executes function M so that c will store the evaluation of M. When the evaluation of a function reduces to a value, rule returns the value to the associated future and removes both the terminated function and its restriction. Rules , and perform the closure under, respectively, structural congruence, restriction, and parallel composition. We include in SKC standard components (conditionals, etc.) and extend evaluation contexts (\(\mathcal {E}\)) accordingly:
We define standard macros for and declarations, and pairs.
2.1 SKC\(_\sigma \) - A Stateful Extension of SKC
SKC considers static definition repositories, i.e. no rules mutate the state of \(\mathcal {D}\). We now present SKC\(_\sigma \), an extension of SKC which includes two primitives to define transformations on definition repositories. As shown in Sect. 3, SKC\(_\sigma \) is powerful enough to encode stateful services, like databases and message queues.
The first primitive included in SKC\(_\sigma \) is , which updates the definition repository \(\mathcal {D}\) to map to M: users can use the primitive to deploy new function definitions or update/override existing ones. The second primitive is , which removes the definition of from \(\mathcal {D}\), returning it to the caller. We report below the semantics of the new primitives.
The only restriction on the application of rule is that the body M of the newly deployed function does not contain futures (futures(M) is the set of futures occurring in M). This preserves the semantics of restriction of futures in function evaluations (cf. rules and ). In the reductum, the rule returns the name of the deployed function, useful to invoke it in the continuation. Rule removes the definition M of a deployed function . For simplicity, we define applicable only if is defined. In the reductum, the caller of the obtains the declaration of the function (useful for internal application) while the association for is removed from \(\mathcal D\) by function \(\texttt {undef}\).
2.2 SKC\(_{\mathtt e}\) - Event-Based Function Composition in SKC
We present an idiom of SKC, called SKC\(_{\mathtt {e}}\), which models event-based function composition. SKC\(_{\mathtt e}\) captures one of the main limitations of current serverless vendors: the lack of support for direct function invocation, replaced by an event-handling/event-triggering invocation model. Indeed, current serverless implementations, such as AWS Lambda, work as follows: they include infrastructural stateful services, such as API gateways, that we can model using our stateful extension SKC\(_{\mathtt \sigma }\), and these services throw events. User-defined functions are invoked as handlers of these events. User-defined functions can then invoke the infrastructural services above. Notably, a user-defined function cannot directly invoke another user-defined function. We will see an instance of the event-based pattern in Sect. 3, while we describe below event handling mechanisms.
We model events ( and variations thereof) inside SKC as function names associated with peculiar function bodies in the repository \(\mathcal {D}\) that asynchronously evaluate the corresponding event handler and discard the handler result. For convenience, (i) we package the asynchronous call of an event handler in the helper function below (hereafter, we assume that \(\mathcal {D}\) contains ) and (ii) we write for unused variable symbols in binding constructs.
Event is defined in \(\mathcal D\) as and its event handler as ; we wrap the name in a lambda abstraction to avoid expansion (via ) since function names are not values. Raising an event with some parameter results in asynchronously executing the corresponding handler, as shown by the derivation below (we abbreviate as and label reductions with the names of the most relevant applied rules).
3 An Illustrative Example
Let SKC\(_{\sigma \mathtt e}\) be the compound of SKC\(_\sigma \) and SKC\(_{\mathtt e}\) presented in Sect. 2. Here, we illustrate how SKC\(_{\sigma {\mathtt e}}\) can capture real-world serverless systems by encoding a relevant portion (depicted in Fig. 2) of Tailor [1], an architecture for user registration, developed by Autodesk over AWS Lambda. Tailor mixes serverless functions with vendor-specific services: API Gateways, key-value databases (DynamoDB), and queue-based notification services (SNS). In the architecture, each function defines a fragment of the logic of a user-registration procedure, like the initiation of registration requests ( ), request validation ( ), etc. To model Fig. 2 in , first, we install in \(\mathcal {D}\) the event handlers for the API Gateway, the DynamoDB, and SNS servicesFootnote 1:
Then, we define the functions called by the handlers installed above, using the same names of the AWS Lambda functions in Fig. 2. Handler calls function , which validates the request and inserts the information of the user in the key/value database. For brevity, we omit the behaviour of in case of invalid requests and the definition of auxiliary functions in \(\mathcal D\):
Handler invokes function , which retrieves from the database the of task , checks if it is complete, and sends a notification on SNS. We omit the definitions of functions and and of the branch.
We conclude illustrating the definitions of functions , and in \(\mathcal D\), which exemplify how SKC\(_{\sigma \mathtt {e}}\) can encode stateful, event-triggering services. Keys are represented as function names and values are stored in \(\mathcal {D}\); thus keys are passed around wrapped in lambda abstractions ( ) as done for events.
Function takes a key (wrapped as ) and a value as parameters, writes on the database by to the body of a function called , and notifies the write, invoking Footnote 2. Function simply unwraps the key thus enabling retrieval from \(\mathcal {D}\). Similarly to , function publishes ( ) a message on an SNS topic (represented as a function name) and triggers .
Remark 3.1
The example illustrates how SKC can capture (but not be restricted by) one of the most prominent limitations of current serverless platform [18], i.e. that i) user-defined functions can be only invoked by raising an event that executes a new function (as done by , using the primitive) and ii) functions can invoke other functions only by interacting with some event-triggering infrastructural service (e.g. a database, represented by function , or a notification queue, represented by function ).
4 Discussion and Conclusion
We propose SKC, the first core formal model to reason on serverless computing. While the design of SKC strives for minimality, it captures the main ingredients [18, 24] of serverless architectures: (i) the deployment and instantiation of event-triggered, stateless functions and (ii) the desiderata of direct function-to-function invocation based on futures—in Sect. 3 we show how this mechanism is powerful enough to cover also the current setting of serverless vendors, where function invocation must rely on third-party services that handle event triggering.
Futures [5, 17], which are the main communication mechanism in SKC, are becoming one of the de-facto standards in asynchronous systems [13, 15, 35, 37]. We considered using named channels (as in CCS/\(\pi \)-calculus [30, 34]) instead of futures, but we found them too general for the needs of the serverless model (they are bi-directional and re-usable). Besides, futures can encode channels [32].
The work closest to ours is [23], appeared during the submission of this work, in the form of a technical report. It presents a detailed operational semantics that captures the low-level details of current serverless implementations (e.g. cold/warm components, storage, and transactions are primitive features of their model) whereas SKC identifies a kernel model of serverless computing. Another work close to SKC is [32], where the authors introduce a \(\lambda \)-calculus with futures. Since the aim of [32] is to formalise and reason on a concurrent extension of Standard ML, their calculus is more involved than SKC, as it contains primitive operators (handlers and cells) to encode safe non-deterministic concurrent operations, which can be encoded as macros in SKC. An interesting research direction is to investigate which results from [23, 32] can be adapted to SKC.
Being the first core framework to reason on serverless architectures, SKC opens multiple avenues of future research. For example, current serverless technologies offer little guarantee on sequential execution across functions, which compels the investigation of new tools to enforce sequential consistency [28] or serialisability [33] of the transformations of the global state [18]. That challenge can be tackled developing static analysis techniques and type disciplines [2, 20] for SKC. Another direction concerns programming models, which should give to programmers an overview over the overall logic of the distributed functions and capture the loosely-consistent execution model of serverless [18]. Choreographic Programming [10, 31] is a promising candidate for that task, as choreographies are designed to capture the global interactions in distributed systems [26], and recent results [9, 11, 14] confirmed their applicability to microservices [12], a neighbouring domain to that of serverless architectures. Other possible research directions, that we do not discuss for space constraints, include monitoring, various kinds of security analysis including “self-DDoS attacks” [25, 27, 36] and performance analysis. This last one is particularly relevant in the per-usage model of serverless architectures, yet requires to extend SKC with an explicit notion of time in order to support quantitative behavioural reasoning for timed systems [7, 8].
Notes
- 1.
We omit the name of the function called by , excluded in the excerpt of Fig. 2.
- 2.
More involved variants of the database are possible. E.g. to avoid clashes among services using the same key for different elements, we can either use scoping or prefix key names with service names—e.g. Tailor uses service-specific tables in DynamoDB.
References
Williams, A.: Tailor - the AWS Account Provisioning Service. https://github.com/alanwill/aws-tailor. Accessed Feb 2019
Ancona, D., et al.: Behavioral types in programming languages. Found. Trends Program. Lang. 3(2–3), 95–230 (2016)
Apache: OpenWhisk. https://github.com/apache/incubator-openwhisk. Accessed Feb 2019
AWS: Lambda. https://aws.amazon.com/lambda/. Accessed Feb 2019
Baker Jr., H.C., Hewitt, C.: The incremental garbage collection of processes. ACM Sigplan Not. 12(8), 55–59 (1977)
Baldini, I., et al.: Serverless computing: current trends and open problems. In: Chaudhary, S., Somani, G., Buyya, R. (eds.) Research Advances in Cloud Computing, pp. 1–20. Springer, Singapore (2017). https://doi.org/10.1007/978-981-10-5026-8_1
Brengos, T., Peressotti, M.: A uniform framework for timed automata. In: CONCUR. LIPIcs, vol. 59, pp. 26:1–26:15. Schloss Dagstuhl - Leibniz-Zentrum fuer Informatik (2016)
Brengos, T., Peressotti, M.: Behavioural equivalences for timed systems. Log. Methods Comput. Sci. 15(1), 17:1–17:41 (2019)
Carbone, M., Montesi, F.: Deadlock-freedom-by-design: multiparty asynchronous global programming. In: POPL, pp. 263–274. ACM (2013)
Cruz-Filipe, L., Montesi, F.: A core model for choreographic programming. In: Kouchnarenko, O., Khosravi, R. (eds.) FACS 2016. LNCS, vol. 10231, pp. 17–35. Springer, Cham (2017). https://doi.org/10.1007/978-3-319-57666-4_3
Dalla Preda, M., et al.: Dynamic choreographies: theory and implementation. Log. Methods Comput. Sci. 13(2), 1–57 (2017)
Dragoni, N., et al.: Microservices: yesterday, today, and tomorrow. Present and Ulterior Software Engineering, pp. 195–216. Springer, Cham (2017). https://doi.org/10.1007/978-3-319-67425-4_12
Ecmascript 2018 language specification. http://ecma-international.org/ecma-262/9.0/index.html. Accessed Feb 2019
Giallorenzo, S., Montesi, F., Gabbrielli, M.: Applied choreographies. In: Baier, C., Caires, L. (eds.) FORTE 2018. LNCS, vol. 10854, pp. 21–40. Springer, Cham (2018). https://doi.org/10.1007/978-3-319-92612-4_2
Goetz, B., et al.: Java Concurrency in Practice. Pearson Education, London (2006)
Google: Cloud Functions. https://cloud.google.com/functions. Accessed Feb 2019
Halstead Jr., R.H.: Multilisp: a language for concurrent symbolic computation. ACM Trans. Program. Languages Syst. (TOPLAS) 7(4), 501–538 (1985)
Hellerstein, J.M., et al.: Serverless computing: one step forward, two steps back. In: CIDR (2019). www.cidrdb.org
Hendrickson, S., et al.: Serverless computation with OpenLambda. In: USENIX. USENIX Association (2016)
Hüttel, H., et al.: Foundations of session types and behavioural contracts. ACM Comput. Surv. 49(1), 3:1–3:36 (2016)
IBM: Cloud Functions. https://www.ibm.com/cloud/functions. Accessed Feb 2019
Iron.io: IronFunctions. https://open.iron.io. Accessed Feb 2019
Jangda, A., et al.: Formal foundations of serverless computing. CoRR abs/1902.05870 (2019). arXiv:1902.05870
Jonas, E., et al.: Cloud programming simplified: a berkeley view on serverless computing. Technical report, EECS Department, University of California, Berkeley, Feburary 2019
K-Optional Software: serverless out of Control. https://koptional.com/2019/01/22/serverless-out-of-control/. Accessed Feb 2019
Kavantzas, N., Burdett, D., Ritzinger, G., Lafon, Y.: Web services choreography description language version 1.0, W3C candidate recommendation. Technical report, W3C (2005). http://www.w3.org/TR/ws-cdl-10
Kevin Vandenborne: serverless: a lesson learned. The hard way. https://sourcebox.be/blog/2017/08/07/serverless-a-lesson-learned-the-hard-way/. Accessed Feb 2019
Lamport, L.: How to make a multiprocessor computer that correctly executes multiprocess programs. IEEE Trans. Comput. 28(9), 690–691 (1979)
Microsoft: Azure Functions. https://azure.microsoft.com/services/functions. Accessed Feb 2019
Milner, R. (ed.): A Calculus of Communicating Systems. LNCS, vol. 92. Springer, Heidelberg (1980). https://doi.org/10.1007/3-540-10235-3
Montesi, F.: Kickstarting choreographic programming. In: Hildebrandt, T., Ravara, A., van der Werf, J.M., Weidlich, M. (eds.) WS-FM 2014-2015. LNCS, vol. 9421, pp. 3–10. Springer, Cham (2016). https://doi.org/10.1007/978-3-319-33612-1_1
Niehren, J., Schwinghammer, J., Smolka, G.: A concurrent lambda calculus with futures. Theor. Comput. Sci. 364(3), 338–356 (2006)
Papadimitriou, C.H.: The serializability of concurrent database updates. J. ACM 26(4), 631–653 (1979)
Sangiorgi, D., Walker, D.: The Pi-Calculus - A Theory of Mobile Processes. Cambridge University Press, Cambridge (2001)
Summerfield, M.: Python in Practice: Create Better Programs Using Concurrency, Libraries, and Patterns. Addison-Wesley, Reading (2013)
Wright, T.: Beware “RunOnStartup” in Azure Functions – a serverless horror story. http://blog.tdwright.co.uk/2018/09/06/beware-runonstartup-in-azure-functions-a-serverless-horror-story/. Accessed Feb 2019
Williams, A.: C++ Concurrency in Action. Manning, New York (2017)
Acknowledgements
This work was partially supported by the Independent Research Fund Denmark, grant no. DFF-7014-00041.
Author information
Authors and Affiliations
Corresponding author
Editor information
Editors and Affiliations
Rights and permissions
Copyright information
© 2019 IFIP International Federation for Information Processing
About this paper
Cite this paper
Gabbrielli, M., Giallorenzo, S., Lanese, I., Montesi, F., Peressotti, M., Zingaro, S.P. (2019). No More, No Less. In: Riis Nielson, H., Tuosto, E. (eds) Coordination Models and Languages. COORDINATION 2019. Lecture Notes in Computer Science(), vol 11533. Springer, Cham. https://doi.org/10.1007/978-3-030-22397-7_9
Download citation
DOI: https://doi.org/10.1007/978-3-030-22397-7_9
Published:
Publisher Name: Springer, Cham
Print ISBN: 978-3-030-22396-0
Online ISBN: 978-3-030-22397-7
eBook Packages: Computer ScienceComputer Science (R0)