Skip to content

Latest commit

 

History

History
121 lines (88 loc) · 11.2 KB

web-serving.md

File metadata and controls

121 lines (88 loc) · 11.2 KB

Web Serving

Pulls on DockerHub Stars on DockerHub

Web Serving is a primary service in the cloud. Traditional web services with dynamic and static content are moved into the cloud to provide fault tolerance and dynamic scalability by bringing up the required number of servers behind a load balancer. Although cloud services use many variants of the traditional web stack (e.g., substituting Apache with other web server software or using other language interpreters instead of PHP), the underlying service architecture remains unchanged. A stateless web server process accepts independent client requests. In response, the web server either directly serves static files from disk or passes the request to a stateless middleware script, written in a high-level interpreted or byte-code compiled language, which is then responsible for producing dynamic content. The middleware stores all the state information in backend databases such as cloud NoSQL data stores or traditional relational SQL servers supported by key-value cache servers to achieve high throughput and low latency. This benchmark includes a social networking engine (Elgg), and a client implemented using the Faban workload generator. This benchmark version is compatible with Php 8.1, which supports JIT execution and thus improves the workload's throughput.

Using the benchmark

The benchmark has four tiers: web server, database server, Memcached server, and clients. The web server runs Elgg and connects to the Memcached and database servers. The clients request to log in to the social network and perform various operations, such as sending and reading messages, adding or removing friends, posting blogs, and adding comments or likes to different posts. Each tier has its own image, identified by its tag.

Dockerfiles

Supported tags and their respective Dockerfile links:

  • web_server contains the application code and the web frontend PHP engine.
  • memcached_server contains the Memcached server as the caching layer.
  • db_server contains the MariaDB database.
  • faban_client contains the load generator based on Faban.

These images are automatically built using the mentioned Dockerfiles available on the parsa-epfl/cloudsuite GitHub repo.

IP Addresses

Please note that all IP addresses should refer to the explicit IP address of the host server running each container.

Starting the database server

The following command will start the database server:

$ docker run -it --net=host --name=database_server cloudsuite/web-serving:db_server

The database is pre-populated with around 100 K users and their data, such as their friends list and sent messages. The initial size of the database is around 2.5 GB. Based on your need, you can increase the database size by running the benchmark for some time and inspecting whether the database size has reached your desired number.

Starting the Memcached server

The following command will start the Memcached server:

$ docker run -dt --net=host --name=memcache_server cloudsuite/web-serving:memcached_server

By default, the Memcached server has 4 threads and 64GB buffer size.

Starting the web server

To run the web server, use the following command:

$ docker run -dt --net=host --name=web_server cloudsuite/web-serving:web_server /etc/bootstrap.sh ${PROTOCOL} ${WEB_SERVER_IP} ${DATABASE_SERVER_IP} ${MEMCACHED_SERVER_IP} ${MAX_PM_CHILDREN} ${WORKER_PROCESS}

The PROTOCOL parameter can either be http or https and determines the web server's protocol. The WEB_SERVER_IP, DATABASE_SERVER_IP, and MEMCACHED_SERVER_IP parameters refer to the explicit IP of the host server running the corresponding container. The MAX_PM_CHILDREN parameter sets the pm.max_children in the php-fpm setting, which controls the number of threads in PHP's thread pool. The default value is 4, and we recommend setting 4 per core to avoid frequent thread switching while still hiding I/O latency. The WORKER_PROCESS parameter specifies the number of Nginx worker processes. The default is auto. We recommend having 1 Nginx worker process per 32 cores.

To check whether the web server is up, you can access Elgg's home page through a web browser at http://<web_server's IP>:8080 or https://<web_server's IP>:8443 URLs for HTTP and HTTPS web servers, respectively. For example, Elgg's home page is shown in the figure below:

image

You may see different content based on the latest recorded activities in the database. You can log in as the service administrator using admin as the username and adminadmin as the password in the log in menu. Then, you will have access to the administration dashboard, where you can modify different settings based on your need.

You can find the list of usernames and passwords of regular users in this file. You can log in as a normal user and see various services and features available for an Elgg user. It will help you better understand how the benchmark's client container works.

Running the benchmark

To start the client container which runs the benchmark, use the following commands:

$ docker run --net=host --name=faban_client cloudsuite/web-serving:faban_client ${WEB_SERVER_IP} ${LOAD_SCALE}

The command has a mandatory parameter WEB_SERVER_IP to set the IP of the web server and an optional parameter LOAD_SCALE to specify the load scale (default is 1). The LOAD_SCALE parameter controls the number of users that log in to the web server and request social networking pages. You can scale it up and down as much as you would like, considering that scaling the number of users may stress the system. To tune the benchmark, we recommend testing your machines for the maximum possible request throughput while maintaining your target Quality of Service (QoS) metric (we use 99 percentile latency). CPU utilization is less important than the latency and responsiveness for these benchmarks.

The client container offers multiple options to control how the benchmark runs. The list of available options is as follows:

  • --oper=<usergen | run | usergen&run>: This option has three possible values: usergen, run, and usergen&run. In usergen, the benchmark only creates new users and adds them to the database. LOAD_SCALE determines the number of generated users. On the other hand, run does not generate new users but starts the benchmark by logging in the users to interact with the server by sending various requests. Note that the pre-populated database container holds ~100K users. Therefore, you can start running the benchmark without needing to generate new users. Finally, usergen&run does what previous operations do together. The default value is usergen&run.
  • --ramp-up=<# of seconds>: the number of seconds the benchmark spends in the ramp-up phase. Remember that there is a one-second interval between the users' log in requests. Therefore, please set the ramp-up time to a value larger than LOAD_SCALE to ensure the number of active users in the steady state matches your given number. The default value is 10.
  • --ramp-down=<# of seconds>: the number of seconds the benchmark spends in the ramp-down phase. The default value is 10.
  • --steady=<# of seconds>: the number of seconds the benchmark spends in the steady-state phase where all users are logged in and interacting with the server. The default value is 30.
  • --min=<# of seconds>: the minimum number of milliseconds between consecutive requests of a specific user. The default value is 1000.
  • --max=<# of seconds>: the maximum number of milliseconds between consecutive requests of a specific user. The default value is 1500.
  • --type=<THINKTIME | CYCLETIME>: This option has two possible values: THINKTIME and CYCLETIME. For the former value, the latency before sending a new request (determined by --min and --max) is measured relative to when the last request finishes. On the other hand, the CYCLETIME policy calculates the latency from the moment a request is sent to the server. The default value is THINKTIME.
  • --dist=<fixed | uniform | negexp>: This option controls the distribution of values chosen for the inter-request latencies between --min and --max. You can give three possible values to this option: fixed, uniform, and negexp (that refers to negative exponential distribution). The default value is fixed.
  • --encryption=<1 | 0>: The client container can send the request to a TLS-encrypted server by setting this option to 1. The default value is 0, which means the client sends HTTP requests. This value should be adjusted according to the PROTOCOL parameter you set when setting up the server.

The client container will output the summary of the benchmark results in XML format after the benchmark finishes. You can also access the summary and logs of the run by mounting the /faban/output directory of the container in the host filesystem (e.g., -v /host/path:/faban/output).

Possible User Operations

Elgg provides different features for the users. The client image implements a subset of the available features. The main driver of the client image is in this file. You can enrich the list of requests that the client driver supports by modifying the mentioned file. The current version supports the following requests:

  • Browse the home page
  • Browse recent activities in the site
  • Browse a user's profile
  • Log in as a user
  • Register a new user
  • Log out a user
  • Add a friend
  • Remove a friend
  • Browse the friends list
  • Check notifications
  • Post a wire (A wire is similar to a tweet or a status update)
  • Browse the wires page
  • Reply to a wire
  • Like a wire
  • Browse the inbox
  • Send a message
  • Read a message
  • Delete a message
  • Browse sent messages
  • Browse the blogs page
  • Post a blog
  • Like a blog post
  • Comment on a blog
  • Search for a site member