联系方式

  • QQ:99515681
  • 邮箱:99515681@qq.com
  • 工作时间:8:00-21:00
  • 微信:codinghelp

您当前位置:首页 >> C/C++编程C/C++编程

日期:2024-03-13 10:35

Page 1 of 12

TCSS 558: Applied Distributed Computing School of Engineering and Technology

Assignment 3

Version 0.10

Replicated Key Value Store

Due Date: Sunday March 10

th, 2024 @ 11:59 pm, tentative

Objective

The purpose of assignment 3 is to extend your TCP client/server key-value store to support replication

and node discovery. Replication can be implemented using a two-phase-commit algorithm.

Two-Phase Commit Algorithm

Any TCP server receiving a client request to put or delete a node becomes the leader of the transaction.

Every TCP server maintains an active copy of the node membership directory. Upon receiving a put or

delete request the receiving node becomes the leader and sends a round of dput1/ddel1 requests to

every TCP server in the membership directory to request the put or delete of the key/value pair. Each

node checks if the key in question is presently locked. If the key is available, the TCP server responds

with an acknowledgement to the leader indicating that it is able to proceed with the transaction. At this

time the node will also “lock” the key from other updates. If the leader receives acknowledgements

from ALL known servers, then a second dput2/ddel2 command is sent to all nodes to commit the data.

If nodes receive the dput2/ddel2, they proceed with the operation locally and unlock the key. If any one

node responds to the leader with an abort message (because the key is locked) the entire transaction is

aborted. At this point the leader will retry the transaction up to a fixed number of times, let’s say 10. If

the transaction cannot be committed after 10 attempts, it is aborted, and an error message is produced.

Using program code developed for assignment 1, extend “GenericNode” to support additional “internal”

commands described in the table to support two-phase commit. Your TCP Server will now leverage your

TCP client code for the purpose of sending internal commands to the server nodes. The operations

below represent an application-level protocol for a replicated key-value store. You are welcome to

implement a custom protocol (and replication algorithm) if desired, but you will be required to submit

summary documentation (as a PDF file) describing your protocol in a similar format as in the table.

The following assumptions can be made:

• Nodes will NOT fail during transactions.

• Only write transactions (put / delete) need to be synchronized.

• Each node should maintain data for in-progress transactions to a concurrent data structure. You

do not have to implement your own from scratch.

• Only one operation on a given key can be performed across the nodes concurrently. Attempts

to perform multiple parallel operations on the same key will be aborted by any node detecting

conflicts.

Page 2 of 12

Replicated Key-Value Store Application Protocol

Operation Description

dput1 dput1 <key> <value>

Called by the transaction leader, dput1 starts an internal node-to-node transaction

to replicate the key/value pair at a remote node. Upon receiving this command the

local node locks the key/value pair and sends an acknowledgement message to the

leader indicating it is ready to proceed to commit the PUT operation. If the

key/value pair is already locked locally, then an abort message is sent to the leader

and the transaction will be aborted.

dput2 dput2 <key> <value>

Called by the transaction leader, dput2 finishes an internal node-to-node

transaction to put the key/value pair at a remote node. Upon receiving this

command the local node performs the “put” operation on its local datastore. After

the key is put, the key/value pair is unlocked enabling other updates to be

performed by other nodes in the replicated key/value store.

The node responding to dput2 will respond with a message equivalent to the put

message from assignment 1.

dputabort dputabort <key> <value>

Called by the transaction leader, dputabort aborts an internal node-to-node

transaction across the replicated key-value store. Transactions are aborted by the

leader if at least one node sent an abort message as a result of dput1. Upon

receiving the dputabort, the local node removes the lock from the local key/value

store.

ddel1 ddel1 <key>

Called by the transaction leader, ddel1 begins a replicated delete operation across

the nodes of the replicated key/value store. Locking and messaging follow the

same scheme as for dput1.

ddel2 ddel2 <key>

Called by the transaction leader, ddel2 finishes a replicated delete operation across

the nodes of the replicated key/value store. Locking and messaging follow the

same scheme as for dput2.

The node responding to ddel2 will respond with a message equivalent to the del

message from assignment 1.

ddelabort ddelabort <key> <value>

Called by the transaction leader, ddelabort aborts an internal node-to-node

transaction across the replicated key-value store. Transactions are aborted by the

leader if at least one node sent an abort message as a result of ddel1. Upon

receiving ddelabort the local node removes the lock from the local key/value store.

To support a replicated key-value store it is necessary to track node membership in the distributed

system to determine the set of nodes across which data will be replicated.

Page 3 of 12

Three membership tracking methods are available. Students must implement at least one membership

tracking method. Extra credit is available for implementing method #2 and/or method #3.

Node Membership Tracking Methods

Method Description

1. Config file The simplest approach to manage membership is to provide a static configuration text file with

IP:PORT pairs for all nodes participating in the replicated key-value store. When the

GenericNode is deployed using separate docker containers, a static configuration file must be

updated and pushed out to each of the containers. The file should be called

“/tmp/nodes.cfg”. GenericNode should periodically reload this file every few seconds to

constantly refresh the view of the system. The format of the file should be a simple list with

each node (IP/PORT) represented on a separate line as follows:

10.0.0.5:1234

10.0.0.4:1234

10.0.0.3:1234

As a proof of successful distributed deployment, capture and provide execution times for the

bigtest_tc.sh script on a 3-container deployment.

2. UDP Discovery An alternate approach is to manage membership dynamically by having the server discover

nodes via a UDP broadcast protocol. For this approach, devise a simple protocol where nodes

periodically send broadcast messages to each other via UDP, and each node accumulates a

complete membership list based on received broadcast messages. If a node is not heard from

after 10 seconds, it can be removed from the system. Broadcast should occur using a fixed

port, such as #4410.

Using UDP discovery, it should be possible to launch multiple docker containers on a single

docker host and they will self-discover their existence and begin to collectively replicate all

transactional data.

As a proof of successful deployment, capture and provide execution times for the bigtest_tc.sh

script on single docker host deployments of 1, 3, and 5 containers.

Special limitation: Note, Docker overlay networks presently do not natively support UDP

broadcast across multiple hosts. This invalidates this approach for automatic discovery of

nodes deployed across separate Docker host machines.

See Docker UDP Broadcast Overlay Bug:

https://github.com/docker/libnetwork/issues/552

3. Centralized

membership

key/value store

For approach 3, deploy a centralized, non-replicated instance of your own TCP key value server

from assignment #1, to track node membership. Keys will be IP addresses. Values will be

ports. The “store” command will list all participating nodes.

Add command line arguments to your TCP server startup to enable a centralized key/value

store IP to be passed in for tracking node membership:

New TCP server startup CLI:

java -jar GenericNode.jar ts <listen-port> <membership-server-IP>

You may use a HARD CODED port for the membership server, for example port 4410. To

Page 4 of 12

deploy, first launch an instance of the TCP key-value store as a membership directory to listen

on a special port (e.g. 4410). This can be deployed using a separate docker container called

“nodedirectory”. Once launching the node directory kvstore, check it’s IP address, and launch

all subsequent keyvalue stores by referring to the membership-server IP address.

OPTIONAL

This assignment can optionally be tested by deploying a multi-node KV store across multiple

host VMs using Docker Swarm are provided here:

http://faculty.washington.edu/wlloyd/courses/tcss558/assignments/a2/DockerSwarmOverlayhowto.txt

When your TCP server starts, it will send a TCP client command to publish its own IP/PORT to

the centralized server, and then periodically request the complete list of servers every few

seconds.

As a docker exercise, scripts will be provided to deploy your replicated key-value store as a

service across multiple docker hosts. Your centralized membership server will be deployed as

a secondary service to a single docker host. The membership server will be deployed first and

its IP/PORT can then be statically defined in the runserver.sh script of the docker container for

your replicated key-value store.

This implementation will enable your key-value store to scale across multiple virtual machines

and containers on AWS.

As a proof of successful deployment, capture and provide execution times for the bigtest_tc.sh

script docker service deployments using 5, and 10 containers deployed across a Docker swarm

consisting of 3 and 5 docker host machines.

Students who submit a working, replicated TCP GenericNode server, and performance comparison

supporting both UDP (#2), and the Centralized TCP Membership tracking server (#3) without significant

errors will be eligible for up to 20% extra credit.

The preferred implementation for assignment #2 is in Java 11. Students are free to implement

assignment #2 in C, C++, or Python if preferred. Solutions in alternate languages must include

documentation to describe how to operate the client and server in the alternate language. All

operations including setup must be explained. Components must be deployed using server and client

docker containers.

*** Important Note About the ‘store’ command for Assignment 3 ***

For Assignment 3, it is required for the ‘store’ command from Assignment 2 that the output be in ASCII

text. Binary output is not permitted. In addition, each key-value pair must appear on a separate line. If

the store command produces unreadable or grouped output, the assignment may be graded as nonworking because it is not reasonable to evaluate and compare the contents of your key-value store after

several operations.

Page 5 of 12

Docker for Assignment #2

All solutions must include a Server Dockerfile to support creating server containers. Servers must be

able to communicate on the local subnetwork shared among containers of a single Docker host, or

shared among multiple containers across a Docker overlay network. The client container will use the

docker container private network IP address to facilitate communication with the server.

To support working with Docker containers, Dockerfiles for the client and server have been provided

and can be downloaded here: (feel free to use these, or develop new Dockerfiles...)

http://faculty.washington.edu/wlloyd/courses/tcss558/assignments/a1/a1_dockerfiles.tar.gz

To extract a tar gzip file use the command: (x for extract, z for unzip, f for file)

tar xzf a1_dockerfiles.tar.gz

Then cd into the individual docker_server or docker_client directories to build the docker images.

The sample dockerfiles includes a placeholder GenericNode.jar Java class archive file. For assignment

#2, you’re to focus on extending the GenericNode.jar TCP server.

Inside the docker_server directory, a runserver.sh script has been provided.

This script includes a command to start a server of one of the given types.

When building your docker_server container, you should uncomment the TCP server by removing the

“#”:

# Dummy jar file

#java -jar GenericNode.jar

#TCP Server – centralized node directory if used

#java -jar GenericNode.jar ts 4410

#TCP Server – KV store

java -jar GenericNode.jar ts 1234 <IP of node directory if used>

Once running, to discover the internal IP address of your server running on a Docker host, use the

following sequence:

First, build the docker_server container:

$ cd docker_server

$ sudo docker build -t tcss558server .

Sending build context to Docker daemon 5.12kB

Step 1/7 : FROM ubuntu

---> ccc7a11d65b1

Step 2/7 : RUN apt-get update

---> Using cache

---> 1413c1a1f91b

Step 3/7 : RUN apt-get install -y default-jre

Page 6 of 12

---> Using cache

---> b23e154d7af3

Step 4/7 : RUN apt-get install -y net-tools

---> Using cache

---> 1d81d5652fc2

Step 5/7 : COPY GenericNode.jar /

---> Using cache

---> f74d73c86c5c

Step 6/7 : COPY runserver.sh /

---> Using cache

---> f23167bd7d09

Step 7/7 : ENTRYPOINT /runserver.sh

---> Using cache

---> e921fbb5db7a

Successfully built e921fbb5db7a

Successfully tagged tcss558server:latest

Then, run the docker container:

$ sudo docker run -d --rm tcss558server

1ad8abcb16cae530322464099487d028154a2452072e5e20f6007ff3e5f1a66d

Now, grab (copy and paste) your unique CONTAINER ID. The Name can also be used (here distracted

hodgkin):

Next, execute bash interactively on this container

$ sudo docker exec -it 1ad8abcb16ca bash

Then, use the “ifconfig” command inside the container to query the local IP address:

root@1ad8abcb16ca:/# ifconfig

eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:02

inet addr:172.17.0.2 Bcast:0.0.0.0 Mask:255.255.0.0

UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

RX packets:48 errors:0 dropped:0 overruns:0 frame:0

TX packets:0 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:0

RX bytes:6527 (6.5 KB) TX bytes:0 (0.0 B)

It is recommended to develop your code on a local machine, and test the deployments to Docker

containers before submitting.

(OPTIONAL) Docker Swarm:

A how-to document is posted here:

Page 7 of 12

http://faculty.washington.edu/wlloyd/courses/tcss558/assignments/a2/DockerSwarmOverlayhowto.txt

The document includes instructions for configuring Docker Swarm using multiple docker-machine hosts

and deploying your TCP server as a docker service. Once setting up Docker Swarm, an overlay network

can be configured to support TCP communication on a private network, or, servers can communicate

using AWS public IP addresses.

Running multiple TCP node servers:

TCP servers support the same syntax from Assignment #1, except now multiple nodes can be run in

parallel.

#TCP Server (ts for TCP server – for #3 centralized membership key-value store:

java -jar GenericNode.jar ts <server port number> <membership-server-IP>

<membership-server-port>

#Example:

java -jar GenericNode.jar ts 1234 54.12.44.33 1111

For Assignment #1, you may optionally have your servers output debugging information. But there are

no formal output requirements for servers to generate output either to the console or to logfile(s).

Testing the servers

Once the IP address of the server is discovered, point your client to this IP address and include the port

number for TCP to support client/server interaction.

Get, put, delete, store, and exit commands should be supported as in assignment #1:

TCP CLIENT TO SERVER INTERACTION

The first parameter is “tc” for TCP client.

The second parameter is the server IP address.

The third parameter is the server port.

Replace localhost with your server IP address.

“1234” represents the service port. The client and server allow the port number to be specified.

Replace with the port used.

$ java -jar GenericNode.jar tc localhost 1234 put a 123

server response:put key=a

$ java -jar GenericNode.jar tc localhost 1234 put b 456

server response:put key=b

$ java -jar GenericNode.jar tc localhost 1234 get a

server response:get key=a get val=123

Page 8 of 12

$ java -jar GenericNode.jar tc localhost 1234 del a

server response:delete key=a

$ java -jar GenericNode.jar tc localhost 1234 store

server response:

key:b:value:456:

$ java -jar GenericNode.jar tc localhost 1234 exit

<the server then exits>

TCP / UDP References

These may be helpful:

https://systembash.com/a-simple-java-tcp-server-and-tcp-client/

https://docs.oracle.com/javase/tutorial/networking/sockets/index.html

https://docs.oracle.com/javase/tutorial/networking/datagrams/clientServer.html

Two Phase Commit Protocol References

The internet will contain helpful references. We will discuss also in class. See book chapter 8.5 as well.

Suggested Integrated Development Environment (IDE) / Project Build Files

For maximum potential for partial credit, students may submit their project as a Netbeans project

created with the Netbeans IDE, Oracle’s Java IDE. By providing projects as a Netbeans project, it will be

possible for the grader to build your source and fix potential issues to support partial credit. For

example, a student may nearly have the code correct, but a small detail prevents operation. If the

grader can rapidly fix the code, a lot of partial credit may be awarded.

Download Netbeans here:

https://netbeans.org/downloads/

Alternatively, students not using Netbeans may submit all requisite project build files, as well as

descriptive documentation which clearly states how code can be rebuilt. If the grader is easily able to

rebuild your projects, then there is higher potential for partial credit.

If no build files are provided, and/or no subsequent documentation describing how to build your

projects, it will not be possible to issue partial credit for functionality that is nearly complete with

minor bugs. In this case, only by reading the code will the grader attempt to issue partial credit if

portions of the program do not work correctly.

Testing Function and Performance

A TCP test script is online at:

TCP:

http://faculty.washington.edu/wlloyd/courses/tcss558/assignments/a1/bigtest_tc.sh

Page 9 of 12

To run the scripts, adjust the server and port BASH variables as needed to test your

deployments. When data is loaded to a single node, it should be automatically replicated at all

other nodes in the system. Running the script against different nodes is a good way to test that

transactions to every node are replicated.

Check that each server node has replicated the same contents of the script by counting the

number of lines returned from by the store command at the conclusion of the test script:

$java -jar GenericNode.jar tc localhost 1234 store | wc -l

Assuming no blank lines, the count should be 70. Also textual diffs can be performed of the

outputs.

To measure performance of TCP, run the script as follows:

#TCP

time ../bigtest_tc.sh > /dev/null

With your submission, please create a PDF file created with Google Docs.

Include in the file performance numbers obtained for your multi-container / multi-host

deployments coinciding with your membership tracking approach (static file, UDP discovery,

centralized TCP key/value store) as described in the table while running the test script

bigtest_tc.sh.

Please test a 1-node, 3-node, and 5-node deployment. Please include performance numbers

in a PDF file. Please label each configuration with the node directory type (Static File, UDP

Discovery, or TCP Discovery), and the number of server nodes tested so the performance of

each is quick to identify and the configure you used is easy to see as follows:

# Assignment 3, Static File, 1 Container TCP

TCP 17.513s

# Assignment 3, Static File, 3 Container TCP

TCP 22.143s

# Assignment 3, Static File, 5 Container TCP

TCP 94.233s

Note the example times here are bogus.

What to Submit

To submit the assignment, teams should build a single tar gzip archive file that contains all project

source code in a main project directory. Java implementations should provide a working Maven build

(e.g. pom.xml) as in assignment #1. In the project directory there should be two directories for the

Page 10 of 12

Docker containers: docker_server and docker_client. The folders must be updated to include your

GenericNode.jar file to enable building a functioning TCP server container.

PDF files with performance results should be submitted as a separate file in Canvas.

All submissions must include a readme.txt file that is included inside the tar gzip archive.

The readme.txt file should describe the: (1) programming language and version, and (2) integrated

development environment (IDE) or editor used to develop the project. The readme.txt should provide

instructions for building/running the project if your program is not a Java/Maven implementation. It is

especially important that Python implementation included detailed usage instructions with examples.

The readme.txt file should provide examples that demonstrate how to launch a server, and how to use a

client to put/get data. Clients and servers should be designed to operate on the test scripts provided

online. Binary files included in the tar gzip archive are deleted and not used for testing.

All membership tracking methods that should be tested for credit must be identified in the readme.txt

file. Any membership tracking methods not documented will not be tested.

To identify membership tracking methods, use codes from the table:

CODES TO IDENTIFY MEMBERSHIP TRACKING METHODS

>> please indicate which types to test <<

ID Description

F Static file membership tracking – file is not reread

FD Static file membership tracking DYNAMIC - file is periodically reread to refresh membership list

T TCP membership tracking – servers are configured to refer to central membership server

U UDP membership tracking - automatically discovers nodes with no configuration

Grading Rubric

This assignment will be scored out of 100 points, while as many as 120 points are possible.

Functionality 70 points

10 points TCP client/server 2-node put replication

3 points TCP client/server 3-node put replication

2 points TCP client/server 5-node put replication

10 points TCP client/server 2-node del replication

3 point TCP client/server 3-node del replication

2 points TCP client/server 5-node del replication

20 points Implementation of one membership tracking system:

Can be:

(1) static node membership file (e.g. nodelist)

(2) TCP centralized membership server

(3) UDP centralized membership server

Instructions should be provided on how to make node

discovery work if not obvious.

5 points Membership tracking system is dynamic – nodes can join

and leave the system, and configuration is updated. But

there is no requirement to bring KV store up to date as in

the RAFT consensus protocol.

Must indicate in documentation that this feature has been

implemented.

Page 11 of 12

10 points Implementation of a second membership tracking system

Can be:

(1) static node membership file (e.g. nodelist)

(2) TCP centralized membership server

(3) UDP centralized membership server

Instructions must be provided on how to make the second

method of node discovery work if not obvious.

5 points Implementation of UDP broadcast membership server

For UDP broadcast, there should be no configuration (e.g.

IP) Node discovery is accomplished entirely with UDP

broadcast messages. No IPs are provided, and

configuration is automatic on a single docker host.

Must indicate in documentation that this feature has been

implemented.

Miscellaneous 50 points

10 points Use of multiple server threads

10 points Healthy synchronization, concurrency, locking, etc.

10 points Performance measurement of multi-node deployments

5 points Docker container scripts

5 points Replication protocol style

5 points Membership protocol style

5 points Program compiles, instructions provided or Netbeans used

Teams (strongly encouraged)

Optionally, this programming assignment can be completed with two or three person teams.

If choosing to work in teams, only one person should submit the team’s tar gzip project source archive

file and the performance report PDF file to Canvas.

Additionally, EVERY team member should submit an effort report on team participation. Effort reports

are submitted INDEPENDENTLY and in confidence (i.e. not shared) by each team member.

Effort reports are not used to directly numerically weight assignment grades.

Effort reports should be submitted as a PDF file named: “effort_report.pdf”. Google Docs and recent

versions of MS Word provide the ability to save or export a document in PDF format.

For assignment 3, the effort report should consist of a one-third to one-half page narrative description

describing how the team members worked together to complete the assignment. The description

should include the following:

1. Describe the key contributions made by each team member.

2. Describe how working together was beneficial for completing the assignment.

3. Comment on disadvantages and/or challenges for working together on the assignment. This

could be anything from group dynamics, to commute challenges, to faulty technology.

4. At the bottom of the write-up provide an effort ranking from 0 to 100 for each team member.

Distribute a total of 100 points among both team members. Identify team members using first

and last name. For example:

Page 12 of 12

John Doe

Research 65

Design 42

Coding 30

Testing 80

Jane Smith

Research 35

Design 58

Coding 70

Testing 20

Team members may not share their effort reports, but should submit them independently in Canvas as

a PDF file. Failure of any team members to submit an effort report will result in all team members

receiving NO GRADE on the assignment…

Disclaimer regarding pair programming:

The purpose of TCSS 558 is for everyone to gain experience developing and working with distributed systems

and requisite compute infrastructure. Pair programming is provided as an opportunity to harness teamwork

to tackle programming challenges. But this does not mean that teams consist of one champion programmer,

and a second observer simply watching the champion! The tasks and challenges should be shared as equally

as possible.

DOCKER Hints…

# Docker build

sudo docker build -t tcss558server .

sudo docker build -t tcss558client .

# Run docker container in the background

sudo docker run -d --rm tcss558server

sudo docker run -d --rm tcss558client

# Docker shell to a container

sudo docker exec -it <container-id> bash

To display all containers running on a given docker node:

docker ps -a

To stop a container:

docker stop <container-id>

For example:

docker stop cd5a89bb7a98

Also docker kill will kill a running container and docker rm will remove a container which has

exited but is no longer running.

Document History:

v.10 Initial version


版权所有:编程辅导网 2021 All Rights Reserved 联系方式:QQ:99515681 微信:codinghelp 电子信箱:99515681@qq.com
免责声明:本站部分内容从网络整理而来,只供参考!如有版权问题可联系本站删除。 站长地图

python代写
微信客服:codinghelp