{'fraction_non_alphanumeric': 0.022032114607733307, 'fraction_numerical': 0.006212445259191363, 'mean_word_length': 5.208219178082191, 'pattern_counts': {'":': 0, '<': 0, '<?xml version=': 0, '>': 1, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
Beauty and the beast: A case study on performance prototyping of data-intensive containerized cloud applications

Data-intensive container-based cloud applications have become popular with the increased use cases in the Internet of Things domain. Challenges arise when engineering such applications to meet quality requirements, both classical ones like performance and emerging ones like elasticity and resilience. There is a lack of reference use cases, applications, and experiences when prototyping such applications that could benefit the research community. Moreover, it is hard to generate realistic and reliable workloads that exercise the resources according to a specification. Hence, designing reference applications that would exhibit similar performance behavior in such environments is hard. In this paper, we present a work in progress towards a reference use case and application for data-intensive containerized cloud applications having an industrial motivation. Moreover, to generate reliable CPU workloads we make use of ProtoCom, a well-known library for the generation of resource demands, and report the performance under various quality requirements in a Kubernetes cluster of moderate size. Finally, we present the scalability of the current solution assuming a particular autoscaling policy. Results of the calibration show high variability of the ProtoCom library when executed in a cloud environment. We observe a moderate association between the occupancy of node and the relative variability of execution time.


Introduction
Containers [18] have become the de-facto standard for packaging and deploying microservice-based applications in the cloud. A particular class of such applications continuously processes streams of data generated by a variety of connected data-sources. The performance of such applications is business-critical. In addition to performance, elasticity and resilience have become two required quality attributes to cost-efficiently handle disruptive events like unexpected failures or changes in the demand.
Scaling non-trivial microservice-based applications remains a challenge for service providers due to the uncertain cloud environment. Achieving elasticity and resilience through an upfront engineering process requires suitable prediction models. There is, however, a lack of reference use cases, applications and experiences matching the characteristics of data-intensive cloud applications that would allow researchers to evaluate their approaches. Two prominent reference applications are proposed to foster research of microservice-based cloud applications: TeaStore [21] and SockShop [3]. Both serve more traditional use cases of classical human-centered request-reply applications. They lack, however, a processing pipeline of continuous data and also do not use asynchronous messaging communication which is very popular in such use cases. In addition, when prototyping such systems, it is hard to generate realistic workloads that utilize the resources according to a given specification (e.g., the time, that operations should consume the CPU).
To tackle the aforementioned problems we present a work in progress towards a reference use case and application for enabling research for data-intensive containerized cloud applications. To generate more reliable CPU workloads and to make the application more predictable in terms of performance, we make use of ProtoCom [7], a library for calibrating and generating CPU demands on various hardware. In addition we present two different scaling strategies for the defined application and present scalability experiments to obtain a first assessment of the capabilities of the application. Moreover, we investigate on the high variability of the load generation approach as our initial results showed high deviations from the expected response times.
The focus of this work is twofold: first, in Section 3, we introduce the reference use case and present performance requirements and the chosen implementation stack; second, in Section 4, we show the variability of the resource demand generation with ProtoCom in a cloud environment, initial scaling variants for the use case and experiments that show the scalability aspect of our microservice-based implementation. In addition, Section 2 presents related work and finally, Section 5 concludes the paper and provides an outlook on future work.

Related Work
Our related work can be divided into two different categories. On the one hand, several benchmarks have been developed as a reference for cloud applications and their performance. On the other hand microbenchmarking has been applied to measure the impact of virtualized environments and to quantify the performance isolation available in those. While we can not solve these inherent problems, developers must be aware of those effects affecting performance and scalability in virtualized and containerized applications.
In [16] Nikounia et al. introduce the noisy neighbour problem, an effect that can be observed in shared infrastructures where the activity on a neighboring core may lead to performance degradation. They report on performance degradation of up to 16x slowdown in virtualized environments. This is caused by noisy neighbour VMs, overcommitment and hypervisor noise.
In [12] Laaber et al. present their findings on using microbenchmarking to assess the performance impact in virtualized environments. The authors performed several experiments on systems deployed in public cloud environments and report on slowdown effects ranging from 0.003% to > 100%. They state that several repetitions on several VM instances are required to get robust results for microbenchmarks and to detect potential slowdowns.
In [14] Lehrig et al. present experiments conducted with the ProtoCom library in a virtualized cloud environment. They show that ProtoCom is well suited to emulate CPU demands realistically when using a calibration based approach.
In addition to many benchmark and test application like Spring PetClinic [4] or ACME Air [1], several academic casestudy systems have been developed in the past for evaluating the performance of cloud and containerised systems: In [21] the Tea Store case-study is presented, a system for studying the performance of microservices based systems. A similar microservices based benchmark using container technologies, the Sock Shop, is presented in [3]. The CloudStore application [13] is a reference application for comparing different cloud providers, cloud service architectures, and assess cloud deployment options. The TrainTicket benchmark [22] in addition focuses on the fault-analysis of microservice-based applications. All four case-study systems have in common that mostly request-response semantics is employed. Asynchronous data-centric communication patterns as typical found in IoT systems are missing.

Running Example
Before going into the implementation details of the running example in Section 3.3, we will explain the considered use case, its purpose and architecture in Section 3.1, and discuss performance challenges in Section 3.2.

Reference Use Case
The herein considered use case -called remote measuringis a fraction of one service package from the Bosch mobility cloud [9]. The mobility cloud is a cloud-based integration platform for developing and updating vehicle software and services. The services are grouped into three packages: over-the-air services (update, function call, essentials, vehicle data), data services (data integration, navigation, broker), and core services (service integration, application run time, application marketplace). Remote measuring is one service from the over-the-air vehicle data package. We consider parts of remote measuring in the implemented running example and its model representation.
The app remote measuring is designed for vehicle data acquisition campaigns. Such cloud-based campaigns are beneficial in vehicle development, fleet observation (e.g. tracking of failure codes in a delivery car fleet), predictive diagnostics, and optimization of spare part logistics in aftermarket business. Imagine a vehicle homologation task [15], where several vehicles must collect data from test rides. Cloudbased remote measuring allows test engineers to configure and conduct a signal measurement setup through web services. Such a setup contains the number and kind of signals, their recording frequency and recording triggers. The test engineer starts the measurement through a web front end. Data is cached in the car and pushed to the cloud, where the data is stored in a database. Then, the data is converted and presented as dashboard, or exported via an API for external applications. This is more flexible and convenient in contrast to conventional workflows, where each vehicle was  Figure 1. Architectural snipped of remote measuring application in mobility cloud suite.
equipped with a signal recorder, a laptop, and a test engineer who configured the campaign, stored the data and fed it into a data center afterwards. Figure 1 explains the architecture of the running example remote measuring. Starting in the lower left corner, one or more devices (vehicles) send data from their vehicle bus (CAN bus [10]) to the device communication service. This service tracks the readiness of the device, caches data, stores the raw data in a data base, and triggers the next service data provider. Once, a new batch of data arrived, the data provider service triggers the data processing service, which conducts data pre-processing and data compression. For this, the data processing fetches the raw data from data base. This part of the use case is considered and implemented in the running example.
The user interface and API on the right in Figure 1 are not implemented in the running example but shown here to understand the use case from end to end. The data processing triggers an export service, which provides the converted data through API and triggers a data dashboard. The API can be used for customized data analysis on customer side.

Requirements and Performance Challenges
The remote measuring use case provides several challenges for development and operations in the mobility cloud. These challenges affect elasticity and resilience properties of the application in practice.
In regard to elasticity, the first challenge arises from broad range of configuration options in data acquisition campaigns. These campaigns may differ largely in terms of number of recorded vehicle signals, their record frequency, and the number of devices itself. In vehicle homologation, the number of connected devices is rather small, but the number of considered signals is large. Add to this, the data recording frequency in homologation is large and such a campaign is usually triggered in parallel within a few days. This results into single events where large amount of data is pushed into the cloud from the test vehicles.
In contrast, in fleet observation the number of devices is large, but the number of signals and their recording frequency are small. Due to large number of devices, the accumulated load is large as well, but during fleet observation, we assume that devices connect to the cloud in a rather random and asynchronous profile.
The goal in both usage scenarios is to provide the remote measuring service with acceptable response time for the customer. Hence, remote measuring requires sufficient elasticity to cope with different usage scenarios.
Add to this, the elasticity property of remote measuring determines another service level objective: the cloud costs. While under provisioning causes unacceptable high response times for the users, over provisioning causes high costs, which reduce the revenue of the remote measuring service. Therefore, we search for optimal elasticity property of remote measuring in development and operations.
With respect to resilience, the homologation scenario requires credible data handling to avoid data loss during expensive and elaborate vehicle test rides. Compared with fleet observation, data loss during homologation would cause repetitions of test rides, which can destruct project plans and time to market goals in vehicle development projects. In addition, outage of remote measuring during homologation usage would destroy user trust in the application. Due to this, methods to design and test resilience of the applications are of high importance.

Performance Prototype/Demonstrator
The remote measuring use case from Figure 1 was re-implemented as performance prototype based on the Spring Boot 1 framework. The components device communication, data provider, data processing, and database were deployed as containers on an eight node Kubernetes (K8s) 2 cluster on bwCloud 3 , a state funded academic cloud. The components use the ProtoCom 4 library to emulate CPU demands.
All components and the database were connected through a RabbitMQ 5 message broker, which runs on a dedicated node on K8s cluster. The database was deployed as Mon-goDB 6 container. The functionality of the devices was resembled by Gatling 7 load generator. Gatling was used to define load profiles for the system. A load profile consists of the number and the ramp up time of the connecting devices, and frequency and size of sent data. Gatling was deployed as container on a dedicated node in K8s. Several experiments were conducted with different load profiles. Each experiment was triggered as K8s job and the results from Gatling were stored together with monitoring data from Prometheus 8 for following analysis.

Performance Variability of Resource Demand Generation
As described previously, to emulate processing of messages in the different services (e.g., the data processing service) each microservice uses ProtoCom. ProtoCom requires a low contention calibration phase to determine the input for a particular algorithm (say Fibbonaci number computations) to put load on the CPU for a given time amount (e.g., consume the CPU for 0.2 CPU-seconds). The results of the calibration are stored in a model as shown in Table 1 which contains the approximated input parameter associated with their individual execution times. Every other resource demand is generated by composing these demands. Since the calibration process consumes time (around 20 minutes for HIGH accuracy) and the test-bed cluster is homogeneous we initially thought of pre-calibrating ProtoCom and sharing the calibration for all service replicas. This would allow us to execute elasticity experiments and upon the spin-up of new containers, the calibration would not affect the start-up time. A precondition for this is, that there is an acceptable variability in CPU time across nodes. Hence, we decide to benchmark the resource demand generation library, namely ProtoCom, to determine how it performs in our cluster.

Environment and Experimentation Setup
The Kubernetes cluster consists of seven worker nodes of identical flavor m1.large with 4vCPUs, 8GB RAM and 12GB storage. On the worker nodes there are various numbers of container being deployed where some are applicationspecific and some come from the platform itself. Table 2 summarizes the number of pods per node together with some characteristic application pods. The average millicores determines the average CPU usage of the cluster when no workload is running. During the benchmark execution the three services of the application-namely, the Device Communication service, the Data Processing service, and the Data Provider service-are co-located on node minion-07.
We define as a compilation of the cluster the state after all VMs have been rebooted. We execute the benchmark with two different container QoS classes enabled: best-effort (no limit, no guaranteed share) and guaranteed (limits are equal to guaranteed share). For each class we make five executions where in each execution five measurement iterations follow after an initial five warm-up iterations 9 . The execution happens on all the seven nodes. A total of 5250 observations determine the performance of ProtoCom in a Kubernetes cluster under two different QoS classes.
To automate the benchmarking process of ProtoCom we make use of the Java Microbenchmark Harness (JMH) 10 that facilitates building, running, and analysing (micro-)benchmarks in Java. We containerised JMH and use Kubernetes OpenKruise 11 to define a BroadcastJob that will execute the benchmark on all the nodes in the cluster. We execute five times the benchmark on all nodes. In each run the benchmark initially calibrates the ProtoCom library in a MEDIUM accuracy setting. There are three different levels of accuracy one can set: LOW, MEDIUM, and HIGH. We chose MEDIUM as a compromise between accuracy and experimentation time that showed sufficient stability. After the calibration, the benchmark varies the resource demand parameter in three levels 50, 200 and 1000 milliseconds. The selection of the resource demands was motivated from the demands which we inject in the demonstrator application.

Discussion of Calibration Results
First, we compare the results for the two used Kubernetes QoS-classes and the three parameter levels. Figure 2 summarizes the overall results where the performance is highly variable and observations deviate up to 40% in both directions. This happens consistently for the different specified demands. The difference between the set container QoS class is not significant both statistically and practically. The minimal difference stems from the fact that nodes are not highly 9 In initial experiments we discovered some warm-up effects affecting the proper calibration of ProtoCom. 10 https://openjdk.java.net/projects/code-tools/jmh/ 11 https://github.com/openkruise/kruise utilized. Table 2 shows what additional load (noise) was deployed on the cluster. For the least loaded node, minion-06, variability is low and variability increases for the guaranteed case while the service might get throttled if it has exceeded its limits. For the most loaded node, minion-02, using the guaranteed class shows a positive impact, where for demand 50 the 95th percentile is much closer to the desired target; same applies for demand 1000. Besides the expected slowdown effects, we also measured several occurrences of speed-ups in our benchmark. The box plots show, that the first quartile is matching the desired execution time. Thus 75% of resource requests are taking more time to complete. Table 3 shows that for parameters 50 and 200 the 95th percentile and standard deviation is slightly lower when comparing best-effort to guaranteed Kubernetes QoS-class. For parameter value 1000 the opposite is true. Second, we compare the results of the benchmark across the nodes in the cluster. We expect to observe differences in the slowdowns due to different placement of VMs in cloud and different level of occupancy of nodes. As expected, in difference to the QoS class, the variability of the results seems to differ on different nodes. Figure 3 depicts the distribution of data points of all iterations on different nodes. The least loaded nodes-in terms of number of pods deployedexperience less variability. For estimating the reproducibility of the experiment we added an additional benchmark run (best-effort-old) that was conducted in a different cluster compilation before. Results show, though the state of the underlying cloud should have changed, that the variance measured on the nodes is similar.
To analyze the impact of individual node occupancy we calculate the correlation between number of Pods on the node, the CPU utilization in millicores and the sample coefficient of variation (CV) which is the ratio of the standard deviation and the average. In Kubernetes the utilization is measured in millicores that denotes a thousands of one vCPU, i.e. a utilization of 207.15 millicores corresponds to 5.18% for a 4 vCPU node. Figure 4 shows a moderate association between both node occupancy, measured in number of pods or millicores CPU, and the relative variability measured through the CV. To sum up, we show that the intuitive assumption that a higher node occupancy leads to higher variance in execution time during load generation holds. Moreover, even nodes with moderate average CPU utilization of less than 20% are affected by slowdowns and varying speeds. Developers should take that into account when designing performance tests and benchmarks and measure the variability in processing speeds using multiple nodes. Our simple occupancy metrics can be used as an initial indicator for potential slowdown variations, however, several other factors, like the burstiness of CPU workloads or the I/O usage, could also affect the execution.
Furthermore, these slowdown effects also impact modelbased performance prediction methods, as varying execution time must be taken into account. While developers could try to model all influencing factors on the nodes in detail, however, a better solution would be to systematically quantify and model the uncertainty in CPU speeds. Based on these information scaling policies and mechanisms can be optimized.

Scaling Policies and Mechanisms
Bondi [8] distinguishes four general types of scalability, namely load, space, space-time and structural scalability. In this work we focus only on load scalability which is the system's ability "to function gracefully, i.e., without undue delay and without unproductive resource consumption or resource contention at light, moderate, or heavy loads while making good use of available resources" ( [8]). Mircoservice.io presents commonly used deployment patterns and distinguishes between the cases of multiple service instances per host and service instance per host, VM or container [17]. AWS autoscaling supports a more VM-based scaling approach by creating collections of EC2 instances through scaling a bunch of VMs instead of spinning up containers [6]. Kubernetes supports scaling on a container level by applying a horizontal pod autoscaling approach, i.e. it assigns more resources by starting additional replicas of a pod (i.e. a container) that is already running for the current workload  replicas desired = ceil replicas current · metric current metric desired .
While this works for any available metric value, commonly an average utilization metric is used. Pods are placed on existing nodes by the k8s node-scheduler using a two-step filtering and scoring approach 12 .
Based on the chosen patterns and technology, software architects might end up with evaluating different kinds of policies. For the demonstrator application, since it is containerized and deployable in Kubernetes, it is possible to employ both service-based policies and also node-based policies. Here we describe the two different policies and the mechanisms to implement them briefly.
For the service-based autoscaling policy we rely on the Horizontal Pod Autoscaler (HPA) [5] to define a separate scaling policy for the three different services that constitute the demonstrator application. When fully characterizing the services, various metrics could be used in the configuration of the HPA.
For the node-based autoscaling policy, we design and implement a controller that replicates Kubernetes nodes and proportionally scales the pods of the three services deployed on the cluster similar to the cluster proportional autoscaler of Kubernetes [2]. A scale out (in) decision occurs whenever the average utilization of available nodes surpasses an upper threshold (falls behind a lower threshold). The number of replicas for each service follows the number of available nodes. For example, if there are two nodes available in the cluster there will be 2 replicas for each of the services. The initial state constitutes one node whereas there may be up to four nodes where the demonstrator can be allocated. Other nodes are reserved for different services and experimentation tools.

Algorithm 1 Node-based Autoscaling of Services
Require: , The two different policies lead to different cluster compilations over time. In the next section we explore the scalability boundaries of the demonstrator when assuming a nodebased autoscaling policy. This allows us to design meaningful scenarios for the elasticity experiments and later evaluate various autoscaling policies including the described ones.

Scalability Assessment as a Prerequisite of
Designing Elasticity Scenarios Several proposals exist in literature to asses the scalability of applications, e.g., [11]. The main purpose of assessing the scalability in our case is to estimate the processing limits of the application and use this information for designing elasticity experiments. To determine whether a configuration can handle a certain load (in terms of devices) we observe the performance and the utilization of the system. We follow a binary search procedure [20] to reach faster the upper bound on the number of devices that a particular configuration can handle without violating a given performance service level objective (SLO). For the remote measuring use case, we define the target SLO to be one second response time for the 95th percentile during a constant load of active devices. Since we lack data for workload characterization for the reference application, we generate synthetic load using Gatling that stresses the application in two configurations: the initial configuration where the demonstrator is deployed on one node and the final configuration where the demonstrator is deployed on four nodes.
As Figure 5 depicts, the demonstrator application is able to scale with additional resources i.e., when such resources are provided by means of VM replication and scaling proportionally the corresponding pods. One data point in the plot shows the 95th percentile of response time for requests that have been generated by the active devices given on the x-axis. The red dashed line shows the SLO boundary of 1000ms that should not be violated. The synthetic workload influences response times through the number of concurrent users (devices), how fast they ramp-up, and the sleep value. The combination of the time to ramp up (5 seconds), the frequency of sending data (60 seconds) and the number of devices together with the intrinsic randomness of the workload generation tool and setup leads to different distributions of inter-arrival times for requests. As the highlighted data point in the scaled part depicts that spawning 2000 devices in 5 seconds in one case leads to the violation of the SLOs while the configuration is able to sustain higher number of devices-and up to a maximum of 5000 in one observationwhen the devices are increased gradually.
Initial experiments allow us to estimate the performance boundaries of the application when assuming a node-based scaling policy for the initial and the most scaled configuration that may occur. However, when employing a servicebased policy, although the initial configuration might be  Figure 5. The 95th percentile of response time of the initial and scaled cluster compilation for synthetic generated load assuming that the application scales using a node-based autoscaling policy. assumed similar, the most scaled configuration is not easily derived upfront. However, the approximated processing capabilities are used for designing scenarios for elasticity experiments in which both alternatives for autoscaling policies could be evaluated.

Conclusions and Future Work
Existing reference applications for experimenting and research are not representative for data-intensive containerized cloud applications. They are serving more traditional use cases of human-centered request-reply communication without a continuous data processing pipeline and without using asynchronous messaging for the communication.
In attempt to fill this gap, in this work we present a reference use case coupled with the initial architecture design and with the engineering challenges for elasticity and resilience. To make the reference application suitable for research of elasticity and resilience mechanisms through increasing the predictability in performance, we have experimented with the CPU load generation tool ProtoCom. Results show a high variability in execution time when generating load for a given time demand. We observe a moderate association between node occupancy and the relative variability. In addition, we sketch how the application could be scaled through two different autoscaling policies and investigate the scalability of the solution assuming a node-based approach.
In the future we plan to investigate further on the performance influences of using different QoS classes for containers. Moreover, we will perform additional experiments using container quotas and CPU throttling. Consolidating and publishing the reference application including the evaluation of elasticity and resilience scenarios is another item for future work. In parallel we have started to construct a performance model of the application that will allow the evaluation of architecture alternatives. Moreover, we created initial simulation models to emulate the QoS-based shared CPU scheduling regime used in Kubernetes and alike. In the long run, we want to optimize scalability and resilience for dynamic cloud applications by incorporating models of uncertain execution environments [19] into simulation-based prediction techniques.