MovieBuzz System Design: Coding End To End System From Scratch! Part 2
5 min readApr 25, 2021
In continuation with my last blog, I added some more features to the MovieBuzz project. Here is the link to the previous blog: https://bhushan-gosavi.medium.com/moviebuzz-system-design-coding-end-to-end-system-from-scratch-606dbd66e568
New Features
- User Authentication and Authorization: Only Authenticated users should be able to access the APIs from Gateway. If the User is not Authenticated then API should return HTTP 401 Unauthorized response code.
- Service Metrics Real-Time Monitoring and Alerts: We want to monitor the health of all the running services in a single dashboard. We want to get memory metrics for each Service such as Heap and Garbage collection metrics, time that is taken by each process for Garbage Collection, etc. We need to get API call rates and API error rates in real-time. We want to get alerts if API rates are increased by threshold or API error rate is increased.
MovieBuzz Updated Architecture
- Gateway will transfer incoming requests to either UserService or FrontAPI service based on the API path.
- /moviebuzz/v1.0/user/** APIs will be redirected to UserService
- All the rest APIs will be redirected to frontAPI service
return builder.routes()
.route(p -> p
.path("/moviebuzz/v1.0/user/**")
.uri(userServiceUrl))
.route(p -> p
.path("/moviebuzz/v1.0/bookings/**", "/moviebuzz/v1.0/movies/**",
"/moviebuzz/v1.0/theatres/**", "/moviebuzz/v1.0/reviews/**")
.uri(frontApiUrl))
.build();
- We will use Appdynamics Software as a Service to Monitor services in real-time.
User Authentication and Authorization
- We will use JWT token-based Authorization. We will use stateless sessions, all the session information will be embedded in the JWT token so we don’t need to worry about maintaining sessions at the backend. For more details about JWT Authorization, have a look at https://jwt.io/introduction
- For Authentication, the user needs to use /moviebuzz/v1.0/user/authenticate API which will return user JWT token in response. As per routing rules Gateway will redirect this API to UserService. UserService handles Authentication.
- The Gateway service container is running on localhost 9090 port. We will use this JWT token in response to get Authenticated for the rest of the APIs
- As we saw, the user doesn’t need to be Authenticated to call /authenticate API. But to call any other API user has to be Authenticated. Also, we don’t want any Authenticated user to add movies and theaters. The only user with ADMIN access should be able to add movies and theaters in DB. Thus the user has to be ADMIN Authorized to add movies and theaters.
httpSecurity.csrf().disable()
.authorizeRequests()
.antMatchers("/v1.0/user/authenticate").permitAll()
.antMatchers(HttpMethod.POST, "/v1.0/movies").hasAuthority("ADMIN")
.antMatchers(HttpMethod.POST, "/v1.0/theaters").hasAuthority("ADMIN")
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.exceptionHandling().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
- Authentication vs Authorization: https://securityboulevard.com/2020/06/authentication-vs-authorization-defined-whats-the-difference-infographic/
- Let’s use /moviebuzz/v1.0/user/validate API to validate JWT token for bgosavi user. Remember, we are not passing the username or password to the API, UserService detects username and authorizes using just JWT token. We are just passing the JWT token as Authorization header to the API.
- How UserService is able to Authorize the request and How UserService knows that request is coming from bgosavi username? This is because bgosavi username is encoded in JWT. This Payload is signed by Secret Key stored in UserService while Authenticating user, this is how JWT token is generated. Thus if anyone tries to modify the JWT token, it won’t work
- JWT tokens are safe until they are stolen. Thus users should not share JWT tokens with anyone and consider JWT tokens as username and password combination.
- After a configured interval of time, JWT tokens get expired. The user needs to be authenticated again and use the newly assigned JWT token.
- Using the same JWT token, users can get Authorized to other moviebuzz APIs like /moviebuzz/v1.0/movies, /moviebuzz/v1.0/bookings etc
- If we don’t pass the JWT token as header, we get 401 Unauthorized as the response.
Service Metrics Real-Time Monitoring and Alerts
- We will use Appdynamics Software as a Service to get more insights into our running services in real-time. https://www.appdynamics.com/
- You can register and create a trial account on Appdynamics here https://www.appdynamics.com/free-trial/
- From this Appdynamics account you can download JavaAgent custom JAR file and we need to pass it as JVM parameter while starting our application on Container.
-javaagent:/opt/appd/javaagent.jar
-Dappdynamics.agent.nodeName=gateway-dockerHost
-Dappdynamics.agent.applicationName=moviebuzz
-Dappdynamics.agent.tierName=gateway
- Apart from JavaAgent jar file you need to pass the nodeName, applicationName and tierName as JVM argument while starting each service
- That’s it and the Appdynamics setup is Done.
- You can clearly see which services are communicating with each other. What’s the API call rate, error rate etc in single Dashboard
- We can see total calls made to Cassandra DB and total messages added to each kafka topic. Along with response time, calls/min and errors/min etc stats.
- We can also deep dive into JVM and memory stats for each node/container on which our services are running.
- We can also add Alerts for our services in Appdynamics. We can define our own health rule, if it get’s violated then we can get alert email.
- I added a sample Health rule, if calls per minute are more than 2, then send me an alert email. (Of course in production we won’t have such rule, I added it just for testing purpose)
- I started hitting API to violate this health rule and I got an email.
The Code
Repository: https://github.com/bhushan-gosavi/moviebuzz-parent
Platform Features
- Horizontally scalable
- Highly Concurrent
- Microservice Architecture
- Containerized Application
- Production Grade Code with Integration Tests using Docker Containers