Smart Services & Smart Clients - How Microservices Change the Way You Build and Deploy Code

Post on 06-Aug-2015

171 views 1 download

Transcript of Smart Services & Smart Clients - How Microservices Change the Way You Build and Deploy Code

Smart Services & Smart Clients

How microservices change the way you build and deploy code

Neil Mansilla Developer Relations @mansillaDEV

Runscope

Presented at YAPC 2015Salt Lake City

Solve API Problems FastMonitor, log, measure & share your API usage.

65 services 9 engineers

Why microservices?

0

14,000,000

28,000,000

42,000,000

56,000,000

70,000,000

May 2013 Sep Jan May Sep Jan 2015

Scaling the infrastructure

Scaling the team

Microservices are highly independent

independent codebases independent deploys independent teams

There are a lot of moving parts…

If you don't invest in INFRASTRUCTURE

don't invest in MICROSERVICES

Microservices = SOA + DevOps

Dashboard Identity

get_teams()

Dashboard Identity

get_teams()

host001.runscope.com host002.runscope.com

import requests

def get_teams(): url = “http://host002.runscope.com/teams” resp = requests.get(url)

return resp.json()

Dashboard Identity

get_teams()

url = “http://host002.runscope.com/teams”url = “http://host003.runscope.com/teams”

Dashboard Identity

get_teams() XIdentity

if ENVIRONMENT == “local”:url = “http://localhost:5000/teams”

elif ENVIRONMENT == “test”:url = “http://test001.runscope.com/teams”

elif ENVIRONMENT == “prod”: url = “http://host003.runscope.com/teams”

Dashboard Identity

get_teams()

How do you find a service?

How do you find a service?

Smart Client

Smart Clientimport requests

def get_teams(): url = “http://host001.runscope.com/teams”

resp = requests.get(url)

return resp.json()

Smart Clientimport smart_client

def get_teams(): url = “http://host001.runscope.com/teams”

resp = smart_client.get(url)

return resp.json()

Smart Clientimport smart_client

def get_teams(): url = “service://identity/teams”

resp = smart_client.get(url)

return resp.json()

Smart ClientService discovery

service://identity/...

Retry failed GET/PUT/DELETE (idempotent) requests

Run HTTP requests asynchronously

Smart Client

Atlas

Smart Client

ZooKeeper

Atlas

DynamoDB

/hosts/identity/host001.runscope.com = 5000/hosts/identity/host001.runscope.com/enabled = True

Register service metadata in Zookeeper & DynamoDB

Smart Client

Atlas

Sidecar

Runs HAProxy on each host.

Reads cluster state from Atlas.

Watches for changes to services and updates the local configuration.

host001

host002

host003

Smart Client

Smart Client

Service AService A

Smart ClientService B

Service B

Smart Clientsmart_client.get(“service://identity/teams”)

requests.get(“http://localhost:4000/teams”, headers={“Runscope-Service”: “identity”})

haproxy.cfgfrontend http-in bind *:4000 mode http acl host_api hdr(runscope-service) -i api acl host_billing hdr(runscope-service) -i billing acl host_mission-control hdr(runscope-service) -i mission-control acl host_elasticsearch hdr(runscope-service) -i elasticsearch

use_backend api-backend if host_api use_backend billing-backend if host_billing use_backend mission-control-backend if host_mission-control use_backend elasticsearch-backend if host_elasticsearch

Smart Clientsmart_client.get(“service://identity/teams”)

requests.get(“http://localhost:4000/teams”, headers={“Runscope-Service”: “identity”})

How do you find a service?

Smart Client

How do you make building services easy?

How do you make building services easy?

Smart Service

Smart Service

Smart Service

Runscope/healthcheck

Smart Service

bugsnag runscope-daemon alchemist smart-config

Smart Service

Configuration Driven

defaults.py

REDIS_SERVICE = “redis-cluster-1”REDIS_DB = 2

BUGSNAG_API_KEY = “xyz123”

Smart Service

Configuration Driven

config = SmartConfig('example-service', defaults=example_service.defaults)

app = SmartService('example-service', config=config)

Smart Service

Various additions to the flask app object

from flask import current_app

current_app.realmcurrent_app.rediscurrent_app.databasecurrent_app.api

Smart Service

Common Logging Configuration

/var/log/runscope/<service>.access.log/var/log/runscope/<service>.error.log

current_app.logger.warn(“Uh oh!”)bugsnag.notify(e)

$> generate-service my-awesome-service

Creating a service skeleton with this configuration: Service name: my-awesome-service Destination directory: ~/runscope/my-awesome-service Python package name: my_awesome_service HTTP port: 5004

1. Generating files in ~/runscope/my-awesome-service2. Initializing Git repository in ~/runscope/my-awesome-service3. Creating virtualenv my-awesome-service4. Installing Python prerequisites (requirements.txt and setup.py)

All done! my-awesome-service source code can be found in ~/runscope/my-awesome-service

Smart ServiceAuto Generate Service Skeletons

Smart Service

Reduce Cognitive Overhead

How do you make building services easy?

Smart Service

What happens when you have so many services?

What happens when you have so many services?

A Lot :)

Automate everything

Language Agnostic

Language AgnosticHTTP is our common ‘language’

No shared databases

DashboardTraffic

GatewayAPI

Postgresql

DashboardTraffic

GatewayAPI

PostgresqlX

DashboardTraffic

GatewayAPI

Identity

Postgresql

Flask

Redis

A service owns it’s own datastore(s).

DashboardTraffic

GatewayAPI

And exposes an API for that data.

Identity

GET /teams/<id>

PUT /teams/<id>

GET /buckets

...

Make Deploying Code Really Easy

Make Deploying Code Really Easy

1-Click Deploys

0

10

20

30

40

50

Jun 2014 Jul Aug Sep Oct Nov Dec Jan Feb Mar 2015

Deploys per day

Test & Monitor your APIs

Test Lifecycle

Local Dev{{identity_host}} = http://localhost

Local Agents

Test Lifecycle

Test Realm

Local Dev

{{identity_host}} = http://test001.runscope.com

Local Agents

Trigger URLs

Test Lifecycle

Test Realm

Production

Local Dev

{{identity_host}} = http://host002.runscope.com

Local Agents

Trigger URLs

Schedules

0

10

20

30

40

50

Jun 2014 Jul Aug Sep Oct Nov Dec Jan Feb Mar 2015

Deploys per day

Thanks!

p.s. - we’re hiring :)

Runscope

https://www.runscope.com/jobs

Neil Mansilla@mansillaDEV