1. Computations are coming back to “virtual” clouded mainframes
Contemporary mainframes are huge data centers comprising tens or hundreds of thousands of interconnected physical servers and disk arrays. Usually, they are built according to cloud architecture where almost everything is virtualized starting with IaaS, PaaS and SaaS. The next virtualizations are FaaS (Function as a Service) and BaaS (Backend as a Service) that constitute a new computing paradigm called Serverless. It is based on an execution model in which an application consists of interrelated individual functions and backend services that can be managed, scaled and executed by cloud provider by automatic and dynamic allocations of compute resources. Developers (of the applications) are charged for—only the compute resources and storage needed to execute a particular piece of code.
Using FaaS and BaaS, developers can effectively implement micro-services that comprise the applications. Cloud providers are responsible for deploying the code, and for an application runtime environment. The book by Brendan Burns 2018 (Burns, 2018) (http://www.istrsjournal.org/wp-content/uploads/2018/06/Designing_Distributed_Systems.pdf) may serve as a classic (now a bit obsolete) introduction to this subject.
There are many serverless platforms provided by main players like Amazon Web Services, Microsoft Azure, Google Cloud Platform, IBM Cloud, Alibaba, etc. as well as many others.
They are trying to persuade developers do create applications mainly out of already existing and proprietary (more or less universal) functions and backend services by composing and orchestrating them into workflows. This gives rise to a new high-level programming paradigm, see, for example, Schleier-Smith et al. 2021 (Schleier-Smith
et al., 2021) https://dl.acm.org/doi/pdf/10.1145/3406011 where the following view was presented:
“ This next phase of cloud computing will change the way programmers work as dramatically as the first phase changed how operators work. […] new general-purpose serverless abstractions will emerge …”
The physical servers are based on the von Neumann architecture. The programming languages (for developing functions and backend services) are still of von Neumann style. However, the overall high-level architecture of cloud systems, and the emerging (serverless) programming style (see for example Castro et al. 2019 (Castro et al., 2019)) are not von-Neumann. This resembles the idea of function-level programming postulated by John Backus 1978 (Backus, 1978).
The classic functional programming languages (based on lambda calculus, lazy evaluation and term rewriting) like Clojure, Erlang, Scala, Haskell and many others, are of limited use here. The essence of serverless computing is dynamic orchestration of functions and backend services into workflows where the functions are black boxes with clearly defined input and output interfaces, and functionalities.
We are going to show that abstract calculus of functionals (higher-order functions) and relations (proposed in (Ambroszkiewicz, 2015a), and then extended in (Ambroszkiewicz, 2015b)) may help to understand and formalize the emerging serverless programming paradigm.
There are interesting speculations about the near future of serverless programming like The Serverless SuperComputer proposed by AWS Lambda creator Tim Wagner in 2019, and The Serverless End Game by Garcia et al. 2021 (Garcia Lopez et al., 2021) predicting virtualization and transparency of computing resources eventually enabling unlimited flexible scaling.
As a simple example of an application based on microservices, let us sketch briefly a shopping application composed of the following microservices:
A frontend application interface.
A search service that looks up products in a database based on user-generated search queries.
A product-detail service that displays additional information about products that users click on.
A shopping cart service to keep track of items that users place in their cart.
A checkout service that handles the payment process.
A service for maintaining inventory with a database.
A service for shipping orders.
These microservices and corresponding databases interact via communication protocols. This is just an example; applications can be decomposed into microservices in a variety of ways.
The general principle of cloud-native approach is that microservice performs one service only, runs independently of the other parts of application, operates in its own environment, and stores its own data (in a separate back-end service). Microservices do not have to be small in size as the prefix micro may suggest. The one service it performs may be quite large and complex.
Microservices constitute an architectural pattern in which complex and sophisticated applications are composed from a collection of fine-grained, independent microservices implemented and deployed independently of each other. They communicate over a network using lightweight protocols. They can be scaled if needed, e.g. by replication.
Once a collection of such microservices is composed and orchestrated into a dynamic workflow, then it can be deployed on a cloud infrastructure, and be called a Cloud-Native Application (CNApp for short). Let us explore the consequences of the above architectural pattern.
The first conclusion is that a CNApp is a network application. That is, it consists of several parts (here, they are microservices) that communicate to each other using dedicated specific protocols implemented on a networking protocol stack; so far it is still the Internet TCP,UDP/IP.
A general definition of protocol in distributed systems is as follows.
A protocol defines the format and the order of messages exchanged between two or more communicating entities. The order, types, and the contents of messages depend on the current state of sender. Sending (reception) of a message may cause a change of the state of sender (recipient).
Each of the specific protocols of CNApp is based on the client-server model of communication. It means that the server component is running on a host with a fixed network address, and is listening on a fixed port waiting for clients. A client component initializes a communication session to the server; so that the client must know the address and the port number. Usually, the server can communicate with many clients at the same time in separate threads. TCP sockets and UDP sockets are the Internet APIs for such communications.
The notions of server and client (in the protocols) are here different from the notions of physical server (a hardware) and client as a host (computer) requesting a service from that server.
Note that we abstract from HTTP and REST-based protocols that (although commonly used for inter microservice communications) usually hard-code the format of messages of the real protocols. HTTP and the REST-based are here mere transport protocols for the factual protocols. For serverless computing they are also inefficient because of additional and large latency overhead. See also (Pemberton et al., 2021) The RESTless cloud by Pemberton et al. 2021 https://sigops.org/s/conferences/hotos/2021/papers/hotos21-s03-pemberton.pdf, for an interesting discussion on serverless communication APIs.
A single microservice may implement and participate in multiple different protocols acting as a client and/or as a server.
Internal functionality of a microservice is event-driven and composed of serverless functions. Roughly, the incoming messages (as events) trigger serverless functions (dynamically composed into dataflows) to run, and then to produce outgoing messages. This will be explained in details in the next section.
Scaling by replication and reduction (closing replicas of microservice instances) of a microservice enforces its stateless. The reason is as follows. If a microservice is statefull, then closing a replica will result in the loss of its state if the state was not stored elsewhere before the closing.
Actually, the stateless is not a serious restriction, because a stateful microservice (with permanent stored data) may be decomposed into stateless part (where the basic functionality is performed), and bakckend services where the permanent data are stored. It is a common practice in CNApp development. The backend services should be (logically) the same for all replicas of the microservice in question. The communication with the backend services is done by specific dedicated protocols. The stateless microservice and its replicas implement clients whereas the backend storing services implement servers.
Hence, a replicate-able microservice can be roughly specified as collection of servers and/or clients of the protocols it participates in, and of its own internal functionality. Permanent data (state) of microservice are stored in dedicated backend storing services (BaaS). The internal functionality is composed of stateless elementary functions (FaaS, like the AWS Lambdas), and orchestrated into a dynamic dataflow.
Usually, communication protocols (at application layer) are defined in an abstract way independently of their implementation.
For our propose, protocol is defined as two tightly coupled software applications (implementing an abstract protocol): server and client . Formally, let it be denoted by pair with appropriate superscripts and/or subscripts if needed.
The abstract input of a microservice can be defined by the servers (of the protocols) it implements:
The abstract output of a microservice is defined by the clients (of the protocols) it implements:
Usually, at least one of the clients is for the communication with dedicated backend storing service.
To omit confusions, the server part and a client part of a protocol will be given another names. Components of abstract input will be called abstract sockets, whereas components of abstract output will be called abstract plugs.
An abstract plug may be connected to an abstract socket if they are of the same type, i.e., they are two complementary sides of the same communication protocol. There may be multiple abstract plugs to the same abstract socket. Let the connection (abstract plugabstract socket) be directed meaning that client has initialized a communication session (of protocol) with server.
Note that these abstract input and abstract output do not correspond necessarily to data flow. That is, data (messages) may be sent (according to a protocol) out from abstract input (an abstract socket) to an abstract output (an abstract plug).
Let us formalize the concept of microservice described above.
Microservice is defined as
where is the abstract input of the microservice, is the abstract output, and is the internal functionality of the microservice to be formally specified and defined in Section 3.
Note that abstract plugs (elements of ) may be dynamically created and/or closed in the runtime.
Incoming messages via abstract sockets of or via abstract plugs of invoke (as events) functions that comprise the internal functionality of the microservice. The functions (in dynamically created dataflow) produce messages to be send out by the abstract output or abstract input .
The Fig. 1 illustrates a microservice, and a microservice composed to an associated backend storing service. The composition is abstract, and means a communication session via protocol .
Fig. 2 depicts abstract composition of three microservices done by protocol and the protocol .
This gives rise to consider a microservice as an abstract function with abstract input and abstract output .
2.1. Proxy and manager of a microservice
Replication of a microservice is postulated as one of the main factors of the cloud-native approach.
CNApp is supposed to be formed by a collection of interconnected (via communication protocols) microservices. This is related to the concept of Service Mesh, i.e. a dedicated infrastructure layer for facilitating service-to-service communications. Examples of popular service meshes are Linkerd, CNCF project, and Istio https://istio.io/latest/docs/concepts/what-is-istio/ that is becoming a widely accepted open standard now. There are also interesting academic frameworks, for example, Kosińska and Zieliński 2020 (Kosińska and Zieliński, 2020) for autonomic management of CNApps.
A service mesh consists of network proxies (called also sidecars), each of them is paired with a microservice. There is also a collection of managements rules that coordinate the behavior of proxies and provides APIs to monitor and control the mesh.
Sidecar of microservice is the key concept of Service Mesh. It is is attached (and loosely coupled) to a microservice and extends /enhances its outside functionalities.
All the incoming and outgoing network traffic to/from an individual microservice flows through its sidecar. So that, the sidecar manages the traffic flow, can gather telemetry data, and can enforce policies of cloud provider. Sidecar can also perform several functionalities like load balancing (by microservice replication), security control, content cache, monitoring and management. For more on microservice sidecar see, https://dzone.com/articles/sidecar-design-pattern-in-your-microservices-ecosy-1.
Let us apply the concept of sidecar to any individual microservice, say , in CNApp, and call it manager & proxy (or sidecar) of , and denote it as .
Sidecar can replicate (or close some replicas of ) if needed, and manages (distributes) the input communication to and all its replicas. Hence, it acts as a proxy, and as a load balancer. This is illustrated by Fig. 3 and Fig. 4.
Sidecar of a microservice can also act as a proxy for the abstract output of the microservice and all its replicas.
Let us present simple example of (somewhat abstract) CNApp. Its microservices along with their -s can be composed into a CNApp in a way as it is depicted in Fig. 5.
The following layers may be distinguished for a typical CNApp, see also Fig. 5.
Frontend, i.e. GUIs for users of CNApp.
API Gateways on the top.
Middle layers for microservices performing the main functionality of CNApp.
Backend on the bottom for data storing microservices.
2.2. First level of abstract architecture of CNApp
Abstract multi graph of CNApp is defined as the following directed labeled multi-graph.
where and denote respectively Vertices and Edges defined below.
Vertices is a collection of sidecars () of all microservices of CNApp , i.e. elements of the form denoted also for short.
Edges is a collection of labeled edges of the graph of the form
where and belong to , and is a protocol, used in CNApp, between of and of . That is, belongs to of , and belongs to of .
Note that the abstract graph of CNApp is supposed to comprise all possible microservices and all edges (protocols) that might be used whenever the CNApp would be executed.
Multi graph means that there may be multiple edges (protocols) between two vertices.
It seems reasonable to assume that abstract graphs have no loops and no cycles, i.e they are acyclic labeled multi graphs.
Initial vertices of the graph correspond to API Gateways, whereas the terminal vertices correspond to backend data storing microservices.
While running CNApp, some of edges of its abstract graph may be inactive for some time-intervals, i.e. the corresponding protocols sessions are closed or not invoked yet, or can not be invoked for some reasons. This means dynamic shrinking or expanding of the active part of abstract graph at the runtime. This can be done by the sidecars of microservices according to the polices determined by cloud provider.
Since sidecar acts as a proxy for a microservice, it can monitor protocol session invocations as well as session closings. This can be implemented (in simple cases) by checking ACK and FIN flags in TCP segments if protocol sessions are implemented on permanent TCP connections.
In general case, sidecar should have access to event monitor implemented inside its microservice and replicas to know their current communication sessions.
The abstract graph of a CNApp is defined as static one. Temporal reductions of the graph due to inactive vertices and/or edges should not be viewed as the only transformations of the graph. There could be also dynamic transformations of the graph in the runtime due to contents (data) of the incoming messages from the frontend (from external users) or/and from the backend where the current state of CNApp can be stored.
Amazon EventBridge https://aws.amazon.com/eventbridge/ may be seen as a universal platform for transforming functionality of running CNApp. It connects microservices using events. Roughly, an event is a signal that a system’s state has changed. The events may also correspond to incoming and outgoing messages of implicit communication protocols hard-coded in microservices. The platform is at software level, and does not scale if the number of microservices and connections is getting large.
In 2019, Netflix had over 700 microservices, whereas Uber had over 500 microservices. Hence, the number of microservices approaches thousands in CNApps created by big tech companies.
If the number of vertices and the number of edges of the abstract graph and its transformations are relatively small (say dozens), it can be done manually by implementing dedicated management mechanisms. In general case, when complexity increases dramatically, the management requires generic mechanisms, see https://www.opslevel.com/2020/04/21/why-you-need-a-microservice-catalog/.
Since the abstract graphs are abstract compositions of abstract functions, these mechanisms (as higher level abstractions) should be related to abstract functional, i.e. operations on abstract functions.
It seems that a calculus of functionals may serve as a high level abstraction for implementing generic management rules for Service Mesh like Istio and others. More pro arguments are in Section 4.
3. Serverless computing paradigm
Serverless means that application code (serverless function) is executed on-demand in response to triggers (based on events) that application developers provide in advance. Usually, serverless functions implement discrete units of application functionality. For an up to date introduction to the subject, see https://www.sumologic.com/blog/microservices-vs-serverless-architecture/.
The serverless computing model includes also Backend as a Service (BaaS) component. It means that the entire backend (database, storage, etc.) of a system is handled independently and offered as a service.
3.1. Combining serverless and microservices
Serverless and microservices are different sorts of technologies. Microservices are a way to design an application, while serverless is a way to run an application (or a part of an application).
Recently, there is an emerging trend to combine serverless and microservices approaches. Cloud providers (like Google, Amazon, Microsoft) found ways to bridge the gap between them. That is, a microservice can be developed as a collection of interrelated and orchestrated event-driven serverless functions (as a workflow) and stored on the third-party vendor’s infrastructure. It can be done, for example, with Logic Apps (Microsoft), Step Functions (Amazon), or AirFlow workflow engine (Google). They allow assigning triggers to microservices, and combine several functions into a service. All these workflow engines (as well as others) are at software level, and provide tools to orchestrate (compose) serverless functions into a microservice or a complete application. It seems to be a right solution if the number of these functions is less than one hundred or something like that. If, additionally, the workflow requires its essential reconfiguration in the runtime, then a higher level of abstraction (above the software) is necessary to cope with complexity.
Both serverless functions and microservices (as a Service Mesh) require similar approaches to monitoring and management.
These approaches, like Amazon EventBridge, seem to be over-complicated. Let us present a different approach that can be scaled.
The crucial question to be answered is: What are events in a microservice, and what are they for?
Generally, events serve for dynamic (depending on these events) compositions of dataflows from serverless functions (including functions implementing protocols) that comprise functionality of microservice.
3.2. An abstract view of serverless architecture of microservice
Formal foundations of serverless computing is a hot research subject in academic community, see for example Jangda et al. 2019 (Jangda et al., 2019), Obetz et al. 2020 (Obetz et al., 2020), and Gerasimov 2019 (Gerasimov, 2019). They are based on classic (based on von Neumann programming style) formal techniques like operational semantics.
The key concept for the proposed abstract architecture of microservice is relation. An event may be defined as an evaluation of a relation to be either true or false.
Once proper relations are defined, the constructor if-then-else can be used to compose functions into dataflows.
Incoming messages to a microservice can be considered as coarse events to be processed in order to evaluate relations that (as conditions) trigger functions.
We need a formal framework to define functions and relations. Let us start with types, and let denote a type with superscripts and/or subscripts if needed. We might think of them as data types in programming languages; at this level of abstraction it is not essential. Let denote that object is of type .
denote function where (for ) is the type of its -th input, and (for ) is the type of its -th output.
Note that denotes the type of function .
Function may have multiple inputs, as well as multiple outputs.
Function application is denoted
where for . Result of this application is denoted where for ; so that .
Relation, denoted with subscripts and/or superscripts if needed, may be viewed as a boolean-valued function. i.e.
and evaluated as a function. Type consists of two logical values: true and false. In type theory, a special sort Propositions is needed for evaluation of relations. For simplicity, the type may serve as a substitute here.
Events are defined as evaluations of these relations.
Functions that process either incoming messages, or produce outgoing messages are defined as follows.
Function that processes messages incoming to abstract socket of protocol . Let the type of such messages be denoted by . Then, such a function is of the form
Analogously, for function that processes messages incoming to abstract plug of protocol . Let the type of such messages be denoted by . Then,
Function that generates messages outgoing from abstract socket of protocol . Let the type of such messages be denoted by . Then,
Analogously, function that produces messages outgoing from abstract plug of protocol . Let the type of such messages be denoted by . Then,
Note that one of the protocol may realize a one way communication with external timer in order to deliver (in consecutive time slots) the current date and time to the microservice.
Since it is supposed that the state of a microservice is stored in associated backend services, the protocols (for communications with these backend services) may deliver events informing the microservice on the state change.
Putting all these pieces together, functionality of microservice can be defined on the basis of:
functions, that process incoming messages, of the form with appropriate superscripts corresponding to protocols;
repository of relations ;
repository of functions ;
functions, that generate outgoing messages, of the form with appropriate superscripts corresponding to protocols.
Functionality of microservice may be presented as data flow graph where initial vertices are functions of the form that process incoming messages. Terminal vertices are functions of the form that produce outgoing messages.
The interior vertices of the graph are either functions from repository or constructors of the form if-then-else to be defined below.
Directed edges of the graph are just compositions, i.e. links (for data flow) directed from an output type of one function to an input type of another function. It means (a partial) composition of these two functions. The type of input and the type of output must be the same.
In Fig. 9, an idea of the constructor if-then-else is presented. Relation determines condition (event) if the values (data) for are delivered to the input of . If the relation is evaluated as true, then the link from input type to output type is established. Otherwise the link to output type (the same type as ) is established.
A simple example of event-dependent dataflow graph is presented in Fig. 10.
The dataflow graph for a microservice may be complex if the numbers of functions and relations are large. Then, construction, updating functions in the graph, and dynamic reconfiguration may require abstractions related to functionals as it is illustrated in Fig. 11, Fig. 12, and Fig. 13. Functional is the complete abstraction of the dataflow graph from Fig. 11. It means that expresses the essence of the dataflow graph connectivity, so that any vertex (concrete function) of the graph may be changed by any function of the same type as the type of the vertex. These changes result in a proper executable dataflow graph.
It is clear that static dataflow graph alone might not represent the entire functionality of a microservice if a recursion in involved. As an example, see Fig. 14 illustrating the construction of higher order primitive recursion schema presented in (Ambroszkiewicz, 2015b) where dataflow graph is expanded dynamically depending on input data.
There is a similar approach CIEL (a bit old) Murray et al. 2011 (Murray et al., 2011) where there are also similar data-dependent control flow constructors, and iterations as dynamic unfolding of acyclic dataflow graphs. In our approach we introduce much more, i.e. functionals as generic mechanisms for transformations of the graphs in the runtime.
Dynamic creation and/or closing abstract plugs of of microservice transforms its dataflow graph in the runtime by adding or removing appropriate functions. New connections (initialized by outside clients, i.e. by abstract plugs of another microservices) to abstract sockets of the microservice expand the dataflow with appropriate functions. Closing connections of some of the outside clients results in removing corresponding functions.
Hence, in general case, functionality of microservice consists in dynamic transformations of the dataflow graphs.
The graph transformations may be caused also by the input from its backend services where the state of microservice can be stored. The input may dynamically change the basic functionality of the microservice in the runtime.
Dynamic transformations of dataflow graphs can be viewed as functionals. Calculus of functionals and relations (Ambroszkiewicz, 2015b) may be seen as a general framework for constructing such dynamic dataflow graphs.
3.3. A bit more on functionals
At the basic level there are some primitive types, primitive functions and type constructors, i.e. the type of natural numbers, the successor function and the predecessor function, constant functions, projections, constructors for product and function types. The key primitive functionals correspond to application, composition, copy (replication), and iteration. It is crucial that these functionals can be constructed by (dynamic, in the case of iteration) establishing links between plugs (here corresponding to output types) and sockets (here corresponding to input types).
The type of functions from natural numbers into natural numbers (denoted by ) may be realized as a simple board consisting of a socket and a plug, see Fig. 15 where also types of higher order are presented. Note that for the type , the input becomes the socket. For the type , the output becomes the plug.
Application of a functional to a function is realized as follows. is the socket of the functional . The application is done (see Fig. 16) by establishing appropriate directed connections (links). That is, the link between the socket of the socket of and the socket of , and the link between the plug of and the plug of the socket of .
Composition functional (denoted by ) for simple composition of two functions (the first function of type , and the second one of type ) is realized as two boards with appropriate links shown in Fig. 17. It is easy to check (by following the links) that applying to two functions (see Fig. 17) results in their composition.
Note that a higher order application (i.e. application of a functional to a function), and a functional for composition are constructed just by providing some links between sockets and plugs.
A functional of special interest is as replication. So that returns two objects: the original , and its copy (replica) . Although the meaning of seems to be simple, its realization is not obvious in general case. In the clouds, there are no problems with replication of functions (as software) and data as bytes in memory.
Iteration is -times composition of a function with itself. Note that as a natural number is a parameter. The iteration is denoted by and it is a functional of type . So that is the function being -time composition of . The realization of requires for making copies of , and copies of the composition functional , see Fig. 18, where the construction is done for .
4. Summary and conclusions
Let us present some related work on workflows and FaaS.
HyperFlow (created by Balis 2016 (Balis, 2016)) provides an interesting (although explicitly not based on FaaS) model of computation for workflows. The abstraction there is still at the software level. Hyperflow was applied to serverless execution of scientific workflows Malawski et al. 2020 (Malawski et al., 2020), and Pawlik et al. 2019 (Pawlik et al., 2019).
Triggerflow, see Lopez et al. 2020 (López et al., 2020), is an interesting framework for composing event-based services. Although a formal model of workfow is presented as a Finite State Machine, its architecture and realization are done on the software level.
Bocci et al. 2021 (Bocci et al., 2021) presented an up to date overview of the existing literature on FaaS orchestrations, and their executions environments.
Ristov at al. 2021 (Ristov et al., 2021) proposed an abstract function choreography language (AFCL) for serverless workflow specification. The authors claim that AFCL is at a high-level of abstraction. Its basic constructs correspond to the classic programming control-flow and data-flow expressions, and are: if-then-else, switch, sequence, for, while, parallel, and parallelFor. They are not enough for all possible dynamic (in the runtime) reconfigurations of data-flows, and to cope with complexity if the number of functions is large.
All Cloud providers are now offering cloud orchestration and function composition services, for example, IBM Composer, Amazon Step Functions, Amazon Express Workfows, Azure Durable Functions, and Google Cloud Composer. All of them are essentially at software level, and do not provide higher-order abstractions to cope with complexity and dynamic reconfigurations.
The proposed abstract architecture of serverless Cloud-Native Apps consists of two layers of abstraction.
Top level concerns the so called service mesh. The abstract view of CNApp (consisting of interacting microservices) is presented in Section 2.2 as abstract multi graph of CNApp for orchestration of its microservices.
Bottom level is about the functionality of microservice. Dynamic event-driven dataflow graph (from the previous Section) is proposed as an abstract view of such functionality.
If the architecture is of some interest as a theoretical approach, then the following challenges emerge.
Repository of standard generic functions (like Lambdas in AWS Cloud).
Repository of standard communication protocols, and corresponding functions implementing the protocols.
Repository of standard generic relations.
Repository of standardized microservices build on the basis of the above repositories.
Platforms and tools for developing these repositories.
Tools and generic mechanisms for constructing the graphs and transforming them.
Managing complexity of internal structure of microservice if the number of its functions is large.
Managing complexity of CNApp if the number of its microservices in large.
Calculus of functionals and relations provides abstractions for reducing complexity of:
Construction of the dataflow graphs of microservices, and the abstract graphs of CNApps.
Dynamic reconfiguration and transformations of the graphs in the runtime.
- Ambroszkiewicz (2015a) Stanislaw Ambroszkiewicz. 2015a. Primitive recursion on higher types. https://doi.org/10.1109/csitechnol.2015.7358244. In 2015 Computer Science and Information Technologies (CSIT). Proceedings of IEEE, 23–32. https://doi.org/10.1109/CSITechnol.2015.7358244
- Ambroszkiewicz (2015b) Stanislaw Ambroszkiewicz. 2015b. Types and operations. arxiv.org/abs/1501.03043. arxiv.org/abs/1501.03043
- Backus (1978) John Backus. 1978. Can Programming Be Liberated from the Von Neumann Style?: A Functional Style and Its Algebra of Programs. Commun. ACM 21, 8 (Aug. 1978), 613–641. https://doi.org/10.1145/359576.359579
- Balis (2016) Bartosz Balis. 2016. HyperFlow: A model of computation, programming approach and enactment engine for complex distributed workflows. Future Generation Computer Systems 55 (2016), 147–162.
- Bocci et al. (2021) Alessandro Bocci, Stefano Forti, Gian-Luigi Ferrari, and Antonio Brogi. 2021. Secure FaaS orchestration in the fog: how far are we? Computing (2021), 1–32.
- Burns (2018) Brendan Burns. 2018. Designing Distributed Systems: Patterns and Paradigms for Scalable, Reliable Services (1st ed.). O’Reilly Media, Inc.
- Castro et al. (2019) Paul Castro, Vatche Ishakian, Vinod Muthusamy, and Aleksander Slominski. 2019. The rise of serverless computing. Commun. ACM 62, 12 (2019), 44–54.
- Garcia Lopez et al. (2021) Pedro Garcia Lopez, Aleksander Slominski, Michael Behrendt, and Bernard Metzler. 2021. Serverless Predictions: 2021-2030. arXiv e-prints (2021), arXiv–2104.
- Gerasimov (2019) Nikita Gerasimov. 2019. The DSL for composing functions for FaaS platform. In Fourth Conference on Software Engineering and Information Management (SEIM-2019)(full papers). 13.
- Jangda et al. (2019) Abhinav Jangda, Donald Pinckney, Yuriy Brun, and Arjun Guha. 2019. Formal foundations of serverless computing. Proceedings of the ACM on Programming Languages 3, OOPSLA (2019), 1–26.
- Kosińska and Zieliński (2020) Joanna Kosińska and Krzysztof Zieliński. 2020. Autonomic Management Framework for Cloud-Native Applications. Journal of Grid Computing 18, 4 (2020), 779–796.
- López et al. (2020) Pedro García López, Aitor Arjona, Josep Sampé, Aleksander Slominski, and Lionel Villard. 2020. Triggerflow: trigger-based orchestration of serverless workflows. In Proceedings of the 14th ACM International Conference on Distributed and Event-based Systems. 3–14.
- Malawski et al. (2020) Maciej Malawski, Adam Gajek, Adam Zima, Bartosz Balis, and Kamil Figiela. 2020. Serverless execution of scientific workflows: Experiments with HyperFlow, AWS Lambda and Google Cloud Functions. Future Generation Computer Systems 110 (2020), 502–514. https://doi.org/10.1016/j.future.2017.10.029
- Murray et al. (2011) Derek G Murray, Malte Schwarzkopf, Christopher Smowton, Steven Smith, Anil Madhavapeddy, and Steven Hand. 2011. Ciel: a universal execution engine for distributed data-flow computing. In Proc. 8th ACM/USENIX Symposium on Networked Systems Design and Implementation. 113–126.
- Obetz et al. (2020) Matthew Obetz, Anirban Das, Timothy Castiglia, Stacy Patterson, and Ana Milanova. 2020. Formalizing event-driven behavior of serverless applications. In European Conference on Service-Oriented and Cloud Computing. Springer, 19–29.
- Pawlik et al. (2019) Maciej Pawlik, Pawel Banach, and Maciej Malawski. 2019. Adaptation of Workflow Application Scheduling Algorithm to Serverless Infrastructure. In European Conference on Parallel Processing. Springer, 345–356.
- Pemberton et al. (2021) Nathan Pemberton, Johann Schleier-Smith, and Joseph E Gonzalez. 2021. The RESTless cloud. In Proceedings of the Workshop on Hot Topics in Operating Systems. 49–57.
- Ristov et al. (2021) Sasko Ristov, Stefan Pedratscher, and Thomas Fahringer. 2021. AFCL: An abstract function choreography language for serverless workflow specification. Future Generation Computer Systems 114 (2021), 368–382.
- Schleier-Smith et al. (2021) Johann Schleier-Smith, Vikram Sreekanti, Anurag Khandelwal, Joao Carreira, Neeraja J Yadwadkar, Raluca Ada Popa, Joseph E Gonzalez, Ion Stoica, and David A Patterson. 2021. What serverless computing is and should become: The next phase of cloud computing. Commun. ACM 64, 5 (2021), 76–84.