A new server-side application needs to be developed to handle incoming REST requests. Depending on the request, a defined REST endpoint must be called with MSISDN as the sole request parameter. Upon receiving the request, the REST endpoint will provide a response consisting of two integer parameters. The new application should then calculate the sum of these two integers and respond back to the initial request with the resulting sum.
- Parallel MSISDNs requests
- Processing waits (queued) while a request with the same MSISDN is already in progress
- Horizontally scalable
- High availability and network partitioning handling
- Under majority of nodes the system works normally
- While on minority of node requests are rejected
- Reactive process approach (less CPU cycles)
- One supervisor with a child dispatcher and another supervisor with child workers processes
- The number of workers is configured in the sys.config file
- During initialization each worker process notifies the dispatcher (idle worker)
- The nodes are connected using
net_adm:world()
called at application start .hosts.erlang
andsys.config
has to be modified for cluster nodes size
- Cowboy REST request handler from Client PID
- Receives an incoming request with the MSDISDN
- If under a minority of nodes in a partitioned network the request is discarded
- Tries to acquire a lock for the MSISDN using a global registration and uses a resolve in case of clash
- If lock not acquired, the PID owning the MSISDN registration is monitored
- Once a DOWN executes step 2
- Switches to a Cowboy loop handler
- Sends the request to the named dispatcher process (gen_server)
- The Dispatcher process
- A request is received and stored in a LIFO queue
- When a worker PID notifies the dispatcher
- If the LIFO queue is not empty a request is sent to the worker PID
- Otherwise, the worker PID is monitored and stored in a FIFO queue (idle workers). If not already there.
- A Worker process
- Receives a request with the MSISDN and Client Pid
- The Client Pid is linked to handle premature client termination
- Uses the MSISDN to build the target URL (in sys.config)
- Sends a REST client request
- The response is sent to the Client PID
- In the Client PID (at 1)
- Matches the response, two integers
- Responds to the original request with a JSON object containing the sum of both integers
- The client connection is closed
NOTE: when using rebar3 test profile the request to the endpoint is mocked
❯ make
*** ReqSrv Command line ***
NOTES:
- The development environment requires rebar3 and Erlang installed
- The cluster requires Docker and Docker Compose
- The development environment uses the test profile in rebar3 config
- The test profile mocks the request to the REST endpoint
deps get deps
compile compile
clean clean
release build release
shell start node locally, application boot with console
cluster-up cluster up
cluster-down cluster down
test send some sample requests
Start the cluster:
❯ make cluster-up
wait for curl --parallel http://localhost:9102/14333
success
NOTE: cluster-up fails, retry.
Test some scenarios:
❯ make test
To bring node 0 and 1 down, attach and exit:
❯ make cluster-attach-0
([email protected])1> ^ CTRL-C
❯ make cluster-attach-1
([email protected])1> ^ CTRL-C
Minority of nodes, reject scenario:
❯ curl -v http://localhost:9102/14333
* Trying 127.0.0.1:9102...
* Connected to localhost (127.0.0.1) port 9102 (#0)
> GET /14333 HTTP/1.1
> Host: localhost:9102
> User-Agent: curl/7.87.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 400 Bad Request
Stop the cluster:
❯ make cluster down
- automate clustering sizing
- control flow
- queue limits
- system metrics
- stress testing and benchmarking
- global:register_name as a distributed lock mechanism needs more testing
- a lot more ...