View
14
Download
0
Category
Preview:
Citation preview
crowdscriber.com
Web Applications for the REST of Us
An Introduction to Ember.js, Akka, and Spray(and Slick)
crowdscriber.com
Craig SeanFounder, Product Managercraig@crowdscriber.com@craiger
Founder, Tech Directorsean@crowdscriber.com
crowdscriber.com
Y etA notherW ebS tack
Presenting...
crowdscriber.com
YOU
crowdscriber.com
ME
crowdscriber.com
Your past has given you the strength and wisdom you have today, so celebrate it. Don’t let it haunt you.
● CGI (C, Perl)● Servlets● JSP● Struts● Wicket● SpringMVC● JSF*● Play*● GWT**
crowdscriber.com
What I was used to...Server-side MVC
Model
Controller
View
<html><%=...</html>
crowdscriber.com
What I didn't like about it...● User Experience
○ Trip to the server to render a page● Not "Designer-friendly"
○ Front-end devs needed to...■ run a servlet container, Database, etc...■ have programming chops■ or rely on developers
● No easy answers to "Can we do this"○ "Can we have an interactive map where users drop pins?"
■ Answer: Derp ● Hands tied
○ Want to use a new Javascript Library?
crowdscriber.com
GWT● This one was different...
○ Everything written in Java○ Concept of Client-side components○ Transliterated Java->Javascript components○ Components made AJAX calls to Server for data
■ i.e. Look Ma! No page reloads!○ "Dev Mode"
■ Debugging/Live-Reload○ Deploys to Google App Engine
● But...○ "Quirky"○ People jumping ship to Angular○ Google no longer spearheads development
crowdscriber.com
Crowdscriber's YAWSFront-end
Ember.js Renders UI, Handles user interaction
Back-endSpray REST API
Akka Async, Concurrency, Scaling
Slick Database Access
crowdscriber.com
Front-endSingle Page Applications
● Popular Frameworks○ Angular○ Ember○ React○ Backbone
● Think Fat-client○ The more things change...
● Server is a glorified datastore
crowdscriber.com
Why Ember?● Active community● Relatively mature
○ Version 2.x currently● Cross-platform (Windows, MacOSX, Linux)● Rapid prototyping
○ Fake out the backend● Opinionated
○ i.e. conventions● Promotes parallel development
○ Front-end Ember Devs○ Back-end API Devs
crowdscriber.com
Ember CLI● Command line tools for...
○ Serving Ember apps (in development)○ Building Ember apps (for production)○ Providing live-reload (think GWT's Dev Mode)○ Generating boilerplate (think Maven archetypes)○ Proxying REST calls (i.e. no CORS.xml)
crowdscriber.com
Ember Concepts● Router
○ Defines URLs in your App● Route
○ Sets up Data for views for a given URL● Components
○ Reusable view logic (Widgets)○ Typically render a Model○ .hbs template + Javascript file
● Ember Data○ ORM for REST APIs○ Provides Models to Routes
● Binding○ Components are notified of changes to Models
crowdscriber.com
Ember Demo
crowdscriber.com
Server-side Stack
Framework Purpose
Spray REST Routing Layer
Akka Scalability and Async
Slick Database Access
crowdscriber.com
Spray● Provides
○ REST Routing DSL spray-routing
○ JSON Serialization spray-json
○ Light-weight server spray-can
crowdscriber.com
Exampletrait ApiRoutes extends HttpService {
// GET /oauth2?code=<someCode>&state=<someState> path("oauth2") {
get {parameters("code", "state") {
(token, userId) => {//handle oauth stuff
}}
}}
}
crowdscriber.com
Or more condensed...trait ApiRoutes extends HttpService {
path("oauth2" & get & parameters("code", "state")) {(token, userId) => {
//handle oauth stuff}
}}
crowdscriber.com
spray-jsonpath("user" & post) {
entity(as[RegistrationDto]) { reg =>complete(
userService.registerUser(reg.email, reg.password))
}}
crowdscriber.com
Akka● Actors framework● Asynchronous● Stateless
○ Promotes concurrency● Scalable● Spray is built on Akka
crowdscriber.com
Actors● Typically thread-per-Actor● Each actor can queue requests (mailbox)● Only one request (message) at a time is processed● Spray uses an Actor as the Route
○ You can use Akka to load-balance○ Multiple instances of your route○ Otherwise requests pile up in the queue
crowdscriber.com
Scalable● Why are Actor Frameworks Scalable?
○ Elastic○ Distributed○ Light-weight
crowdscriber.com
Scaling● How would you scale a traditional JEE app?
○ Connection pool○ Caching○ I know! Increase the thread pool!
■ Ah, that didn't work. Let's Load-balance
crowdscriber.com
Request Threads
t1 t2 t3
r1 r3r2 r4
What you don't want to happen...
f1 c1
f2 c2
f3 c3
f4 c4f4
r4 ✅
t1 t2 t3
f3
f2
f1
r1 r3r2
What you want to happen...
crowdscriber.com
Load Balancing● Balance requests (load) across App Containers
○ Strategy: Round-robin, Random, Sticky...● But what if it's only certain requests that cause load?
○ Do we actually want to scale entire containers?○ What if we could Scale from within our app?
● Akka lets us Scale internally○ Costly requests are balanced across Actors○ Freeing up request threads to handle more requests○ Actors may be remotely distributed across process/network boundaries
crowdscriber.com
Internal Actors● Subtitle Actor
○ Built-in serialization of our requests● Chunker Actor
○ Time-intensive algorithm○ Distribute load across Actor systems
crowdscriber.com
Load Balancing vs Actor Pools
Server 1 Server 2
Requests Requests
crowdscriber.com
● Loosely Coupled○ Replace any layer with something else
● Rapid Prototyping○ Develop Ember with Mock Data○ Same app you'll deliver to the Client
● Parallel Development○ Two different developers can develop Front-end/Back-end
● Reusable API○ Open it up to customers○ Use it for a batch jobs
● Close to the Metal front-end○ HTML/CSS/JS○ Designer can iterate their design
Why our YAWS?
crowdscriber.com
Do we have time for Slick?● Scala RDMS ORM● Access database tables like collections● Connection pooling● Transaction management● Code Generator● Schema Generator● Query DSL
crowdscriber.com
Slick DSLval subQuery =
for {
uc <- UserContentTable.query if uc.userId === userId.toString
c <- ContentTable.query if uc.contentId === c.id
} yield (uc, c)
val query =
UserTable.query.filter(_.id === userId.toString)
.joinLeft(subQuery).on { case (u, (uc, c)) => u.id === uc.userId}
.map { case (u, sub) => (u, sub.map{ case (uc, c) => c }) }
SELECT s17.s112, s17.s113, s90.`user_id`, s91.`id`, s91.`title`, s91.`source`, s91.`source_id`, s91.`content_type`, s91.`duration`, s91.`privacy_status`, s91.`thumbnail_url`, s91.`publisher`FROM (SELECT `id` AS s112, `email` AS s113 FROM `user` WHERE `id` = 'c504073a-bcf2-410b-9d88-3e81531374e5') s17LEFT OUTER JOIN (`user_content` s90 INNER JOIN `content` s91 ON (s90.`user_id` = 'c504073a-bcf2-410b-9d88-3e81531374e5') AND (s90.`content_id` = s91.`id`)) ON s17.s112 = s90.`user_id`
crowdscriber.com
Is the Grass Truly Greener?● Learning Curve● You have to like Javascript● Prepare to upgrade often● Slick Upgrade was tough
crowdscriber.com
Craig Seancraig@crowdscriber.com@craiger
sean@crowdscriber.com
Thank you
Recommended