REST in-practice, in practice!

46
MILAN November 28 th /29 th , 2014 REST in Practice, in Practice @iansrobinson Ian Robinson

description

by Ian Robinson - In the mid-2000s I was using the web as a platform for building enterprise apps. This led to my co-authoring 'REST in Practice', a guide to applying the tenets of REST in the enterprise. Then, in 2011, I joined a graph database company. Here, we applied the ideas that inspired 'REST in Practice' to a quite different set of architectural problems. In this session I'll discuss some the things I've learnt in implementing a database server Web API, and building the infrastructure we use for testing clusters, reproducing customer scenarios, and benchmarking the database.

Transcript of REST in-practice, in practice!

Page 1: REST in-practice, in practice!

MILAN November 28th/29th, 2014

REST in Practice, in Practice

@iansrobinson

Ian Robinson

Page 2: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Internal Mail

Work  in  the  1950s  Office  

Business

Page 3: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

RESTful  Web  App  

Domain Model

Web Technologies

http://app

http://app/abc

http://app/xyz

HTTP

HTTP

Page 4: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Protocols  Coordinate  Processes  

v HTTP

v ?

Page 5: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Protocols  

Page 6: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Protocol  SpecificaBon  

Page 7: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Protocol  Discovery  

Page 8: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Everyday  Protocol  Discovery  

Page 9: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Hypermedia  Constraint  

Hypermedia As

The

Engine Of

Application State

Page 10: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Graph database Clustered

Page 11: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Infrastructure  and  Tooling  

•  Performance  tesBng  •  Soak  tesBng  •  Stress  tesBng  •  Proof  of  concept  •  Reproduce  customer  issues  

http://www.danzigergallery.com/artists/yuji-obata/7

Page 12: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Page 13: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

TestLab  Manager  

Workflows Application State

Page 14: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Provision  Estate  

Install  Database  

Configure  Database  

Install  Dataset  

Install  Extension  

Start  Database   Archive  Logs  

Backup  Database  

Check  Database  Status  

Capture  Heap  Dump  

Install  Workload  

Execute  Workload  

Publish  Results  

Analyze  Results  

1.  Design  Around  CapabiliBes  

Page 15: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Provision  Estate  

Install  Database  

Configure  Database  

Install  Dataset  

Install  Extension  

Start  Database   Archive  Logs  

Backup  Database  

Check  Database  Status  

Capture  Heap  Dump  

Install  Workload  

Execute  Workload  

Publish  Results  

Analyze  Results  

Implement  as  Resource  Families  

Page 16: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Deploy  in  Services  

Provision  Estate  

Install  Database  

Configure  Database  

Install  Dataset  

Backup  Database  

Check  Database  Status  

Capture  Heap  Dump  

Install  Extension  

Start  Database   Archive  Logs  

Database  Agent  

Install  Workload  

Execute  Workload  

Load  Generator  

Publish  Results  

Analyze  Results  

Results  Service  

Page 17: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Client  Creates  an  ApplicaBon  •  Client-­‐specific  applicaBon  goal  

•  Applies  resources  to  saBsfy  this  goal    •  Intelligence  at  the  edges  

•  Client  understands/reconstructs  state  of  the  applicaBon  

Page 18: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Neo-­‐Workbench  Java  SDK  

Database  Agent  

Command-­‐Line  Tools   Tests  (e.g.  Soak  Tests)  

Database  Agent  

Database  Agent  

Servers

Clients

Page 19: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Database  Agent  Demo  •  Browser  •  Command-­‐line  •  Code  

Page 20: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

<table> <tr> <td> <a href="http://localhost:38000/database-agent/001" rel="database-admin">001</a> </td> </tr> ...</table>

<form class="install-database" method="POST" action="http://localhost:38000/database-agent/" enctype="application/x-www-form-urlencoded"> <input type="hidden" name="_redirect_" value="http://localhost:38000/database-agent/"></input> <input type="text" name="installUri"></input> <button type="submit" id="submit-form-install-database">Install</button></form>

2.  Choose  a  Hypermedia  Format  

Page 21: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

<table> <tr> <td> <a href="http://localhost:38000/database-agent/001" rel="database-admin">001</a> </td> </tr> ...</table>

<form class="install-database" method="POST" action="http://localhost:38000/database-agent/" enctype="application/x-www-form-urlencoded"> <input type="hidden" name="_redirect_" value="http://localhost:38000/database-agent/"></input> <input type="text" name="installUri"></input> <button type="submit" id="submit-form-install-database">Install</button></form>

Link  –  Safe  OperaBons  

SemanBc  context  

Page 22: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

<table> <tr> <td> <a href="http://localhost:38000/database-agent/001" rel="database-admin">001</a> </td> </tr> ...</table>

<form class="install-database" method="POST" action="http://localhost:38000/database-agent/" enctype="application/x-www-form-urlencoded"> <input type="hidden" name="_redirect_" value="http://localhost:38000/database-agent/"></input> <input type="text" name="installUri"></input> <button type="submit" id="submit-form-install-database">Install</button></form>

Form  –  Unsafe  OperaBons  

SemanBc  context  

Page 23: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

<table> <tr> <td> <a href="http://localhost:38000/database-agent/001" rel="database-admin">001</a> </td> </tr> ...</table>

<form class="install-database" method="POST" action="http://localhost:38000/database-agent/" enctype="application/x-www-form-urlencoded"> <input type="hidden" name="_redirect_" value="http://localhost:38000/database-agent/"></input> <input type="text" name="installUri"></input> <button type="submit" id="submit-form-install-database">Install</button></form>

Program  the  Client  

Page 24: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

<table> <tr> <td> <a href="http://localhost:38000/database-agent/001" rel="database-admin">001</a> </td> </tr> ...</table>

<form class="install-database" method="POST" action="http://localhost:38000/database-agent/" enctype="application/x-www-form-urlencoded"> <input type="hidden" name="_redirect_" value="http://localhost:38000/database-agent/"></input> <input type="text" name="installUri"></input> <button type="submit" id="submit-form-install-database">Install</button></form>

Machines  First,  Browsers  Second  

Conven&on  Fields  with  _underscores_  target  the  browser  

Page 25: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

POST /database-agentinstallUri=file:///neo4j-enterprise-2.1.5-unix.tar.gz

Client  Database  Agent  

ProgrammaBc  Client  

201 CREATEDLocation: /database-agent/001/

Page 26: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Database  Agent  

Browser  Client  

303 SEE OTHERLocation: /database-agent

GET/database-agent

200 OKContent-Type: text/html

POST /database-agentinstallUri=file:///neo4j-enterprise-2.1.5-unix.tar.gz_redirect_=/database-agent

Page 27: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

3.  Long-­‐Running  Processes  •  Request  triggers  long-­‐running  operaBon  (e.g.  backup)  

•  Client  waits  for  response:  • What  happens  if  the  connecBon  breaks?  

Page 28: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

202  Accepted  •  Indicates  request  has  been  accepted  for  processing  

•  Response  includes  URI  of  status  monitor  •  Client  polls  status  monitor  

Page 29: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Client  Database  Agent  

202  Accepted  

202 ACCEPTEDLocation: /database-agent/jobs/3e4d0

POST /database-agent/001/storesinstallUri=s3://.../graph.db.zip

GET /database-agent/jobs/3e4d0

202 ACCEPTEDLocation: /database-agent/jobs/3e4d0

GET /database-agent/jobs/3e4d0

201 CREATEDLocation: /database-agent/002/stores/graph.db

Install  Store  

Page 30: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Polling  Demo  

Page 31: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

4.  Client-­‐Side  OrchestraBon  

Neo-­‐Workbench  Java  APIs  

Command-­‐Line  Tools   Tests  (e.g.  Soak  Tests)  

Servers

Clients

1.  Install Database 1 2.  Install Database 2 3.  Install Database 3 4. Upload Store 1-A 5. Upload Store 2-A 6. Upload Store 3-A 7. Start Database 1 8. Start Database 2 9. Start Database 3 10. etc…

Sequential = Slow

Page 32: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Client  Database  Agent  

Database  Agent  

Database  Agent  

Install  Database  Install  Database  

Install  Database  

Upload  Dataset  Upload  Dataset  

Upload  Dataset  

Page 33: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

ReacBve  Extensions  Iterables   Observables  

Synchronous   Asynchronous  

Pull   Push  for ( Integer integer : stats.counters() ){ System.out.println( integer );}

stats.counters().subscribe( new Action1<Integer>() { @Override public void call( Integer integer ) { System.out.println( integer ); } });

h^ps://github.com/Ne`lix/RxJava/wiki  

Page 34: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

new StartCluster() .execute( cluster ) .subscribe( new Action1<URI>() { @Override public void call( URI uri ) { System.out.println( format( "Database started: %s", uri ) ); } } );

Client-­‐Side  OrchestraBon  

Page 35: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

new StartCluster() .execute( cluster ) .subscribe( new Action1<URI>() { @Override public void call( URI uri ) { System.out.println( format( "Database started: %s", uri ) ); } } );

Client-­‐Side  OrchestraBon  

Page 36: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

{ "estate" : { "estateId" : "est51b65", "owner" : "neo-workbench", "scenario" : "soak-test", "blocks" : [ { "blockId" : "blke16a8", "name" : "db-cluster", "size" : 3, "machines" : [ { "id" : "mace5508", "publicIpAddress" : "127.0.0.1", "publicDnsName" : "localhost", "links" : [ { "rel" : "database-agent", "uri" : "http://localhost:38001/database-agent" }, { "rel" : "database-admin", "uri" : "http://localhost:38001/database-agent/003" }, { "rel" : "database", "uri" : "http://localhost:7475" } ],

5.  Bookmark  ApplicaBon  State  

Page 37: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

{ "estate" : { "estateId" : "est51b65", "owner" : "neo-workbench", "scenario" : "soak-test", "blocks" : [ { "blockId" : "blke16a8", "name" : "db-cluster", "size" : 3, "machines" : [ { "id" : "mace5508", "publicIpAddress" : "127.0.0.1", "publicDnsName" : "localhost", "links" : [ { "rel" : "database-agent", "uri" : "http://localhost:38001/database-agent" }, { "rel" : "database-admin", "uri" : "http://localhost:38001/database-agent/003" }, { "rel" : "database", "uri" : "http://localhost:7475" } ],

5.  Bookmark  ApplicaBon  State  

Page 38: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

6.  Automate  Deployment  

Database   Results  Load  

Page 39: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Automated  Provisioning  

Provisioning  API  AWS  

CloudFormation  SDK  

Local  Provisioning  Provider  

Azure  SDK  Vagrant  

Page 40: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Fluent  API  

Estate estate = new Estate() .addBlock( new Block<>( "results", 1, ResultsServiceConfig.DEFAULT, AwsPlatformConfig.DEFAULT ) .addBlock( new Block<>( "db-cluster", 3, DatabaseAgentConfig.builder().withPackageDownloadUri( URI.create( "http://dist.neo4j.org/neo4j-enterprise-2.1.2-unix.tar.gz" ) ).build(), AwsPlatformConfig.DEFAULT ) ) .addBlock( new Block<>( "load-generator", 1, LoadGeneratorConfig.DEFAULT, LocalPlatformConfig.DEFAULT ) );

EstateProvisioning provisioning = new EstateProvisioning();provisioning.provision( estate );

Page 41: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Graphite  Block  in  AWS  

Estate estate = new Estate() .addBlock( new Block<>( "results", 1, ResultsServiceConfig.DEFAULT, AwsPlatformConfig.DEFAULT ) .addBlock( new Block<>( "db-cluster", 3, DatabaseAgentConfig.builder().withPackageDownloadUri( URI.create( "http://dist.neo4j.org/neo4j-enterprise-2.1.2-unix.tar.gz" ) ).build(), AwsPlatformConfig.DEFAULT ) ) .addBlock( new Block<>( "load-generator", 1, LoadGeneratorConfig.DEFAULT, LocalPlatformConfig.DEFAULT ) );

EstateProvisioning provisioning = new EstateProvisioning();provisioning.provision( estate );

Page 42: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Database  Block  in  AWS  

Estate estate = new Estate() .addBlock( new Block<>( "results", 1, ResultsServiceConfig.DEFAULT, AwsPlatformConfig.DEFAULT ) .addBlock( new Block<>( "db-cluster", 3, DatabaseAgentConfig.builder().withPackageDownloadUri( URI.create( "http://dist.neo4j.org/neo4j-enterprise-2.1.2-unix.tar.gz" ) ).build(), AwsPlatformConfig.DEFAULT ) ) .addBlock( new Block<>( "load-generator", 1, LoadGeneratorConfig.DEFAULT, LocalPlatformConfig.DEFAULT ) );

EstateProvisioning provisioning = new EstateProvisioning();provisioning.provision( estate );

Page 43: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Local  Load  Generator  Block  

Estate estate = new Estate() .addBlock( new Block<>( "results", 1, ResultsServiceConfig.DEFAULT, AwsPlatformConfig.DEFAULT ) .addBlock( new Block<>( "db-cluster", 3, DatabaseAgentConfig.builder().withPackageDownloadUri( URI.create( "http://dist.neo4j.org/neo4j-enterprise-2.1.2-unix.tar.gz" ) ).build(), AwsPlatformConfig.DEFAULT ) ) .addBlock( new Block<>( "load-generator", 1, LoadGeneratorConfig.DEFAULT, LocalPlatformConfig.DEFAULT ) );

EstateProvisioning provisioning = new EstateProvisioning();provisioning.provision( estate );

Page 44: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Fluent  API  

Estate estate = new Estate() .addBlock( new Block<>( "results", 1, ResultsServiceConfig.DEFAULT, AwsPlatformConfig.DEFAULT ) .addBlock( new Block<>( "db-cluster", 3, DatabaseAgentConfig.builder().withPackageDownloadUri( URI.create( "http://dist.neo4j.org/neo4j-enterprise-2.1.2-unix.tar.gz" ) ).build(), AwsPlatformConfig.DEFAULT ) ) .addBlock( new Block<>( "load-generator", 1, LoadGeneratorConfig.DEFAULT, LocalPlatformConfig.DEFAULT ) );

EstateProvisioning provisioning = new EstateProvisioning();provisioning.provision( estate );

Page 45: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Ian Robinson, Jim Webber & Emil Eifrem

Graph Databases

h

Compliments

of Neo Technology

@iansrobinson  

Page 46: REST in-practice, in practice!

MILAN November 28th/29th, 2014 – Ian Robinson

Soak  Test  

Database  Agent  

Database  Agent  

Database  Agent  

Load  Server  

Results  Server  

Graphite   Graphite    

Database  Cluster  

Workload  

Estate