CS6650 Building Scalable Distributed Systems
Write a Java multithreaded programs that
Run the program with a variable number of threads (e.g.1,10k etc) and see if you can observe any relationship between number of threads and total run time?
Write a Java program that uses a single thread to add a lot of elements (100k?) to a:
Time how long each test takes to quantify the overheads of synchronization.
Write a Java program that uses a single thread to add a lot of elements (100k?) to a:
You will have to make access to the HashMap threadsafe using Collections.synchronizedMap.
You aim is to write a multithreaded program that writes information to a test file as fast as possible.
Start by creating a Java program that opens a text file for writing.
Then create 500 threads and in each thread generate 1000 strings of the format: “timestamp, Thread-id, N”
where:
Your aim to to store all these generated strings from all threads into the same file as quickly as possible. The order they are written to the file is initially unimportant.
Time how long the program takes by taking a timestamp immediately before creating any threads and another when all threads are completed and the file is written and closed.
Approaches you can experiment with are along the lines of:
Implement two or more of these approaches and compare the wall time for the program.
What insights do you take away from this exercise?
Extensions:
First, make sure you are using the latest version of IntelliJ. Old versions seem to have build problems
GroupId
, ArtifactId
, Version
and click Next
This will create a simple web application structure in your project
The API we’ll work from is on Swagger. We’ll just work on the POST and GET for /skiers, not the full API.
Add Servlet dependency to your pom.xml (use your own groupId
and artifactId
)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cs6650-lab</groupId>
<artifactId>cs6650-lab</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
Right click src/main/java
directory, point to New and click Create New Servlet.
doGet
and doPost
methodsjava
directory is marked as sources root, which should be done by defaultCreate servlet mapping in web.xml by adding code below inside the web-app
tag
<servlet>
<servlet-name>SkierServlet</servlet-name>
<servlet-class>SkierServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SkierServlet</servlet-name>
<url-pattern>/skiers/*</url-pattern>
</servlet-mapping>
Add doGet
and doPost
methods to handle GET
/POST
requests matching /skiers/*
which is the url patterns you specified in <servlet-mapping>
tag in web.xml
shown above. You can use the code below as your starting point.
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
res.setContentType("text/plain");
String urlPath = req.getPathInfo();
// check we have a URL!
if (urlPath == null || urlPath.isEmpty()) {
res.setStatus(HttpServletResponse.SC_NOT_FOUND);
res.getWriter().write("missing paramterers");
return;
}
String[] urlParts = urlPath.split("/");
// and now validate url path and return the response status code
// (and maybe also some value if input is valid)
if (!isUrlValid(urlParts)) {
res.setStatus(HttpServletResponse.SC_NOT_FOUND);
} else {
res.setStatus(HttpServletResponse.SC_OK);
// do any sophisticated processing with urlParts which contains all the url params
// TODO: process url params in `urlParts`
res.getWriter().write("It works!");
}
}
private boolean isUrlValid(String[] urlPath) {
// TODO: validate the request url path according to the API spec
// urlPath = "/1/seasons/2019/day/1/skier/123"
// urlParts = [, 1, seasons, 2019, day, 1, skier, 123]
return true;
}
You can use similar URL validation approach for doPost
.
Additionally, according to the API spec, the POST
method to the same URL accepts a JSON request body. We can parse that information with req.getReader()
which returns a BufferedReader
, which can be easily converted to a String for further JSON processing.
This step is optional but highly recommended. By doing so, we can make sure our servlets fully work in our local Tomcat server before we are confident enough to deploy it to the server in EC2. You can also set breakpoints in doGet/doPost methods, and the debugger will be triggered once the corresponding request comes.
Important:
When that’s done, if you run Tomcat server inside IntelliJ, you should see console output similar to this.
......
......
......
16-Sep-2019 03:42:06.991 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-8080"]
16-Sep-2019 03:42:07.085 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["ajp-nio-8009"]
16-Sep-2019 03:42:07.099 INFO [main] org.apache.catalina.startup.Catalina.load Server initialization in [682] milliseconds
16-Sep-2019 03:42:07.242 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina]
16-Sep-2019 03:42:07.243 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet engine: [Apache Tomcat/9.0.24]
16-Sep-2019 03:42:07.271 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
16-Sep-2019 03:42:07.326 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-8009"]
16-Sep-2019 03:42:07.366 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [266] milliseconds
Connected to server
[2019-09-16 03:42:07,397] Artifact cs6650lab:war exploded: Artifact is being deployed, please wait...
[2019-09-16 03:42:08,111] Artifact cs6650lab:war exploded: Artifact is deployed successfully
[2019-09-16 03:42:08,111] Artifact cs6650lab:war exploded: Deploy took 714 milliseconds
And if you visit http://localhost:8080/[WEB_APP]/skiers/12/seasons/2019/day/1/skier/123 (no brackets, same below), (hopefully) you should see the response ("It works!"
) processed by doGet
method in your servlet.
If you get a 404 page, make sure WEB_APP
matches Application Context specified in Run/Debug Configurations -> Tomcat Server -> Deployment tab.
In IntelliJ:
Open the Build menu and click Build Artifacts and click “Edit” in “Action”
In “Artifacts” tab of Project Settings, click “+” to add “Web Application: Archive” for “[WEB_APP]:war exploded” and click “OK” to finish.
Open the Build menu and click Build Artifacts and click “Build” for “[WEB_APP]:war”
out/artifacts/[WEB_APP]/[WEB_APP].war
Upload this file to the webapps
folder in your Tomcat installation path in the EC2 instance with tools such as scp, for example
$ sudo scp -i /path/to/pem/file /local/path/to/war/file ec2-user@EC2_IP_ADDR:/remote/path/to/tomcat_webapp/directory
The exact location is dependent on installation choices and version but there’s a good chance it will be something like ‘/var/lib/tomcat8/webapps’ or alternatively /usr/share/tomcat8/webapps
If you get permission denied, you’ll have to use chmod as follows:
cd /var/lib/tomcat8
sudo chmod -R 777 webapps/
Visit http://{YOUR_REMOTE_INSTANCE_IP}:8080/[WEB_APP]/skiers/12/seasons/2019/day/1/skier/123 and you should see the same response as what you get locally
GET
request is very straightforward as it can be easily done by visiting the URL in your favorite web browser.
Since POST
requests usually also contain request body, we can utilize tools like Postman to include those additional information.
Choose POST
as request method and enter the request URL
In “Body” tab, choose raw
and enter the JSON request body in the text area, for example
{
"time": 217,
"liftID": 21
}
then click “Send”.
If all goes well, you will be able to see the response produced by your doPost
method.
Congratulations! You have just finished one of the most tricky part of all assignments! It may take a lot of pain to set up everything correctly and get your dev environment ready, but I assure you much more exciting stuff is coming up next!
Finding a file - example Linux command
find / -name “tomcat-users.xml” 2>/dev/null
200: Done, it was okay. Generally, your GETs return this code.
201: “Done, and created.” Generally, your POSTs return this code.
204: “Done, and no body.” Generally, your DELETEs return this code.
400: “Client sent me junk, and I’m not going to mess with it.”
401: “Unauthorized, the client should authenticate first.”
403: “Not allowed. You can’t have it because you logged in but don’t have permission to this thing or to delete this thing.”
404: “Can’t find it.”
410: “Marked as deleted.”
451: “The government made me not show it.”