Upgrade to Pro — share decks privately, control downloads, hide ads and more …

WJAX 2015 Boot your own Infrastructure - Spring...

WJAX 2015 Boot your own Infrastructure - Spring Boot erweitern

Im Zuge des Hypethemas Microservices ist auch Spring Boot zum Gesprächsthema geworden. Dabei ist Spring Boot viel mehr als nur ein Microservices-Framework. In dieser Session wird in fünf Schritten gezeigt, wie man einen eigenen Spring Boot Starter schreibt, um genau die Infrastruktur zu booten, die der eigene Typ Anwendung benötigt – ein sehr nützliches Werkzeug auch im Enterprise-Umfeld, in dem man üblicherweise viele Anwendungen eines bestimmten Typs hat und proprietäre Technologien verwendet werden.

Avatar for tobiasflohre

tobiasflohre

November 04, 2015
Tweet

More Decks by tobiasflohre

Other Decks in Programming

Transcript

  1. Tobias Flohre | codecentric AG Dennis Schulte | codecentric AG

    Boot your own Infrastructure Spring Boot erweitern
  2. Agenda Intro Spring Boot Eigener Spring Boot Starter – Warum?

    Eigener Spring Boot Starter – Wie? Client-Server-Architektur Erweiterbarkeit von Spring Boot Komponenten Fazit 4
  3. Agenda Intro Spring Boot Eigener Spring Boot Starter – Warum?

    Eigener Spring Boot Starter – Wie? Client-Server-Architektur Erweiterbarkeit von Spring Boot Komponenten Fazit 5
  4. Intro Spring Boot Spring Boot makes it easy to create

    stand-alone, production-grade Spring based Applications that you can "just run".
  5. Intro Spring Boot Spring Boot makes it easy to create

    stand-alone, production-grade Spring based Applications that you can "just run". Spring Boot Starter liefern Dependencies liefern Konfiguration einfach erweiterbar
  6. Intro Spring Boot Spring Boot makes it easy to create

    stand-alone, production-grade Spring based Applications that you can "just run". Embedded Servlet Container Start per main-Methode Startfähiges Fat-Jar java –jar app.jar
  7. Intro Spring Boot Spring Boot makes it easy to create

    stand-alone, production-grade Spring based Applications that you can "just run". Monitoring Properties Remote Shell CRaSH
  8. Agenda Intro Spring Boot Eigener Spring Boot Starter – Warum?

    Eigener Spring Boot Starter – Wie? Client-Server-Architektur Erweiterbarkeit von Spring Boot Komponenten Fazit 10
  9. Eigener Spring Boot Starter – Warum? Ja, warum eigentlich? Viele

    Anwendungen gleichen Typs • Intranet-Web • Kundenportal-Web • Batch • App-Rest Default-Stacks 11
  10. Eigener Spring Boot Starter – Warum? Und warum eigentlich nicht?

    Share nothing? Microservices vs. Microservices, but Autonomie vs. Wiederverwendung Keine Fachlichkeit in Frameworks! Veröffentlichung auf github 12
  11. Eigener Spring Boot Starter – Warum? Fehlende Unterstützung für eine

    offen verfügbare Technologie Fehlende Unterstützung für eine eigene, proprietäre Technologie / ein eigenes Framework Eigene Vorgaben / Defaults Automatische Konfiguration von Infrastruktur- / Businesslogik 13
  12. Eigener Spring Boot Starter – Warum? Unser persönlicher Anwendungsfall: Batch

    14 Servlet Container Anwendung Batch Application HTTP Endpoint Scheduler Job- Metadaten Logs Cron-Job Workflow-System
  13. Eigener Spring Boot Starter – Warum? HTTP-Endpoints Job-Start Status Job-Stop

    Logfile / Protokoll Laufende Jobs Deployed Jobs Job-Execution- Details Logging Logfile pro Job- Execution Thread-Local Protokoll Einheitliches Format Kerndaten des Joblaufs Revisionssichere Ablage Metrics Test- Unterstützung Test-Ressourcen In-Memory Zähler Summen Transaktionssicher
  14. Agenda Intro Spring Boot Eigener Spring Boot Starter – Warum?

    Eigener Spring Boot Starter – Wie? Client-Server-Architektur Erweiterbarkeit von Spring Boot Komponenten Fazit 17
  15. Eigener Spring Boot Starter – Wie? 1. Wähle eine Basis

    aus existierenden Spring Boot Startern spring-boot-starter-web spring-boot-starter-batch spring-boot-starter-jdbc spring-boot-starter-actuator
  16. Eigener Spring Boot Starter – Wie? 2. Eigene Konfiguration und

    Auto-Configuration META-INF/spring.factories org.springframework.boot.autoconfigure.EnableAutoConfiguration= de.codecentric.batch.configuration.BatchWebAutoConfiguration
  17. Eigener Spring Boot Starter – Wie? 3. Konfigurierbarkeit durch Properties

    @Value("${batch.max.pool.size:5}") private int maxPoolSize; @Bean public TaskExecutor taskExecutor() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setMaxPoolSize(maxPoolSize); taskExecutor.afterPropertiesSet(); return taskExecutor; }
  18. Eigener Spring Boot Starter – Wie? 4. Erweiterbarkeit durch überschreibbare

    Default-Implementierungen @ConditionalOnMissingBean(BatchConfigurer.class) @Configuration public class TaskExecutorBatchConfigurer implements BatchConfigurer {} public interface BatchConfigurer { JobRepository getJobRepository() throws Exception; PlatformTransactionManager getTransactionManager() throws Exception; JobLauncher getJobLauncher() throws Exception; JobExplorer getJobExplorer() throws Exception; }
  19. Eigener Spring Boot Starter – Wie? 5. Abhängigkeit von Klassenpfad

    und Ressourcen @ConditionalOnClass(name = "javax.persistence.EntityManagerFactory") @ConditionalOnMissingBean(BatchConfigurer.class) @Configuration protected static class JpaBatchConfiguration {} @ConditionalOnMissingClass @ConditionalOnResource @ConditionalOnWebApplication @ConditionalOnExpression @ConditionalOnProperty
  20. Client-Server-Architektur 24 Verteilte Architektur Server Spring Boot Application Spring Boot

    Application Spring Boot Application Mögliche Use Cases: Service Registry Zentrales Monitoring Zentrale Authentifizierung/ Autorisierung usw.
  21. Spring Boot Admin 27 Actuator Endpoints (z.B. Health) { "status"

    : "UP", "diskSpace" : { "status" : "UP", "free" : 26665549824, "threshold" : 10485760 }, "db" : { "status" : "UP", "batchDataSource" : { "status" : "UP", "database" : "Oracle", "hello" : 1 }, } }
  22. Spring Boot Admin 30 Architektur (Service Registrierung) Spring Boot Admin

    Server Spring Boot Application GUI HTTP Spring Boot Application Spring Boot Application register
  23. Spring Boot Admin 31 Architektur (Client Kommunikation) Spring Boot Admin

    Server Spring Boot Application GUI HTTP Spring Boot Application Spring Boot Application check Health Zuul
  24. Spring Boot Admin 32 Server @Configuration @EnableAutoConfiguration @EnableAdminServer public class

    Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
  25. Spring Boot Admin 33 /** * @author Dennis Schulte */

    @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(AdminServerImportSelector.class) public @interface EnableAdminServer { }
  26. Spring Boot Admin 34 public class AdminServerImportSelector implements DeferredImportSelector {

    @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[] { MailNotifierConfiguration.class.getCanonicalName(), HazelcastStoreConfiguration.class.getCanonicalName(), AdminServerWebConfiguration.class.getCanonicalName(), DiscoveryClientConfiguration.class.getCanonicalName(), RevereseZuulProxyConfiguration.class.getCanonicalName() }; } }
  27. Spring Boot Admin 35 @Configuration public class AdminServerWebConfiguration extends WebMvcConfigurerAdapter

    implements ApplicationContextAware { /** * @return Default registry for all registered application. */ @Bean public ApplicationRegistry applicationRegistry() { return new ApplicationRegistry(applicationStore); } [...] }
  28. Spring Boot Admin 38 Architektur mit Eureka Spring Boot Admin

    Server Spring Boot Application GUI Spring Boot Application Spring Boot Application register Eureka
  29. Spring Boot Admin 39 Eureka: Discovery durch Server @Configuration @EnableAutoConfiguration

    @EnableDiscoveryClient @EnableAdminServer public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } eureka.instance.client.serviceUrl=http://service-registry:8761/eureka
  30. Health • Eigene Implementierung public class BackendHealthIndicator extends AbstractHealthIndicator{ @Override protected

    void doHealthCheck(Health.Builder builder) { if(isBackendAvailable(url)){ builder.up(); }else{ builder.down(); } } } 43
  31. Metrics public interface GaugeService { /** * Set the specified

    gauge value * @param metricName the name of the gauge to set * @param value the value of the gauge */ void submit(String metricName, double value); } 47
  32. Metrics 48 Unser Use Case: Java Batch - Datenmigration • 

    Joblaufzeiten vergleichen •  Langläufer? •  Wo geht die Zeit verloren?
  33. Metrics @Aspect public class ReaderProcessorWriterMetricsAspect { @Around("execution(* org.springframework.batch.item.ItemReader.read(..))") public Object

    profileReadMethods(ProceedingJoinPoint pjp) { StopWatch stopWatch = startStopWatch(); try { return pjp.proceed(); } finally { gaugeService.submit(getIdentifier(), getMillis(stopWatch)); } } } 49
  34. Metrics Job- und Step-Laufzeiten Metric [name=timer.batch.example-job.duration, value=2592.0, timestamp=Wed Oct 28

    07:56:35 CET 2015] Metric [name=timer.batch.example-job.step1.duration, value=2519.0, timestamp=Wed Oct 28 07:56:35 CET 2015] Aspects Metric [name=timer.batch.example-job.step1.DummyItemReader.read, value=10.0, timestamp=Wed Oct 28 07:56:35 CET 2015] Metric [name=timer.batch.example- job.step1.ExampleService.callExternalRemoteService, value=569.0, timestamp=Wed Oct 28 07:56:35 CET 2015] Metric [name=timer.batch.example-job.step1.LogItemProcessor.process, value=569.0, timestamp=Wed Oct 28 07:56:35 CET 2015] Metric [name=timer.batch.example-job.step1.LogItemWriter.write, value=41.0, timestamp=Wed Oct 28 07:56:35 CET 2015] 51
  35. Metrics Eigene Exporter @Bean @ConditionalOnProperty("batch.metrics.export.console.enabled") @ConditionalOnClass(ConsoleReporter.class) public Exporter consoleExporter() {

    return new ConsoleMetricsExporter(metricRegistry); } @Bean @ConditionalOnProperty("batch.metrics.export.graphite.enabled") @ConditionalOnClass(name="com.codahale.metrics.graphite.GraphiteReporter") public Exporter graphiteExporter() { return new GraphiteMetricsExporter(metricRegistry, metricReader, server, port); } 54