More on billing
[aquarium] / doc / arch / aquarium.tex
1 \documentclass[preprint,10pt]{sigplanconf}
2 \usepackage{amsmath}
3 \usepackage{amssymb}
4 \usepackage{graphicx}
5 \usepackage[british]{babel}
6 \usepackage{url}
7 \usepackage{listings}
8 \usepackage{color}
9
10 \newcommand{\cL}{{\cal L}}
11
12 \begin{document}
13 \conferenceinfo{ScalaDays '12}{London, UK.}
14 \copyrightyear{2012}
15 \copyrightdata{1-59593-056-6/05/0006}
16
17 \titlebanner{DRAFT---Do not distribute}
18
19
20
21 \title{Aquarium: Billing for the Cloud in the Cloud}
22
23 \authorinfo{Georgios Gousios \and Christos Loverdos}
24 {GRNet SA}
25 {\{gousiosg,loverdos\}@grnet.gr}
26
27 \maketitle
28 \begin{abstract}
29     This paper describes the architecture for the Aquarium cloud infrastructure
30     software.
31 \end{abstract}
32
33 \category{D.3.3}{Programming Languages}{Language Constructs and Features}[Control structures]
34
35 \terms
36     Object-Oriented Programming, Philosophy
37
38 \keywords
39     OOP, Ontology, Programming Philosophy
40
41 \section{Introduction}
42 \section{Requirements}
43
44 Aquarium was designed on a clean sheet to serve a particular purpose,
45 namely the provision of billing services to an IaaS infrastructure,
46 and also be extensible to new services. In the following sections,
47 we briefly present the requirements that shaped Aquarium's design.
48
49 \subsection{Application Environment}
50 Aquarium developed as part of the Okeanos project at GRNet. The
51 Okeanos project is building a full stack public IaaS system for Greek
52 universities, and several services on top of it. Several components comprise
53 the Okeanos infrastructure:
54
55 \begin{description}
56
57     \item[Synnefo] is an IaaS management console. Users can create and start
58         VMs, monitor their usage, create private internal networks among VMs
59         and connect to them over the web. The service backend is based on
60         Google's Ganneti for VM host management and hundrends of physical
61         VM container nodes.
62
63     \item[Archipelago] is a storage service, based on the Rados
64         distributed object store. It is currently under development, and the
65         plan is to act as the single point of storage for VM images, shared
66         volumes and user files, providing clonable snapshots and distributed
67         fault tolerance.
68     
69     \item[Pithos] is a user oriented file storage service. Currently it its
70         second incarnation, it supports content deduplication, sharing of files
71         and folders and a multitude of clients.
72
73     \item[Astakos] is an identity consolidation system that also acts as the
74         entry point to the entire infrastructure. Users can login using 
75         identities from multiple systems, such as the Shibboleth (SAML) 
76         federation enabled across all Greek universities or their Twitter 
77         accounts.
78
79 \end{description}
80
81 While all the above systems (and several prospective ones) have different 
82 user interfaces and provide distinct functionality in the context of
83 the GRnet IaaS, they all share a common notion of \emph{resources}, access
84 and manipulation options to which they offer to users. 
85
86 \subsection{Sharing}
87
88 The Okeanos IaaS will support the Greek higher education, an estimated
89 population of 100.000 students and researchers. Each member will be granted
90 access to a collection of resources using her institutional account. To enforce
91 a limit to the resources that can be acquired from the platform, each user will
92 have a limited amount of credits, renewable each month, which will be allowed
93 to spend on any resource available through the infrastructure. Resources can
94 also be shared; for example files on the Pithos file service or virtual machine
95 images on the Archipelago storage are potentially subject to concurrent usage from 
96 multiple users. This means that charges for the use of a single resource
97 may need to be distributed among several users. Also this may mean that in order
98 for sharing to work correctly, users may need to transfer credits among them.
99
100
101 \subsection{Configuration}
102
103 Billing systems are by nature open ended. As new services are deployed, new
104 resources appear, while others might be phased out.  Moreover, changes to
105 company policies may trigger changes to price lists for those resources, while
106 ad-hoc requests for large scale computational resources may require special
107 pricing policies. In order for a billing system to be able to successfully
108 adapt to changing requirements, it must be able to accommodate such changes
109 without requiring changes to the application itself. This means that all
110 information required for Aquarium in order to perform a billing operation,
111 must be provided to it externally. Moreover, to ensure high-availability,
112 billing configuration should be updatable while Aquarium is running, or at
113 least with minimal downtime, without affecting the operation of external
114 systems.
115
116
117 \subsection{Scaling}
118
119 In the context of the Okeanos system, Aquarium provides billing services on a
120 per user basis for all resources exposed by other systems. As such, it is in
121 the critical path of user requests that modify resource state; all supported
122 applications must query Aquarium in order to ensure that the user has enough
123 credits to create a new resource. This means that for a large number of users
124 (given previous GRNet systems usage by the Greek research community, we
125 estimate a concurrency level of 30.000 users), Aquarium must update and
126 maintain in a queryable form their credit status, 
127 with soft realtime guarantees. 
128
129 Being on the critical path also means that Aquarium must be highly resilient,
130 too. If Aquarium fails, all supported systems will also fail. Even if Aquarium
131 fails for a short period of time, it must not loose any billing events, as this
132 will allow users to use resources without paying for them. Moreover, in case of
133 failure, Aquarium must not corrupt any billing data under any circumstances,
134 while it should reach an operating state very fast after a service restart.
135
136 \section{Architecture}
137
138
139
140 \section{Implementation}
141
142
143 \subsection{The configuration DSL}
144
145 The configuration requirements presented above were addressed by creating a new
146 domain specific language ({\sc dsl}), based on the YAML format.  The DSL
147 enables administrators to specify billable resources, billing policies and
148 price lists and combine them arbitrarily into agreements applicable to specific
149 users, user groups or the whole system. 
150 The DSL supports inheritance for policies, price lists and agreements and composition in the case of agreements.
151 It also facilitates the
152 definition of generic, repeatable debiting rules, which are then used by the
153 system to refill the user's account with credits on a periodic based.
154
155 The DSL is in itself based on five top-level entities, namely:
156
157 \begin{description}
158
159     \item[Resources] specify the properties of resources that Aquarium knows
160         about. Apart from the expected ones (name, unit etc), a resource has
161         two properties that affect billing: \textsf{costpolicy} defines the
162         algorithm to be used to calculate the resource usage, while the
163         \textsf{complex} attribute defines whether a resource can have one or
164         many instances per user.
165
166     \item[Pricelists] assign a price tag to each resource, within a timeframe.
167     
168     \item[Algorithms] specify the way the billing operation is done in response
169         to a billing event. The simplest (and default) way is to multiply the 
170         billable quantity with the applicable price. To enable more complex billing
171         scenarios, the Aquarium DSL supports a simple imperative language with
172         a number of implicit variables (e.g. \texttt{price, volume, date}) 
173         that enable administrators to specify, e.g. billing algorithms that
174         scale with billable volume. Similarily to pricelists, algorithms
175         have an applicability timeframe attached to them.
176
177     \item[Crediplans] define a number of credits to give to users and a repetition
178         period.
179
180     \item[Agreements] assign a name to algorithm, pricelist and creditplan triplets,
181         which is then assigned to each user.
182
183 \end{description}
184
185
186 \begin{figure}
187 \lstset{language=c, basicstyle=\footnotesize,
188 stringstyle=\ttfamily, 
189 flexiblecolumns=true, aboveskip=-0.9em, belowskip=0em, lineskip=0em}
190
191 \begin{lstlisting}
192 resources:
193   - resource:
194     name: bandwidthup
195     unit: MB/hr
196     complex: false
197     costpolicy: continuous
198 pricelists:
199   - pricelist: 
200     name: default
201     bandwidthup: 0.01
202     effective:
203       from: 0
204   - pricelist: 
205     name: everyTue2
206     overrides: default
207     bandwidthup: 0.1
208     effective:
209       repeat:
210       - start: "00 02 * * Tue"
211         end:   "00 02 * * Wed"
212       from: 1326041177        //Sun, 8 Jan 2012 18:46:27 EET
213 algorithms:
214   - algorithm:
215     name: default
216     bandwidthup: $price times $volume
217     effective:
218       from: 0
219 agreements:
220   - agreement:
221     name: scaledbandwidth
222     pricelist: everyTue2
223     algorithm:
224       bandwidthup: |
225         if $volume gt 15 then
226           $volume times $price
227         elsif $volume gt 15 and volume lt 30 then
228           $volume times $price times 1.2
229         else
230           $volume times price times 1.4
231         end
232 \end{lstlisting}
233
234 \caption{A simple billing policy definition.} 
235 \label{fig:dsl}
236 \end{figure}
237
238 In Figure~\ref{fig:dsl}, we present the definition of a simple (albeit valid) 
239 policy. The policy parsing is done top down, so the order of definition 
240 is important. The definition starts with a resource, whose name is then
241 re-used in order to attach a pricelist and a price calculation algorith to it.
242 In the case of pricelists, we present an example of \emph{temporal overloading};
243 the \texttt{everyTue2} pricelist overrides the default one, but only for 
244 all repeating time frames between every Tuesday at 02:00 and Wednesday at
245 02:00, starting from the timestamp indicated at the \texttt{from} field. Another
246 example of overloading is presented at the definition of the agreement, which
247 overloads the default algorithm definition using the imperative part of the
248 Aquarium {\sc dsl} to provide a scaling charge algorithm.
249
250 \subsection{Billing}
251
252 Commonly to most similar systems, billing in Aquarium is the application of the
253 provisions of a user's contract to an incoming billing event in order to
254 produce an entry for the user's wallet. However, in stark contrast to most
255 other systems, which rely on database transactions in order to securely modify
256 the user's balance, Aquarium performs account updates asynchronously and
257 concurrently for all users.
258
259 Per resource, the charging operation is affected by the cost policy and complexity
260 parameters. Specifically, the 3 available cost policies affect the calculation 
261 of the amount of resource usage to be charged as follows:
262
263 \begin{itemize}
264     \item resources employing the \textsf{continuous} cost policy are charged for
265         the actual resource usage through time. When a resource event arrives,
266         the previous resource state between the previous charge operation and the
267         current event event timestamp is charged and the resource state is then
268         updated. More formally, for continuous resources, if $f(t)$ represents
269         the function of resource usage through time and $p(t)$ is the function
270         representing the pricelist at time $t$, 
271         then the total cost up to a 
272         $c(t) = \sum_{i=0}^{t} {p(t) \times \int_0^{t}{f(t)dt}}$. Most resources
273         in Aquarium are continuous, for example bandwidth and disk space.
274
275     \item resources employing the \textsf{onoff} cost policy can be in two states:
276         either switched on and actively used or switched off. Therefore, the unit
277         of resource usage is time and not the actual resource usage, while the
278         period of charging is calculated only when the resource is switched on.
279         Virtual machines are examples of resources with the \textsf{onoff} cost
280         policy.
281
282     \item resources using the \textsf{distinct} cost policy are charged
283         upon usage, without time playing a role in the charge. Such resources
284         are useful for one off charges, such as the allocation of
285         virtual machine or the migration of a virtual machine to a less busy
286         host.
287
288 \end{itemize}
289
290 Billing events are obtained through a connection to a message queue. Upon
291 arrival, a billing event is stored in an immutable log, and then forwarded to
292 the user actor's mailbox; the calculation of the actual billing entries to be
293 stored in the user's wallet is done within the context of the user actor,
294 serially for each incoming events. This permits the actor to have mutable state
295 internally (as described in Section~\ref{sec:ustate}), without risking the
296 calculation correctness. The calculation process involves steps such as
297 validating the resource event, resolving the current state of resource affected
298 by the incoming resource event, deciding the value applicable pricelist and
299 algorithm, generating entries for the user's wallet and updating the current
300 resource state for the user. A significant source of complexity in the process
301 is the support for temporal overriding for pricelists and algorithms: within
302 the timeframe between resource updates, several policies or algorithms may be
303 active. The billing algorithm must therefore split the billing period to pieces
304 according the applicability of each policy/algorithm and make sure that at 
305 least a baseline policy is in effect in order to perform the calculation.
306 Consequently, a resource event might lead to several entries to the user's wallet.
307
308 The actual format of the event is presented in Figure~\ref{fig:resevt}.
309
310 \begin{figure}
311 \lstset{language=C, basicstyle=\footnotesize,
312 stringstyle=\ttfamily, 
313 flexiblecolumns=true, aboveskip=-0.9em, belowskip=0em, lineskip=0em}
314
315 \begin{lstlisting}
316 {
317   "id":"4b3288b57e5c1b08a67147c495e54a68655fdab8",
318   "occured":1314829876295,
319   "userId":31,
320   "cliendId":3,
321   "resource":"vmtime",
322   "eventVersion":1,
323   "value": 1,
324   "details":{
325     "vmid":"3300",
326     "action": "on"
327   }
328 }
329 \end{lstlisting}
330 \caption{A billing event example} 
331 \label{fig:resevt}
332
333 \end{figure}
334
335 \subsection{User State}
336 \label{sec:ustate}
337
338 \section{Performance}
339
340 To evaluate the performance and scalability of Aquarium, we performed two
341 experiments: The first one is a micro-benchmark that measures the time required
342 for the basic processing operation performed by Aquarium, which is billing for
343 increasing number of messages. The second one demonstrates Aquarium's
344 scalability on a single node with respect to the number of users.  In both
345 cases, Aquarium was run on a MacBookPro featuring a quad core 2.33{\sc g}hz
346 Intel i7 processor and 8{\sc gb} of {\sc ram}. We selected Rabbit{\sc mq} and
347 Mongo{\sc db} as the queue and database servers, both of which were run on a
348 virtualised 4 core with 4{\sc gb} {\sc ram} Debian Linux server. Both systems
349 were run using current versions at the time of benchmarking (2.7.1 for
350 Rabbit{\sc mq} and 2.6 for Mongo{\sc db}).  The two systems were connected with
351 a full duplex 100Mbps connection.  No particular optimization was performed on
352 either back-end system, nor to the {\sc jvm} that run Aquarium. 
353
354 To simulate a realistic deployment, Aquarium was configured, using the policy
355 {\sc dsl} to handle billing events for 4 types of resources, using 3 overloaded
356 pricelists, 2 overloaded algorithms, all of which were combined to 10 different
357 agreements, which were randomly (uniformly) assigned to users. To drive the
358 benchmarks, we used a synthetic load generator that worked in two stages: it
359 first created a configurable number of users and then produced billing events
360 that 
361
362
363 All measurements were done using the first working version of the
364 Aquarium deployment, so no real optimisation effort did take place. 
365
366
367 \section{Lessons Learned}
368
369 One of the topics of debate while designing Aquarium was the choice of
370 programming platform to use. With all user facing systems in the Okeanos cloud
371 being developed in Python and the initial Aquarium designers being beginner
372 Scala users (but experts in Java), the choice certainly involved risk that
373 management was initially reluctant to take. However, by breaking down the
374 requirements and considering the various safeguards that the software would
375 need to employ in order to satisfy them, it became clear that a
376 typesafe language was a hard requirement. Of the platforms examined, the {\sc
377 jvm} had the richest collection of ready made components; the Akka library was
378 particularly enticing for the scalability and distribution possibilities it
379 offered.
380
381 The choice of Scala at the moment it had been made was a high risk/high gain
382 bet for GRNet. However, the development team's experience has been generally
383 positive. Scala as a language was an enabling factor; case classes permitted
384 the expression of data models, including the configuration {\sc dsl}, that
385 could be easily be serialized or read back from wire formats while also
386 promoting immutability through the use of the \texttt{copy()} constructor. The
387 pervasive use of immutability allowed us to write strict, yet simple and
388 concise unit tests, as the number of cases to be examined was generally low.
389 The \textsf{Maybe}\footnote{\textsf{Maybe} works like \textsf{Option}, but it
390 has an extra possible state (\textsf{Failed}), which allows exceptions to be
391 encapsulated in the return type of a function, and then retrieved and accounted
392 for in a pattern matching operation with no side effects. More at
393 \url{https://github.com/loverdos/Maybe}} monad, enabled side-effect free
394 development of data processing functions, even in cases where exceptions were
395 the only way to go. Java interoperability was excellent, while thin Scala
396 wrappers around existing Java libraries enabled higher productivity and use of
397 Scala idioms in conjunction with Java code.
398
399 The Akka library, which is the backbone of our system, is a prime example of 
400 the simplicity that can be achieved by using carefully designed high-level
401 components. Akka's custom supervision hierarchies allowed us to partition the
402 system in self-healing sub-components, each of which can fail independently
403 of the other. For example, if the queue reader component fails due to a queue
404 failure, Aquarium will still be accessible and responsive for the {\sc rest}
405 interface. Also, Akka allowed us to easily saturate the processing components
406 of any system we tested Aquarium on, simply by tuning the number of threads (in
407 {\sc i/o} bound parts) and actors (in {\sc cpu} bound parts) per dispatcher. 
408
409 Despite the above, the experience was not as smooth as initially expected. The
410 most prominent problem we encountered was that of lacking documentation. The
411 Akka library documentation, extensive as is, only scratches the surface.
412 Several other libraries we use, for example Spray for {\sc rest} handling, have
413 non-existent documentation. The Java platform, and .Net that followed, has
414 shown that thorough and precise documentation are key to adoption, and we
415 expected a similar quality level. Related is the problem of shared community
416 wisdom; as most developers know, a search for any programming problem will
417 reveal several straightforward Java or scripting language sources. The
418 situation with Scala is usually the opposite; the expressive power of the
419 language makes it the current language of choice for treating esoteric
420 functional programming concepts, while simple topics are often neglected. Scala
421 has several libraries of algebraic datatypes but no {\sc yaml} parser. As Scala
422 gains mainstream adoption, we hope that such problems will fade.
423
424 From a software engineering point of view, the current state of the project was
425 reached using about 6 person months of effort, 2 of which were devoted to
426 requirements elicitation, prototype building and familiarizing with the
427 language. The source code currently consists of 5.000 lines of executable
428 statements (including about 1.000 lines of tests), divided in about 10
429 packages. The system is built using both {\sc sbt} and Maven. 
430
431 \section{Related Work}
432
433 \section{Conclusions and Future Work}
434 In this paper, we presented Aquarium, a high-performance, generic billing 
435 system, currently tuned for cloud applications. We presented the requirements
436 that underpinned its design, outlined the architectural decisions made
437 and analysed its implementation and performance.
438
439 Scala has been an enabling factor for the implementation of Aquarium, both
440 at the system prototyping phase and during actual development. 
441
442 Aquarium is still under development, with a first stable version 
443 being planned for early 2012. 
444
445 Aquarium is available under an open source license at 
446 \url{https://code.grnet.gr/projects/aquarium}.
447
448 \bibliographystyle{abbrvnat}
449 \bibliography{aquarium}
450
451 \end{document}