Georgina McFadyen

Report 2 Downloads 83 Views
Elixir Umbrella Microservice or Majestic Monolith? Georgina McFadyen @gemcfadyen

Elixir Umbrella

@gemcfadyen

What is an Umbrella Project?

@gemcfadyen

Umbrella Application

@gemcfadyen

Create Umbrella

@gemcfadyen

Create Sub Applications

@gemcfadyen

Create Sub Applications

@gemcfadyen

Create Sub Applications

@gemcfadyen

sub app mix.exs

Root level config.exs

root_project/config/config.exs

@gemcfadyen

Run Tests

@gemcfadyen

Run Tests

@gemcfadyen

Dependencies

root_project/apps/sub_app_B/config/config.exs @gemcfadyen

Umbrella Summary •

Breaks down a complex system into parts

• •

Code hosted in one repository



Sub apps as internal dependencies

Sub apps can be developed independently

@gemcfadyen

Faros An Elixir Umbrella https://github.com/deploying-elixir/Faros

@gemcfadyen

Faros: An Elixir Umbrella Faros is a learning portal where blog posts can be saved and searches can be initiated @gemcfadyen

Landing Page

@gemcfadyen

Saving Posts

Searching

Faros Structure

@gemcfadyen

Communication

faros/apps/faros_frontend/mix.exs

@gemcfadyen

Communication

faros/apps/faros_frontend/mix.exs

@gemcfadyen

Why an Umbrella? Is it a sleek solution for Microservices or a Majestic Monolith?

@gemcfadyen

Lessons Learned

! ! @gemcfadyen

#1 Breaking Bad

@gemcfadyen

How do you define the boundary of each sub app?

@gemcfadyen

Core vs Web

@gemcfadyen

Per Responsibility

@gemcfadyen

Persistence

@gemcfadyen

One service per responsibility with one database service

@gemcfadyen

Umbrellas lend themselves to change

@gemcfadyen

#2 Elixir Versions

@gemcfadyen

@gemcfadyen

Requirements Requirements allow you to specify which versions of a given dependency you are willing to work against

https://hexdocs.pm/elixir/Version.html#module-requirements

@gemcfadyen

! @gemcfadyen

@gemcfadyen

:faros_frontend

elixir: “-> 1.2”

{:post_service, in_umbrella: true},

:post_service

elixir: “-> 1.4” @gemcfadyen

Strive For Consistency

@gemcfadyen

#3 Circular Dependencies

@gemcfadyen

Sub App 1

depends on

depends on

Sub App 2

Check if services are too granular - maybe they should be merged together !

#4 Transient Dependency Clashes

@gemcfadyen

@gemcfadyen

Wikipedia Dependencies

faros/apps/wikipedia/mix.exs

@gemcfadyen

Frontend Dependencies

faros/apps/faros_frontend/mix.exs

@gemcfadyen

Phoenix Dependencies

https://github.com/phoenixframework/phoenix/mix.exs

@gemcfadyen

@gemcfadyen

@gemcfadyen

Add Poison as an explicit dependency to Phoenix sub app

Use the override flag to ignore other versions

@gemcfadyen

#5 Namespace Clashes

@gemcfadyen

@gemcfadyen

wikipedia/search.ex

twitter/search.ex

@gemcfadyen

@gemcfadyen

! @gemcfadyen

@gemcfadyen

! @gemcfadyen

@gemcfadyen

💥 @gemcfadyen

Depending which module is loaded first depends on the outcome

@gemcfadyen

Namespace modules

@gemcfadyen

wikipedia/search.ex

twitter/search.ex

@gemcfadyen

#6 Test Data Cleanup

@gemcfadyen

Database Access 3 Umbrella sub applications interact with the database:

- db_service - post_service - faros_frontend @gemcfadyen

Database Access 3 Umbrella sub applications interact with the database:

- db_service - post_service - faros_frontend @gemcfadyen

Database Access 3 Umbrella sub applications interact with the database:

- db_service - post_service - faros_frontend @gemcfadyen

Ecto Sandbox to create Transactional Tests

@gemcfadyen

Configure the Sandbox

faros/apps/db_service/config/test.exs

@gemcfadyen

Get Connection

@gemcfadyen

Ownership

@gemcfadyen

Shared Mode

@gemcfadyen

Shared Mode

@gemcfadyen

#7 Testing Boundaries

@gemcfadyen

faros_frontend

wikipedia

@gemcfadyen

Substitute External Systems

@gemcfadyen

search_controller_test.exs

faros/apps/faros_frontend/test/controllers/search_controller_test.exs

search_controller.ex

faros/apps/faros_frontend/web/controllers/search_controller.ex

search_controller.ex

@gemcfadyen

Wrap the real search functionality

@gemcfadyen

@gemcfadyen

Provide a fake search @gemcfadyen

@gemcfadyen

MIX_ENV=test

MIX_ENV=dev

@gemcfadyen

fake_search.ex

third_party_search.ex

faros_frontend/config/test.exs

faros_frontend/config/dev.exs

@gemcfadyen

search_controller_test.exs

search_controller.ex

search_controller_test.exs

fake_search.ex

search_controller_test.exs

fake_search.ex

Test Doubles Be aware of the boundaries you cross

Switch real/fake implementations in/out

Test away from external systems

Deterministic tests

@gemcfadyen

#8 Documentation

@gemcfadyen

Limited Documentation Dig deep for answers

Read through issue lists

Scour blog posts for workarounds

Tooling documentation is playing catch up @gemcfadyen

Deployment

@gemcfadyen

Distillery Generate release config:

@gemcfadyen

Distillery Bundles all the sub applications into one single release:

faros/rel/config.exs @gemcfadyen

Distillery If you prefer to release each sub app individually:

@gemcfadyen

Any various combinations in between:

faros/rel/config.exs @gemcfadyen

Build & Start Release

@gemcfadyen

Start Release

@gemcfadyen

Build & Start Release Build release using distillery task:

Build specific release:

@gemcfadyen

Assets

@gemcfadyen

One release of all sub apps

or

Group sub apps and release separately

@gemcfadyen

Distribution

@gemcfadyen

Communication The Elixir repl is an individual Erlang runtime:

@gemcfadyen

Distributed Mode

@gemcfadyen

Distributed Mode

@gemcfadyen

Distributed Mode

@gemcfadyen

Cluster

@gemcfadyen

Connecting Nodes Node connection is transitive

@gemcfadyen

Communication A Node is a system running the Erlang VM with a given name

@gemcfadyen

Distribution

@gemcfadyen

Distribution wikipedia

@gemcfadyen

twitter

Distribution [email protected]

:

@gemcfadyen

[email protected]

:

Communication Services need to communicate using a protocol

@gemcfadyen

rpc A remote procedure call is a method to call a function on a remote node and collect the answer.

@gemcfadyen

Distributed Faros

@gemcfadyen

Cluster Configuration

@gemcfadyen

Cluster Configuration

faros/apps/faros_frontend/config/dev.exs

@gemcfadyen

Connect to Node

@gemcfadyen

Distribute to the Node

Cluster Configuration

@gemcfadyen

Remotely Distributed Faros

@gemcfadyen

Build Multiple Releases

@gemcfadyen

Deploy wikipedia release

@gemcfadyen

Configure the address of the node that wikipedia is deployed to

@gemcfadyen

Deploy faros release configured with that child node

@gemcfadyen

Elixir Umbrella Microservice or Majestic Monolith?

@gemcfadyen

Development Monlith: Single repository

Microservices: Separate repositories

Umbrella: Single repository

@gemcfadyen

Communication Monlith: Direct access

Microservices: Defined Protocol

Umbrella: Direct access to dependant sub applications

@gemcfadyen

Languages Monlith: Single language

Microservices: Can use different languages

Umbrella: Single language

@gemcfadyen

Releases Monlith: Shipped as one product

Microservices: Separate pieces shipped independently Umbrella: As you define

@gemcfadyen

Summary Less coordination of pull requests Easy to abstract libraries Flexibility in deployment

@gemcfadyen

Majestic Microservices

@gemcfadyen

Thank-you Elixir.LDN!

@gemcfadyen