Slide 1

Slide 1 text

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission. Inside spring.io: a Production Spring Reference Application Brian Clozel - @brianclozel

Slide 2

Slide 2 text

Chris Beams at SpringOne 2013

Slide 3

Slide 3 text

Carl Sagan smiling at you

Slide 4

Slide 4 text

Now, seizing planets

Slide 5

Slide 5 text

And me!

Slide 6

Slide 6 text

…and, well, me. ! Brian Clozel ! • Spring Framework committer • Sagan developer • Bad at Photoshop @brianclozel

Slide 7

Slide 7 text

The Plan ! ! 1. Open sourcing spring.io 2. Evolving spring.io 3. What’s next?

Slide 8

Slide 8 text

Open sourcing spring.io

Slide 9

Slide 9 text

Why did we open source Sagan? ! ! • The Example/Sample App problem • The Reference App problem • We’re committed to Open Source

Slide 10

Slide 10 text

Enter Sagan application

Slide 11

Slide 11 text

Sagan: Blog

Slide 12

Slide 12 text

Sagan: Spring portfolio

Slide 13

Slide 13 text

Sagan: Spring guides

Slide 14

Slide 14 text

Sagan: search

Slide 15

Slide 15 text

Billions and billions of visitors

Slide 16

Slide 16 text

Available on GitHub ! ! • github.com/spring-io/sagan • BSD3-license • Master branch == running in production

Slide 17

Slide 17 text

Project Layout

Slide 18

Slide 18 text

Writing blog posts ! ! • spring.io/blog • Project Sagan: open sourcing spring.io • Project Sagan: zero downtime deployments • Project Sagan: client side architecture • Project Sagan: upgrading to JDK 8

Slide 19

Slide 19 text

Embedded documentation

Slide 20

Slide 20 text

Partial/total rewrites ! • Getting started experience… • JDK8 features • Code architecture • Client side architecture

Slide 21

Slide 21 text

sagan-client

Slide 22

Slide 22 text

Build integration with Gradle 1/2 ! // install NPM dependencies! task npmInstall(type:Exec) {! inputs.files "package.json", "bower.json"! outputs.dir "node_modules"! commandLine 'npm', 'install'! }! // run the Gulp.js build! task npmBuild(dependsOn: npmInstall, type:Exec) {! inputs.dir "src"! inputs.file "gulpfile.js"! outputs.dir "dist"! commandLine 'npm', 'run', 'build'! }

Slide 23

Slide 23 text

Build integration with Gradle 2/2 apply plugin: 'java'! // create a webjar to be served by the sagan-site module! jar {! from 'dist'! eachFile { ! details -> details.path = ! details.path.startsWith('META-INF') ?: 'static/'+details.path! }! }! ! jar.dependsOn npmBuild

Slide 24

Slide 24 text

Modular JavaScript application // using curl.js as a module loader! curl.config({! packages: {! app: { location: 'app'}! },! paths: {! jquery: 'lib/jquery/jquery.min',! ! gmaps: {location: 'lib/gmaps/gmaps', config:cjsConfig }, ! }! });! ! // Promises-based API for executing callbacks! curl(['app', 'jquery']).then(start, fail);

Slide 25

Slide 25 text

Gulp, a streaming build system

Slide 26

Slide 26 text

Gulp, a streaming build system // concatenate and minify CSS files! gulp.task('minify-css', function() {! return gulp.src('src/css/*.css')! .pipe(cssmin({root: 'src/css'}))! .pipe(gulp.dest('./dist/css'));! });! ! // tasks run in parallel! gulp.task('build', [‘minify-css', 'bower-files'], function(){ });

Slide 27

Slide 27 text

Gulp, a streaming build system // using cram and uglify to concatenate and minify! gulp.task(‘build-modules', function() {! return cram(paths.run, opts).into("run.js")! .pipe(sourcemaps.init())! .pipe(uglify())! .pipe(sourcemaps.write("./"))! .pipe(gulp.dest('./dist/'));! })!

Slide 28

Slide 28 text

Early feedback for Spring Framework ! • Changed our opinion on Resource Handling • Real client side experience • « Project Sagan: client-side architecture » • « JavaScript modularity, without the buzzwords » Resource Handling in Spring 4.1 • Rossen Stoyanchev & Brian Clozel • Tomorrow 8:30AM

Slide 29

Slide 29 text

Spring Boot, in production > 1 year “Spring Boot lets you pair-program with the Spring team. Josh Long, @starbuxman

Slide 30

Slide 30 text

Evolving spring.io

Slide 31

Slide 31 text

Writing code: JDK8 ! List projectVersions = project.getProjectReleases().stream()! .map(ProjectRelease::getVersion)! .collect(Collectors.toList());

Slide 32

Slide 32 text

Writing code: autoconfiguration ! @EnableAutoConfiguration // <- THIS!! @Configuration! @ComponentScan! public class AppConfiguration {! ! }

Slide 33

Slide 33 text

(indirect use of) @Conditional ! @Conditional(CustomCondition.class)! @Configuration! public class AppConfiguration {! ! }

Slide 34

Slide 34 text

Boot Actuators ! curl spring.io/info! ! curl spring.io/autoconfig! ! curl spring.io/health! ! curl spring.io/beans! ! * some endpoints are protected!

Slide 35

Slide 35 text

Remote shell with CRaSH

Slide 36

Slide 36 text

Distributed team!

Slide 37

Slide 37 text

HipChat +3rd party integrations

Slide 38

Slide 38 text

Issues management: waffle.io

Slide 39

Slide 39 text

Embracing continuous deployment • From first deploy live, SpringOne2GX 2013 • 100+ deploys last 3 months

Slide 40

Slide 40 text

Green/Blue deployments Sagan Blue instances CF Router (golang) Sagan Green instances

Slide 41

Slide 41 text

Green/Blue: Session management? ! • PWS default: sticky sessions • CF java-buildpack: session replication with Redis • No Sessions :-)

Slide 42

Slide 42 text

Green/Blue: DB schema updates? ! • Sagan: FlywayDB • Divide and conquer (read-only flags) • DB Store that fits your needs

Slide 43

Slide 43 text

General Advice: 12factor.net ! • codebase • dependencies • config • concurrency • logs • …

Slide 44

Slide 44 text

What’s next?

Slide 45

Slide 45 text

Sagan - services architecture 45 sagan-site hosted on GET http://spring.io search - get raw guides - render blogs ElephantSQL

Slide 46

Slide 46 text

Sagan guides…

Slide 47

Slide 47 text

…are asciidoctor documents

Slide 48

Slide 48 text

Marketplace services

Slide 49

Slide 49 text

New Relic Java Agent

Slide 50

Slide 50 text

New Relic dashboard

Slide 51

Slide 51 text

Monitoring / Map

Slide 52

Slide 52 text

Sagan error rate

Slide 53

Slide 53 text

Application errors

Slide 54

Slide 54 text

Top transactions

Slide 55

Slide 55 text

First fix: using our CDN

Slide 56

Slide 56 text

Profiling threads

Slide 57

Slide 57 text

Template engine cache… disabled

Slide 58

Slide 58 text

An easy fix!

Slide 59

Slide 59 text

Monitoring transactions

Slide 60

Slide 60 text

Search transactions

Slide 61

Slide 61 text

Checking external services

Slide 62

Slide 62 text

Spring guides transactions

Slide 63

Slide 63 text

Search improvement: change service

Slide 64

Slide 64 text

Guides improvement: shared cache

Slide 65

Slide 65 text

Guides improvement: cache strategy

Slide 66

Slide 66 text

What do you think?

Slide 67

Slide 67 text

What I’ve learned ! • With small or distributed teams: • time spent on managing issues is important • contributor/developer experience is a top priority • Always learn with monitoring, profiling • In cloud environments: • you can throw resources at problems • or use the marketplace (scale better, save money)

Slide 68

Slide 68 text

Sagan is ! • An reference app • An open source project • A space for discussion and experiments • A JDK8, Spring 4, Spring Boot, critical app in production

Slide 69

Slide 69 text

Thanks! @brianclozel