Save 37% off PRO during our Black Friday Sale! »

Spring Boot アプリのシステム情報を 可視化する(not Actuator)/spring-boot-not-actuator

Spring Boot アプリのシステム情報を 可視化する(not Actuator)/spring-boot-not-actuator

M3 tech meetup! #1
http://m3-engineer.connpass.com/event/32205/

で話したスライドです。

422505eb0de893a7a3a21dd466e3b0ba?s=128

sinsengumi

June 08, 2016
Tweet

Transcript

  1. M3 tech meetup! #1 Spring Boot ΞϓϦͷγεςϜ৘ใΛ ՄࢹԽ͢Δʢnot Actuatorʣ ٢ా

    ๎໵ʢΤϜεϦʔגࣜձࣾʣ
  2. M3 tech meetup! #1 ຊ೔͸ M3 tech meetup! ʹ ͓ӽ͠௖͖ɺ੣ʹ͋Γ͕ͱ͏͍͟͝·͢ʂ

  3. 3 ࣗݾ঺հ • ໊લ : ٢ా ๎໵ / @sinsengumi •

    ৬ۀ : ιϑτ΢ΣΞΤϯδχΞ
 Web σβΠφʔ ==> ΤϯδχΞ
 ޷͖ͳݴޠ͸ Java ! • ॴଐ : ΤϜεϦʔגࣜձࣾ • JJUG 2016 Spring Ͱ Spring Boot ͷ࿩Λͨ͠ͷͰɺ
 ͦͪΒ΋ݟͯ௖͚Δͱخ͍͠Ͱ͢ʂ
 https://speakerdeck.com/sinsengumi/spring-boot-application-infrastructure M3 tech meetup! #1
  4. 4 ໨࣍ 1. Spring Boot Actuator ʹ͍ͭͯ 2. Spring Boot

    Actuator ͷΧελϚΠζํ๏ 3. Spring Boot Actuator Λ࢖ΘͣʹγεςϜ৘ใΛՄࢹԽ͢Δ 4. Spring Boot Admin M3 tech meetup! #1
  5. 5 Spring Boot Actuator ʹ͍ͭͯ Spring Boot ͕ Production-ready feature

    ͱݺΜͰ͍Δػೳɻ ΞϓϦέʔγϣϯͷঢ়ଶΛϞχλɺ؅ཧͰ͖ΔΑ͏ʹͳΔɻ HTTP, JMX, SSH Λ࢖ͬͯΞΫηε͕Ͱ͖Δɻ <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> ಋೖ͸ jar ΛೖΕΔ͚ͩʢAuto-configurationʣ M3 tech meetup! #1
  6. 6 Endpoints : mappings @RequestMapping ͷҰཡΛදࣔ͢Δɻ M3 tech meetup! #1

  7. 7 Endpoints : beans Spring Bean ͷҰཡΛදࣔ͢Δɻ M3 tech meetup!

    #1
  8. 8 Endpoints : env ϓϩύςΟͷҰཡΛදࣔ͢Δɻ M3 tech meetup! #1

  9. 9 Endpoints : health ϔϧενΣοΫͷ৘ใΛදࣔ͢Δɻ M3 tech meetup! #1 ϛυϧ΢ΣΞ΋ରԠ͍ͯ͠Δ΋ͷ͕͋Ε͹ɺ

    ࣗಈͰ௥Ճͯ͘͠ΕΔɻ
  10. 10 M3 tech meetup! #1

  11. 11 Spring Boot Actuator ͷΧελϚΠζํ๏ • application.properties • endpoints.* Ͱɺ֤

    Endpoint ͷઃఆ • management.* ͰɺηΩϡϦςΟઃఆ • Endpoint Λ௥Ճ͢Δ • Endpoint ΠϯλϑΣʔεΛ࣮૷͢Δ • health Endpoint ʹ৘ใΛ௥Ճ͢Δ • HealthIndicator ΠϯλϑΣʔεΛ࣮૷͢Δ • info Endpoint ʹ৘ใΛ௥Ճ͢ΔʢSpring Boot 1.4.0 ͔Βɻઆ໌͸ׂѪʣ • InfoContributor ΠϯλϑΣʔεΛ࣮૷͢Δ M3 tech meetup! #1
  12. 12 application.propertiesʢ1ʣ M3 tech meetup! #1 # env ͸࢖༻ෆՄ endpoints.env.enabled=false

    # mappings ͷ PATH มߋ endpoints.mappings.id=routers # shutdown ػೳΛ ON endpoints.shutdown.enabled=true # actuator ͷ context-path Λมߋ management.context-path=/api/management # actuator ͷ port Λมߋ management.port=8081 http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/ #common-application-properties
  13. 13 Endpoint Λ௥Ճ͢Δʢ1ʣ M3 tech meetup! #1 EndpointʢAbstractEndpoint<T>ʣΛ࣮૷͢Δɻ @Component public

    class BatchEndpoint extends AbstractEndpoint<List<Map<String, String>>> { public BatchEndpoint() { super("batch"); } @Override public List<Map<String, String>> invoke() { String taskPackage = "net.sinsengumi.springboot.notactuator.task"; ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true); return provider.findCandidateComponents(taskPackage).stream() .map(bean -> classForName(bean.getBeanClassName())) .flatMap(clazz -> Stream.of(clazz.getDeclaredMethods())) .filter(method -> method.getAnnotation(Scheduled.class) != null) .map(method -> { Scheduled scheduled = method.getAnnotation(Scheduled.class); return ImmutableMap.of( "method", method.toGenericString(), "cron", scheduled.cron()); }) .collect(Collectors.toList()); } }
  14. 14 Endpoint Λ௥Ճ͢Δʢ2ʣ M3 tech meetup! #1 2016-05-29 22:33:07,401 INFO

    [restartedMain] o.s.b.a.e.m.EndpointHandlerMapping (534) - Mapped "{[/api/ management/info || /api/management/info.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2016-05-29 22:33:07,402 INFO [restartedMain] o.s.b.a.e.m.EndpointHandlerMapping (534) - Mapped "{[/api/ management/batch || /api/management/batch.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2016-05-29 22:33:07,402 INFO [restartedMain] o.s.b.a.e.m.EndpointHandlerMapping (534) - Mapped "{[/api/ management/autoconfig || /api/management/autoconfig.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2016-05-29 22:33:08,462 INFO [restartedMain] o.s.b.a.e.j.EndpointMBeanExporter (674) - Located managed bean 'batchEndpoint': registering with JMX server as MBean [org.springframework.boot:type=Endpoint,name=batchEndpoint] 2016-05-29 22:33:08,498 INFO [restartedMain] o.s.b.a.e.j.EndpointMBeanExporter (674) - Located managed bean 'requestMappingEndpoint': registering with JMX server as MBean [org.springframework.boot:type=Endpoint,name=requestMappingEndpoint] 2016-05-29 22:33:08,504 INFO [restartedMain] o.s.b.a.e.j.EndpointMBeanExporter (674) - Located managed bean 'environmentEndpoint': registering with JMX server as MBean [org.springframework.boot:type=Endpoint,name=environmentEndpoint] 2016-05-29 22:33:08,508 INFO [restartedMain] o.s.b.a.e.j.EndpointMBeanExporter (674) - Located managed bean 'healthEndpoint': registering with JMX server as MBean [org.springframework.boot:type=Endpoint,name=healthEndpoint]
  15. 15 Endpoint Λ௥Ճ͢Δʢ3ʣ M3 tech meetup! #1

  16. 16 Endpoint Λ௥Ճ͢Δʢ4ʣ M3 tech meetup! #1

  17. 17 health Endpoint ʹ৘ใΛ௥Ճ͢Δʢ1ʣ M3 tech meetup! #1 HealthIndicatorʢAbstractHealthIndicatorʣΛ࣮૷͢Δɻ @Component

    @ConditionalOnProperty(prefix = "management.health.userAccountService", name = "enabled", matchIfMissing = true) public class UserAccountServiceHealthIndicator extends AbstractHealthIndicator { @Autowired private UserAccountService userAccountService; @Override protected void doHealthCheck(Builder builder) throws Exception { if (userAccountService.healthy()) { builder.up().withDetail("version", "1.0.0"); } else { builder.down().withDetail("version", "1.0.0"); } } }
  18. 18 health Endpoint ʹ৘ใΛ௥Ճ͢Δʢ2ʣ M3 tech meetup! #1 Bean ໊͔Β

    “healthIndicator” Λ੾Γऔͬͨ΋ͷ
  19. 19 Spring Boot Actuator Λ࢖ΘͣʹՄࢹԽ͢Δ • Spring Boot Actuator ͕ग़Δલʢࢲ͕஌Βͳ͔͚͔ͬͨͩ΋ʣ͔Βɺ


    ΦϨΦϨ࣮૷Ͱ΍͍ͬͯͨͷͰ঺հ͍͚ͨͩ͠Ͱ͢ɾɾɾ • URL ͱ͔ Play ͷ routers ϑΝΠϧతʹҰཡͰݟ͍ͨ • DI Container ࢖ͬͯΔͳΒొ࿥͞ΕͯΔ Bean ͷ৘ใݟ͍ͨ • ซͤͯɺSpring Boot Actuator ͕಺෦Ͱ΍͍ͬͯΔ͜ͱ΋ݟ͍ͯ͘ɻ • ΦϨΦϨ࣮૷Ͱ΍͍ͬͯͨ࣌ͱͷࠩ෼ M3 tech meetup! #1
  20. @Controller public class RouterController { @Autowired RequestMappingHandlerMapping handlerMapping; @RequestMapping(value =

    "/admin/system/router", method = RequestMethod.GET) public String routers(Model model) { model.addAttribute("requestMappingInfos", OriginalRequestMappingInfo.of(handlerMapping)); return "screen/admin/system/router"; } @Data public static class OriginalRequestMappingInfo implements Serializable { private Site site; private Set<RequestMethod> methods; private Set<String> patterns; // লུ public static List<OriginalRequestMappingInfo> of(RequestMappingHandlerMapping handlerMapping) { List<OriginalRequestMappingInfo> result = new ArrayList<OriginalRequestMappingInfo>(); for (Entry<RequestMappingInfo, HandlerMethod> e : handlerMapping.getHandlerMethods().entrySet()) { RequestMappingInfo requestMappingInfo = e.getKey(); // লུ result.add(o); } return result; } } } ΦϨΦϨ࣮૷ 20 URL ͷՄࢹԽʢ1ʣ M3 tech meetup! #1 άάͬͨΒɺRequestMappingHandlerMapping ͱ͍͏ͷʹ RequestMapping ͷҰཡ͕ೖ͍ͬͯΔΒ͍͠ɻ
  21. 21 URL ͷՄࢹԽʢ2ʣ M3 tech meetup! #1 Actuator ͷ Endpoint

    ͷ URL ͱ͔ɺ੩తϦιʔεͷ URL ͱ͔ग़͖ͯͯͳ͍ɻ Actuator ͷ mappings Endpoint Ͱ͸શ෦ग़͍ͯͨɻ ͳΜ͔଍Γͳ͍ɾɾʁʁ
  22. 22 URL ͷՄࢹԽʢ3ʣ M3 tech meetup! #1 @ConfigurationProperties(prefix = "endpoints.mappings")

    public class RequestMappingEndpoint extends AbstractEndpoint<Map<String, Object>> implements ApplicationContextAware { private List<AbstractUrlHandlerMapping> handlerMappings = Collections.emptyList(); private List<AbstractHandlerMethodMapping<?>> methodMappings = Collections.emptyList(); @Override public Map<String, Object> invoke() { Map<String, Object> result = new LinkedHashMap<String, Object>(); extractHandlerMappings(this.handlerMappings, result); extractHandlerMappings(this.applicationContext, result); extractMethodMappings(this.methodMappings, result); extractMethodMappings(this.applicationContext, result); return result; } protected void extractHandlerMappings(// লུ) { // লུ } protected void extractMethodMappings(// লུ) { // লུ } } Actuator ͷ࣮૷ΛݟͯΈΔʢRequestMappingEndpointʣ
  23. 23 URL ͷՄࢹԽʢ4ʣ M3 tech meetup! #1 Spring MVC ͷ

    URL ͱ Controller ͸ HandlerMapping Ͱؔ࿈෇͚ΒΕ͍ͯΔɻ ܧঝؔ܎͸ҎԼɻ ΦϨΦϨΫϥεͰ Inject ͍ͯͨ͠΋ͷ RequestMappingEndpoint Ͱ List ͱͯ͠ Inject ͍ͯͨ͠΋ͷ
  24. 24 URL ͷՄࢹԽʢ5ʣ M3 tech meetup! #1 Actuator ͷ HandlerMapping

    ΦϨΦϨΫϥεͰ Inject ͍ͯͨ͠΋ͷɻ ͜ͷ bean ʹ͸ࣗ෼Ͱఆٛͨ͠ @RequestMapping ͕ೖΔ ΦϨΦϨͰ͸ RequestMappingHandlerMapping Λ୯ମͰ Injection ͍ͯͨ͠ҝɺ Actuator ͷ URLʢEndpointHandlerMappingʣ͕ग़ͯ͜ͳ͔ͬͨʢผ Beanʣ List<RequestMappingHandlerMapping> Ͱ Inject ͢Δͱग़ͯ͘Δɻ ʢSpring DI ͷॊೈ͞ͱڧྗ͞ʂʂʣ ※ management.port Ͱผϙʔτʹ͍ͯ͠ΔͱऔಘͰ͖ͳ͍ɻ
  25. 25 URL ͷՄࢹԽʢ6ʣ M3 tech meetup! #1 ͱ͍͏͜ͱͰɺΦϨΦϨ͸࿙Ε͕͋Δ͜ͱ͕Θ͔Γ·ͨ͠ɻ

  26. @Controller public class ContextController { @Autowired private ApplicationContext applicationContext; @RequestMapping(value

    = "/admin/system/context", method = RequestMethod.GET) public String context(Model model) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) applicationContext.getAutowireCapableBeanFactory(); Map<String, BeanDefinition> beanDefinitions = new LinkedHashMap<>(); for (String bd : registry.getBeanDefinitionNames()) { beanDefinitions.put(bd, registry.getBeanDefinition(bd)); } model.addAttribute("context", applicationContext); model.addAttribute("beanDefinitions", beanDefinitions); return "screen/admin/system/context"; } } ΦϨΦϨ࣮૷ 26 Bean ͷՄࢹԽʢ1ʣ M3 tech meetup! #1 ApplicationContext ͔Β bean ͷఆٛʢBeanDefinitionʣΛऔಘͰ͖Δɻ ApplicationContext ΋ Injection Ͱ͖Δɻ
  27. 27 Bean ͷՄࢹԽʢ2ʣ M3 tech meetup! #1 309ݸ

  28. [~] curl http://localhost:8080/api/management/beans | grep '"bean"' | wc -l 287

    28 Bean ͷՄࢹԽʢ3ʣ M3 tech meetup! #1 ͋ΕɺͳΜ͔਺͕ҧ͏ɾɾʁʁ Actuator ͷ beans Endpoint ͷํ͕গͳ͍ɻ Կ͔ϑΟϧλ͞Ε͍ͯΔɾɾʁ Actuator ͷ beans Endpoint ΛݟͯΈΔɻ
  29. 29 Bean ͷՄࢹԽʢ4ʣ M3 tech meetup! #1 Actuator ͷ࣮૷ΛݟͯΈΔʢBeansEndpoint ->

    LiveBeansView.generateJsonʣ protected String generateJson(Set<ConfigurableApplicationContext> contexts) { for (Iterator<ConfigurableApplicationContext> it = contexts.iterator(); it.hasNext();) { ConfigurableApplicationContext context = it.next(); // লུ ConfigurableListableBeanFactory bf = context.getBeanFactory(); String[] beanNames = bf.getBeanDefinitionNames(); for (String beanName : beanNames) { BeanDefinition bd = bf.getBeanDefinition(beanName); if (isBeanEligible(beanName, bd, bf)) { // লུ } } // লུ } return result.toString(); } protected boolean isBeanEligible(String beanName, BeanDefinition bd, ConfigurableBeanFactory bf) { return (bd.getRole() != BeanDefinition.ROLE_INFRASTRUCTURE && (!bd.isLazyInit() || bf.containsSingleton(beanName))); } Role.INFRASTRUCTURE ͱ͔ @Lazy ͱ͔ͰϑΟϧλ͞Ε͍ͯΔ
  30. 30 Bean ͷՄࢹԽʢ5ʣ M3 tech meetup! #1 ͱ͍͏͜ͱͰɺΦϨΦϨͱ Actuator Ͱඍົͳࠩҟ͕͋Δ͜ͱ͕Θ͔Γ·ͨ͠ɻ

    Actuator Ͱ͸ Role.INFRASTRUCTURE (= 2 ) ͕ϑΟϧλ͞Ε͍ͯͨ
  31. 31 Spring Boot Admin υΠπͷ codesentric ͱ͍͏ձ͕ࣾ࡞͍ͬͯΔɻ ෳ਺ͷ Spring Boot

    ΞϓϦΛ؅ཧ͢Δ UI Λఏڙͯ͘͠ΕΔɻ https://github.com/codecentric/spring-boot-admin M3 tech meetup! #1
  32. 32 Spring Boot Admin σϞ M3 tech meetup! #1 ʢ͕࣌ؒ͋Ε͹ʣ

  33. 33 ·ͱΊ M3 tech meetup! #1 • Spring Boot Actuator

    ศརɻΞϓϦͷ͜ͱ͸ΞϓϦʹฉ͘ͷ͕Ұ൪ɻ
 URL Ұཡͱ͔ͷ Excel ͸͍ΒΜ͔ͬͨΜ΍ɻ • த਎͸ DI ίϯςφ͔Β৘ใΛऔͬͯ͘Δͱ͍͏ Spring Β͍͠΍Γํͱɺ
 Auto-configuration Ͱ࣮૷͞Ε͍ͯΔɻ • Spring Boot ΞϓϦͷ্ཱ͕ͪ͛؆୯ա͗ΔͷͰɺ
 Spring Boot Admin ͱ͍͏؅ཧΞϓϦ΋ग़͖ͯͨɻ