shmeleva / Microservices-Project

πŸ”¬ COM-EV Microservice Architectures and Serverless Computing @ Aalto

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

πŸ‘©β€πŸ­ This is a WIP version!

0. Deployment

For the sake of simplicity, everything exists inside Docker Compose. Run to build and start the system:

docker-compose up --build

All methods are available through this API gateway.

Public IP addresses

API Gateway

http://localhost:4000

Consul

http://localhost:48500

Redis

http://localhost:46379

I. System Architecture

Service Description
Identity Issues JWT tokens. Stores users in an MongoDB database.
Carsharing Provides methods for searching, booking and returning cars. Stores cars in a MongoDB database. Requires JWT authentication. Does not provide methods for creating or removing cars from the database, i.e., cars simply exist. Does not have any payment mechanism, i.e., cars are free.
Geocoding Provides methods for converting an address to coordinates and vice versa.

System Architecture

1. Identity Service

Method Description
POST api/v1/identity/create

Query parameters:
username: string, required, unique
password: string, required
Creates a user with the specified username and password.
GET api/v1/identity/jwt

Query parameters:
username: string, required
password: string, required
Issues a JWT for the specified user.

2. Carsharing

Method Description
GET api/v1/cars/available

Query parameters:
latitude: double, required
longitude: double, required
radius: double (meters), 500 meters by default
Searches for available cars in the specified area. Only offers mock functionality, i.e., ignores coordinates and returns all available cars.
POST api/v1/cars/book

{ CarId: string }
Books a car with the specified Id. Accepts JSON.
Not thread-safe.
POST api/v1/cars/return

{ CarId: string, Latitude: double, Longitude: double }
Marks a car with the specified Id as available and updates its location. Accepts JSON.

Requires JWT authentication:

Authorization: Bearer <token>

Tokens are issued by api/v1/identity/jwt.

3. Geocoding

Method Description
GET api/v1/geocode/forward

Query parameters:
address: string, required
Returns coordinates of the specified location. Only works for Uusimaa.
GET api/v1/geocode/reverse

Query parameters:
latitude: double, required
longitude: double, required
Returns an address of the specified location.

Source: HERE Geocoder API.

4. API Gateway

API gateway exposes with their original routes, e.g., api/v1/cars/available is mapped to api/v1/cars/available.

II. Aspects

1. Service Discovery

(1) Services register themselves in Consul on startup:

var ip = Dns.GetHostEntry(Dns.GetHostName()).AddressList.FirstOrDefault(x => x.AddressFamily == AddressFamily.InterNetwork);
var port = 80;
...
consulClient.Agent.ServiceRegister(serviceRegistration).Wait();

(2) Services also register their api/v1/health methods so that Consul can run health checks.

(3) API Gateway is implemented with Ocelot that offers a support for Consul service discovery:

"ServiceDiscoveryProvider": {
  "Type": "Consul",
  "Host": "consul",
  "Port": 8500
}

Consul is only used to discover service IPs. MongoDB, Redis and Consul itself are accessed through their container names.

2. Dynamic Configuration

consul-template daemon is used for dynamic configuration. At this point, only Carsharing mircoservice includes support for dynamic configuration.

In order to change a configuration, a file with Carsharing/appsettings.json key must be created in http://localhost:48500/ui/dc1/kv. This will replace original service configuration file.

consul-template is started in a Dockerfile and runs alongside with Carsharing.dll:

./consul-template -consul-addr "consul:8500" -template "appsettings.tpl:appsettings.json"
dotnet Carsharing.dll

3. Caching

Geocoding mircoservice caches the data retrieved from HERE Geocoder API in a Redis distributed cache:

services.AddDistributedRedisCache(options =>
{
    options.Configuration = "redis:6379";
});

4. Authentication

Identity mircoservice stores users in a MongoDB:

public class User
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string Id { get; set; }

    [BsonElement("Username")]
    public string Username { get; set; }

    [BsonElement("Salt")]
    public string Salt { get; set; }

    [BsonElement("Hash")]
    public string Hash { get; set; }
}

It validates username+password combinations and issues JWT tokens. Identity and Carsharing mircoservices share the symmetric security key.

services
    .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(x =>
    {
        ...
        x.TokenValidationParameters = new TokenValidationParameters
        {
            ...
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("secret")),
        };
    });

References

About

πŸ”¬ COM-EV Microservice Architectures and Serverless Computing @ Aalto


Languages

Language:C# 91.4%Language:Dockerfile 7.2%Language:JavaScript 1.3%Language:Smarty 0.1%