Spring Cloud微服务阅读随笔--第2章【微服务构建:Spring Boot】

微服务构建:Spring Boot

    在展开Spring Cloud的微服务架构部署之前,我们先通过本章的内容来了解一下用于构建微服务的基础框架----Spring Boot。对于Spring Boot 已经有深入了解的,可以直接跳过第二章,直接学习Spring Cloud各个组件的使用。

    介绍Spring Boot的目的除了他是Spring Cloud的基础之外,也由于其自身的各项有点:自动化配置快速开发轻松部署等,非常适合用作微服务架构中各项具体微服务的开发框架。

    所以强烈推荐使用Spring Boot来构建微服务,它不仅可以帮助我们快速地搭建微服务,还可以轻松简单地整合Spring Cloud实现系统服务化,而如果使用了传统的Spring 构建方式的话,在整合过程中我们还需要做更多的依赖管理工作才能让它们完好地运行起来。

    为了改善每次新项目就要重复复制粘贴一些差不多的配置文件这样枯燥乏味的事(作为一名优秀的程序员或架构师,我们总会想尽办法来避免这样的重复劳动,比如:通过Maven等构建工具来创建针对不同场景的脚手架工程,在需要新建项目时通过这些脚手架来初始化我们自定义的标准工程,并根据需要做一些简单修改以达到简化原有配置过程的效果。)

    这样的做法虽然减少了工作量,但是这些配置依然大量散布在我们的工程中,虽然大部分情况下我们并不会去修改这些内容

 

    Spring Boot的出现可以有效改善这类问题,其宗旨并非要重写Spring 或是替代Spring 。而是希望通过设计大量的自动化配置等方式来简化Spring 原有样板话的配置,使得开发者可以快速构建应用。

    POMs定义:

      除了解决配置问题置为,Spring Boot还通过一系列Srarter POMS(POM依赖包采用spring-boot-starter-*的方式命名)的定义,让我们整合各项功能的时候,不需要在Maven的pom.xml中维护那些错综复杂的依赖关系,而是通过类似模块化的Starter模块定义来引用,使得依赖管理工作变得更为简单。

     应用轻便(兼容Docker、自带Tomcat):

      在如今容器化大行其道的时代,Spring Boot除了可以很好融入Docker之外,其自身就支持嵌入的Tomcat、Jetty等容器。所以,通过Spring Boot构建的应用不再需要安装Tomcat,将应用打包成war,再部署到Tomcat这样复杂的构建与部署动作,只需将Spring Boot应用打成jar包,并通过Java -jar 命令直接运行就能启动一个标准化的Web应用,这使得Spring Boot应用变得非常快捷。

      在项目依赖dependencies 配置中,包含了下面两项:

       1.spring-boot-starter-web:全栈Web开发模块,包含嵌入式Tomcat、spring MVC

       2.spring-boot-starter-test:通用测试模块,包含JUnit.Hamcrest、Mockito.

      这里所引用的web和test模块,在Spring Boot生态中被称为Starter POMS。Starter POMS是一系列轻便的依赖包,是一套一站式的Spring 相关技术的解决方案。

      

     支持REATful API@RequestMapping("/") ):

      整个Spring Boot的生态系统都使用到了Groovy,很自然的,我们完全可以通过使用Gradle和Groovy来开发Spring Boot应用。比如下面短短的不足100个字符的代码,通过编译打包,使用java -jar命令就能启动一个返回“hello”的RESTful API.

      

1 @RestController
2 class App{
3    @RequestMapping("/")
4    String home(){
5       "hello"
6    }  
7 }

     配置文件:

        Spring Boot的工程结构中,src/main/resources目录是Spring Boot的配置目录,所以当要为应用创建个性化配置时,应在该目录下进行。

        Spring Boot的默认配置文件位置为src/main/resources/application.properties。关于Spring Boot应用的配置内容都可以集中在该文件中。根据我们引入的不同Starter模块,可以在这里定义容器端口号、数据库连接信息、日志级别等各种配置信息。

        比如,我们需要自定义Web模块的服务端口号,可以在application.properties中添加server.port=8888来指定服务端口为8888,也可以通过spring.application.name=hello来指定应用名(该名字在后续Spring Cloud中会被注册为服务名)

        Spring Boot的配置文件除了可以使用传统的properties文件外,还支持现在被广泛推荐使用的YAML文件。

        YAML采用的配置格式不像properties的配置那样以单纯的键值对形式来表示,而是以类似大纲的缩进形式来表示(YAML使用空白符号和分行来分隔资料,其让人最容易上手的特色是巧妙避开各种封闭符号,如引号、各种括号等,这些符号在巢状结构时会变得复杂而难以辨认。)

        

1 enviroments:
2     dev:
3         url:http://dev.bar.com
4         name:Developer Setup
5     prod:
6         url:http://foo.bar.com
7         name:My Cool App

        与其等价的properties配置如下所示:

environment.dev.url=http://dev.bar.com
environment.dev.name=Developer Setup
environment.prod.url=http://foo.bar.com
environment.prod.name=My Cool App

        通过YAML的配置方式我们可以看到,配置信息利用阶梯化缩进的方式,期结构更为清晰易读,同时配置内容的字符量也得到显著减少。除此之外,YAML还可以在一个单个文件中通过使用spring.profiles属性来定义多个不同的环境配置

        例如以下:在指定为test环境时,server.port将使用8882端口;而在prod环境中,server.port将使用8883端口;如果没有指定环境;server.port将使用8881端口。

server:
    port:8881
---
spring:  
    profiles:test
server:
        port:8882
---
spring:
    profiles:prod
server:
    prot:8883

        注意:YAML目前还有一些不足,它无法通过@Propertysource注解来加载配置。但是,YAML将属性加载到内存中保存的时候是有序的,所以当配置文件中的信息需要具备顺序含义时,YAML的配置方式比起properties配置文件更有优势。

    自定义参数: 

      除了可以在Spring Boot的配置文件中设置各个Starter模块中预定义的配置属性,也可以在配置文件中定义一些我们需要的自定义属性。比如在application.properties中添加:

      

book.name=SpringCloudInAction
book.author=yangkang

      然后,在应用中可以通过@Value注解来加载这些自定义的参数,比如:

//把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>
@Component public class Book{ @Value("${book.name}") private String name; @Value("${book.author}") private String author //省略getter 和setter }

      @Value 注解加载属性值的时候可以支持两种表达式来进行配置,如下所示。

        1.一种是上面介绍的PlaceHolder方式,格式为${...},大括号内为PlaceHolder.

        2.另一种是使用SpEL表达式(Spring Expression Language),格式为#{...},大括号内为SpEL表达式。

    参数引用:

      在application.properties中的各个参数之间可以直接通过使用PlaceHolder的方式来进行引用,就像下面的设置:

book.name=SpringCloud
book.author=yangkang
book.desc=${book.author} is writing 《${book.name}》

      book,desc参数引用了上文中定义的book.name和book.author属性,最后该属性的值就是yangkang is writing 《SpringCloud》.

 

    使用随机数:

      在一些特殊情况下,我们希望有些参数每次被加载的时候不是一个固定的值,比如密钥、服务器端口等。在Spring Boot的属性配置文件中,可以通过使用${random} 配置来产生随机的int 值、long值或者string 字符串,

      

${random}的配置方式主要有以下几种,可参考使用
#随机字符串
com.didispace.blog.value=${random.value}

#随机int
com.didispace.blog.number=${random.int}

#随机long
com.didispace.blog.bignumber=${random.long}

#10以内的随机数
com.didispace.blog.test1=${random.int(10)}

#10-20的随机数
com.didispace.blog.test2=${random.int[10,20]}

      改配置方式可以设置应用端口场景,以避免在本地调试时出现端口冲突的麻烦。

 

    命令行参数:

        jar 启动应用,指定应用参数:java -jar xxx.jar --server.port=8888,直接以命令行的方式来设置server.port属性,并将启动应用的端口设为8888.

        在用命令行方式启动Spring Boot应用时,连续的两个减号 - - 就是对application.properties 中的属性值进行赋值的标识。所以,Java - jar xxx.jar --server.port=8888命令,等价于application.properties中添加属性 server.port=8888 

        通过命令行来修改属性值是SpringBoot非常重要的特性。(如果每个参数都需要通过命令行来指定,这显然也不是个好的方案,所以引出在Spring Boot中实现多环境的配置)

  

    多环境配置:

         在Spring Boot中,多环境配置的文件名需要满足 application-{profile}.properties 的格式,其中{profile}对应你的环境标识,如下所示。

        1.application-dev.properties:开发环境

        2.application-test.properties:测试环境

        3.application-prod.properties:生产环境

     

         至于具体哪个配置文件会被加载,需要再application.properties文件中通过spring.profiles.active属性来设置,其值对应配置文件中的{profile}值。如spring.profiles.active=test 就会加载application-test.properties配置文件内容。

        

         多环境配置思路如下:

          1.在application.properties中配置通用内容,并设置spring.profiles.active=dev,以开发环境为默认配置

          2.在application-{profile}.properties中配置各个环境不同的内容。

          3.通过命令行方式激活不同环境的配置(Java- jar xxx.jar -- spring.profiles.active=prod)

    加载顺序:

      随着开发规模的扩大,项目环境的细节需要有各个负责人(QA或是运维)来集中维护这些信息。

      对此,出现了很多讲配置内容外部化的框架和工具,后续的Spring Cloud Config就是其中之一,为了后续能更好地理解Spring Cloud Config的加载机制,我们需要对Spring Boot 对数据文件的加载机制有一定的了解。

      为了能够更合理地重写各属性的值,Spring  Boot使用了下面这种较为特别的属性加载顺序:

        1.在命令行中传入的参数。

        2.SPRING_APPLICATION_JSON中的属性。SPRING_APPLICATION_JSON是以JSON格式配置在系统环境变量中的内容。

        3.Java:comp/env中的Jndi属性。

        4.Java的系统属性,可以通过System.getProperties()获得的内容。

        5.操作系统的环境变量。

        6.通过random.*配置的随机属性。

        7.位于当前应用jar包之外,针对不同{profile}环境的配置文件内容,例如application-{profile}.properties或是YAML定义的配置文件。

        8.位于当前应用jar包之内,针对不同{profile}环境的配置文件内容,例如application-{profile}.properties或是YAML定义的配置文件。

         9.位于当前应用jar包之外的application.properties和YAML配置内容。

        10.位于当前应用jar包之内的application.properties和YAML配置内容。

        11.在@Configuration注解修改的类中,通过@PropertySource注解定义的属性。

        12.应用默认属性,使用SpringApplication.setDefaultProperties定义的内容。

      优先级按上面的顺序由高到低,数字越小优先级越高。

   可以看到,其中第7项和第9项都是从应用jar包之外读取配置文件,所以,实现外部化配置的原理就是从此切入,为其指定外部配置文件的加载位置来取代jar包之内的配置内容。通过这样的实现,我们的工程在配置中就变得非常干净,只需在本地放置开发需要的配置即可,而不用关心其他环境的配置,由其对应环境的负责人去维护即可。

    

    监控与管理spring-boot-starter-actuator:

      在微服务架构中,我们将原本庞大的单体系统拆分成多个提供不同服务的应用。虽然各个应用的内部逻辑因分解而得以简化,但是由于部署应用的数量成倍增长,使得系统的维护复杂度大大提升。对于运维人员来说,随着应用的不断增多,系统集群中出现故障的频率也变得越来越高,虽然在高可用机制的保护下,个别故障不会影响系统的对外服务,但是这些频繁出现的故障需要被及时发现和处理才能长期保证系统处于健康可用状态。为了能对这些成倍增长的应用做到高效运维,传统的运维方式显然是不合适的,所以我们需要实现一套自动化的监控运维机制,而这套机制的运行基础就是不间断地收集各个微服务应用的各项指标情况,并根据这些基础指标信息来制定监控和预警规则,更进一步甚至做到一些自动化的运维操作等。

       当我们决定用Spring Boot来作为微服务框架时,除了它强大的快速开发功能之外,还因为它在Starter POMs中提供了一个特殊依赖模块spring-boot-starter-actuator。引入该模块能够自动为Spring Boot构建的应用提供一系列用于监控的端点。

      同时,Spring Cloud在实现各个微服务组件的时候,进一步为该模块做不少扩展,比如,为原生端点增加了更多的指标和度量信息(比如在整合Eureka的时候会为/health端点增加相关的信息),并且根据不同的组件还提供了更多有空的端点(比如,为API网关组件Zuul提供了/routes端点来返回路由信息)。

      spring-boot-starter-actuator模块的实现对于实施微服务的中小团队来说,可以有效地省去或大大减少监控系统在采集应用指标时的开发量。当然,它也不是万能的,有时候也需要对其做一些简单的扩展来帮助我们实现自身系统个性化的监控需求。

      

     初识actuator(控制台看到console输出端点定义):

      在现有的Spring Boot应用中引入该模块非常简单,只需要在pom.xml的dependency节点中,新增spring-boot-starter-actuator的依赖即可,具体如下:

      

<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-actuator</artifactid>
</dependency>

     增加该依赖之后,重新启动应用。可在控制台看到console输出端点定义,这些端点并非我们自己在程序中创建的,而是由spring-boot-starter-actuator模块根据应用依赖和配置自动创建出来的监控和管理端点。通过这些端点,我们可以实时获取应用的各项监控指标,比如访问/health端点。

 

 

 

     在没有引入其他依赖之前,该端点的内容较为简单,后续我们在使用Spring Cloud的各个组件之后,它的返回会变得非常丰富,这些内容将帮助我们制定更为个性化的监控策略。

 

 

 

 

     原生端点:

      spring-boot-starter-actuator模块中已经实现的一些原生端点,根据端点的作用,可以将原生端点分为以下:

        1.应用配置类:获取应用程序中加载的应用配置、环境变量、自动化配置报告等与Spring  Boot应用密切相关的配置类信息。

        2.度量指标类:获取应用程序运行过程中用于监控的度量指标,比如内存信息、线程池信息、HTTP请求统计等。

        3.操作控制类:提供了对应用的关闭等操作类功能。

      应用配置类:

        Spring Boot 为了改善传统Spring 应用繁杂的配置内容,采用了包扫描自动化配置的机制来加载原本集中于XML中文件中的各项内容。虽然这样的做法让我们的代码变的非常简洁,但是整个应用的实例创建和依赖关系等信息都被离散到了各个配置类的注解上,这是我们分析整个应用资源和实例的各种关系变得非常困难。而这类端点可以帮助我们轻松获取一系列关于Spring 应用配置内容的详细报告,比如自动化配置的报告、Bean创建的报告、环境属性的报告等。

        /autoconfig:该端点用来获取应用的自动化配置报告,其中包括所有自动化配置的候选项。同时还列出了每个候选项是否满足自动化配置的各个先决条件。所以,该端点可以帮助我们方便地找到一些自动化配置为什么没有生效的原因。该报告内容将自动化配置内容分为以下两部分。

          a.positiveMatches中返回的是条件匹配成功的自动化配置。  

          b.negativeMatches中返回的是条件匹配不成功的自动化配置。   

{
    "positveMatches": { // 条件匹配成功的
     "EndpointWebMvcAutoConfiguration": [
      {       "condition": "OnClassCondition",
        "message": "@ConditionalOnClass classes found: javax.servlet.Servlet,org.springframework.web.servlet.DispatcherServlet"
      },
      {
        "condition": "OnWebApplicationCondition", 
        "message": "found web application StandardServletEnvironment"
      }
      ], 
    ...
  },
"negativeMatches": { //条件匹配不成功的
    "HealthindicatorAutoConfiguration.DataSourcesHealthindicatorConfiguration":
    {     "condition": "OnClassCondition",
      "message": "required @ConditionalOnClass classes not found: org.springframework.jdbc.core.JdbcTemplate"
    } ], ... } }

       从如上示例中我们可以看到,每个自动化配置候选项中都有一系列的条件,比如上面没有成功匹配的HealthIndicatorAutoConfiguration.DataSourcesHealth-IndicatorConfiguration配置,它的先决条件是需要在工程中包含org.springframework.jdbc.core.jdbcTemplate类,由于我们没有引入相关的依赖,它就不会执行自动化配置内容。所以,当我们发现有一些期望的配置没有生效时,就可以通过该端点(以下内容)来查看没有生效的具体原因。  

       /beans:该端点用来获取应用上下文中创建的所有Bean.

[  
    {  
        "context": "hello:dev:8881",  
        "parent": null,  
        "beans": [  
            {  
                "bean": "org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration$DispatcherServletConfiguration",  
                "scope": "singleton",  
                "type": "org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration$DispatcherServletConfiguration
3440282b",  
                "resource": "null",  
                "dependencies": [  
                    "serverProperties",  
                    "spring.mvc.CONFIGURATION_PROPERTIES",  
                    "multipartConfigElement"  
                ]  
            },  
            {  
                "bean": "dispatcherServlet",  
                "scope": "singleton",  
                "type": "org.springframework.web.servlet.DispatcherServlet",  
                "resource": "class path resource [org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfiguration$DispatcherServletConfiguration.class]",  
                "dependencies": []  
            }  
        ]  
    }  
]

    在如上示例中,我们可以看到在每个Bean中包含了下面这些信息。

    1. bean:Bean的名称

    2.scope:Bean的作用域

    3.type:Bean的Java类型

    4.resource:class文件的具体路径

    5.dependencies:依赖的Bean名称

 

    /configprops:该端点用来获取应用中配置的属性信息报告。从下面该端点返回示例的片段中,我们看到返回了关于该短信的配置信息,prefix属性代表了属性的配置前缀,properties代表了各个属性的名称和值。所以,我们可以通过该报告来看到各个属性的配置路径,比如我们要关闭该端点,就可以通过使用endpoints.configprops.enabled=false来完成设置。

{  
    "configurationPropertiesReportEndpoint": {  
        "prefix": "endpoints.configprops",  
        "properties": {  
            "id": "configprops",  
            "sensitive": true,  
            "enabled": true  
        }  
    },  
    ...  
}  

      /env:该端点与/configprops不同,它用来获取应用所有可用的环境属性报告。包括环境变量、JVM属性、应用的配置属性、命令行中的参数。从下面该端点返回的示例片段中,可以看到它不仅返回了应用的配置属性、还返回了系统属性、环境变量等丰富的配置信息,其中还包括了应用还没有使用的配置,所以它可以帮助我们方便地看到当前应用可以加载的配置信息,并配合@ConfigurationProperties注解将它们引入到我们的应用程序中来使用。另外,为了配置属性的安全,对于一些类似密码等敏感信息,该端点都会进行隐私保护,但是我们需要让属性名中包含password、secret、key这些关键词,这样该端点在返回它们的时候会使用*来替代实际的属性值。

{  
    "profiles": [  
        "dev"  
    ],  
    "server.ports": {  
        "local.server.port": 8881  
    },  
    "servletContextInitParams": {  
          
    },  
    "systemProperties": {  
        "idea.version": "2016.1.3",  
        "java.runtime.name": "Java(TM) SE Runtime Environment",  
        "sun.boot.library.path": "C:\\Program Files\\Java\\jdk1.8.0_91\\jre\\bin",  
        "java.vm.version": "25.91-b15",  
        "java.vm.vendor": "Oracle Corporation",  
        ...  
    },  
    "systemEnvironment": {  
        "configsetroot": "C:\\WINDOWS\\ConfigSetRoot",  
        "RABBITMQ_BASE": "E:\\tools\\rabbitmq",  
        ...  
    },  
    "applicationConfig: [classpath:/application-dev.properties]": {  
        "server.port": "8881"  
    },  
    "applicationConfig: [classpath:/application.properties]": {  
        "server.port": "8885",  
        "spring.profiles.active": "dev",  
        "info.app.name": "spring-boot-hello",  
        "info.app.version": "v1.0.0",  
        "spring.application.name": "hello"  
    }  
} 

 

       /mapping:该端点用来返回所有Spring MVC的控制器映射关系报告。从下面的示例片段中,我们可以看到该报告的信息与我们在启用Spring MVC的Web应用时输出的日志信息类似,其中bean属性标识了该映射关系的请求处理器,method属性标识了该映射关系的具体处理类和处理函数。

{  
    "/webjars/**": {  
        "bean": "resourceHandlerMapping"  
    },  
    "/**": {  
        "bean": "resourceHandlerMapping"  
    },  
    "/**/favicon.ico": {  
        "bean": "faviconHandlerMapping"  
    },  
    "{[/hello]}": {  
        "bean": "requestMappingHandlerMapping",  
        "method": "public java.lang.String com.didispace.web.HelloController.index()"  
    },  
    "{[/mappings || /mappings.json],methods=[GET],produces=[application/json]}": {  
        "bean": "endpointHandlerMapping",  
        "method": "public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()"  
    },  
    ...  
}  

 

       /info:该端点用来返回一些应用自定义的信息。默认信息下,该端点只会返回一个空的JSON内容。我们可以在application.properties配置文件中通过info前缀来设置一些属性,比如下面这样:

info.app.name=spring-boot-hello  
info.app.version=v1.0.0  

 

       再访问/info端点,我们可以得到下面的返回报告,其中就包含了上面我们在应用中自定义的两个参数:

{  
    "app": {  
        "name": "spring-boot-hello",  
        "version": "v1.0.0"  
    }  
} 

 

   度量指标类

    上面我们所介绍的应用配置类端点所提供的信息报告再应用启动的时候就已经基本确定了其返回内容,可以说是一个静态报告。而度量指标类端点提供的内容则是动态变化的,这些端点提供了应用程序在运行过程中的一些快照信息,比如内存使用情况、HTTP请求统计、外部资源指标等。这些端点对于我们构建微服务架构中的监测系统非常有帮助,由于Spring Boot应用自身实现了这些端点,所以我们可以很方便地利用它们来收集我们想要的信息,以指定出各种自动化策略。下面,我们就来分别看看这些强大的端点功能。

    /metrics:该端点用来返回当前应用的各类重要度量指标,比如内存信息、线程信息、垃圾回收信息等。

{  
  "mem": 541305,  
  "mem.free": 317864,  
  "processors": 8,  
  "instance.uptime": 33376471,  
  "uptime": 33385352,  
  "systemload.average": -1,  
  "heap.committed": 476672,  
  "heap.init": 262144,  
  "heap.used": 158807,  
  "heap": 3701248,  
  "nonheap.committed": 65856,  
  "nonheap.init": 2496,  
  "nonheap.used": 64633,  
  "nonheap": 0,  
  "threads.peak": 22,  
  "threads.daemon": 20,  
  "threads.totalStarted": 26,  
  "threads": 22,  
  "classes": 7669,  
  "classes.loaded": 7669,  
  "classes.unloaded": 0,  
  "gc.ps_scavenge.count": 7,  
  "gc.ps_scavenge.time": 118,  
  "gc.ps_marksweep.count": 2,  
  "gc.ps_marksweep.time": 234,  
  "httpsessions.max": -1,  
  "httpsessions.active": 0,  
  "gauge.response.beans": 55,  
  "gauge.response.env": 10,  
  "gauge.response.hello": 5,  
  "gauge.response.metrics": 4,  
  "gauge.response.configprops": 153,  
  "gauge.response.star-star": 5,  
  "counter.status.200.beans": 1,  
  "counter.status.200.metrics": 3,  
  "counter.status.200.configprops": 1,  
  "counter.status.404.star-star": 2,  
  "counter.status.200.hello": 11,  
  "counter.status.200.env": 1  
}  

 

  从上面的示例中,我们看到有如下这些重要的度量值。

    1.系统信息:包括处理器数量processors、运行时间uptime和instance.uptime、系统平均负载systemload.average.

    2.mem.*:内存概要信息,包括分配给应用的总内存数量以及当前空闲的内存数量。这些信息来自java.lang.runtime.

    3.heap.*:堆内存使用情况。这些信息来自java.lang.management.MemoryMXBean接口中getHeapMemoryUsege方法获取的java.lang.management.MemoryUsage.

    4.nonheap.*:非堆内存使用情况。这些信息来自java.lang.management.MemoryMXBean接口中getNonHeapMemoryUsage方法获取的java.lang.management.MemoryUsage.

    5.threads.*:线程使用情况,包括线程数、守护线程数(daemon)、线程峰值(peak)等,这些数据均来自java.lang.management.ThreadMXBean.

    6.classes.*:应用加载和卸载的类统计。这些数据均来自java.lang.management.ClassLoadingMXBean.

    7.gc.*垃圾收集器的详细信息,包括垃圾回收次数 gc.ps_scavenge.count、垃圾回收消耗时间 gc.ps_scavenge.time、标记-清除算法的次数 gc.ps_marksweep.count、标记-清除算法的消耗时间 gc.ps_marksweep.time.这些数据均来自java.lang.management.GarbageCollectorMXBean.

    8.httpsessions.*:Tomcat 容器的会话使用情况。包括最大会话数httpsessions.max和活跃会话数httpsessions.active.该度量指标信息仅在引入嵌入式Tomcat作为应用容器的时候才会提供。

 

      9.gauge.*:HTTP请求的性能指标之一,它主要用来反映一个绝对数值。比如上面示例中的gauge.response.hello:5,它表示上一次hello请求的延迟时间为5毫秒。

      10.counter.*:HTTP请求的性能指标之一,它主要作为计数器来使用,记录了增加量和减少量。上述示例中的counter.status.200.hello:11,它代表了hello请求返回200状态的次数为11。

@RestController  
public class HelloController {  
      
    @Autowired  
    private CounterService counterService;  
    @RequestMapping("/hello")  
    public String greet() {  
        counterService.increment("didispace.hello.count");  
        return "";  
    }  
    
} 

      /metrics端点可以提供应用运行状态的完整度量指标报告,这项功能非常实用,但是对于监控系统中的各项监控功能,它们的监控内容、数据收集频率都有所不同,如果每次都通过全量获取报告的方式来收集,略显粗暴。所以,我们还可以通过/metrics/{name}接口来更细粒度地获取度量信息,比如可以通过访问/metrics/mem.free来获取可用内存数量。

 

     /health:该端点在一开始的示例中我们已经使用过了,它用来获取应用的各类健康指标信息。在spring-boot-starter-actuator模块中自带实现了一些长常用资源的健康指标检测器。这些检测器都通过HeathIndicator接口实现,并且会根据依赖关系的引入实现自动化装配,比如下面列出的这些。

   

 

     有时候,我们可能还会用到一些Spring Boot的startPoms中还没有封装的产品来进行开发,比如,当使用Rocket MQ作为消息代理时,由于没有自动化配置的检测器,所以需要自己来实现一个用来采集健康信息的监测器。我们可以在SpringBoot的应中,为org.springframework.boot.actuate.health.Healthindicator接口实现一个对Rocket MQ的监测器类:

@Component  
public class RocketMQHealthIndicator implements HealthIndicator {  
    @Override  
    public Health health() {  
        int errorCode = check();  
        if (errorCode != 0) {  
          return Health.down().withDetail("Error Code", errorCode).build();  
        }  
        return Health.up().build();  
    }  
    private int check() {  
        // 对监控对象的检测操作  
    }  
}  

 

     通过重写health()函数可实现健康检查,在返回的health对象中,共有两项内容,一个是状态信息,除了该示例中的UP与DOWN之外,还有UNKNOWN和OUT_OF_SERVICE,可以根据需要来实现返回:还有一个详细信息,采用Map的方式存储,在这里通过withDetail函数,注入了一个Error Code信息,我们也可以填入其他信息,比如,检测对象的IP地址、端口等:

"rocketMQ": {  
  "status": "UP"  
} 

 

     /dump:该端点用来暴露程序运行中的线程信息。它使用java.lang.management.ThreadMXBean的dumpAllThreads方法来返回所有含有同步信息的活动线程详情。

     /trace:该端点用来返回基本的HTTP跟踪信息。默认情况下,跟踪信息的存储采用org.springframework.boot.actuate.trace.InMemoryTraceRepository实现的内存方式,始终保留最新的100条请求记录。他记录的内容格式如下所示:

[  
    {  
        "timestamp": 1482570022463,  
        "info": {  
            "method": "GET",  
            "path": "/metrics/mem",  
            "headers": {  
                "request": {  
                    "host": "localhost:8881",  
                    "connection": "keep-alive",  
                    "cache-control": "no-cache",  
                    "user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",  
                    "postman-token": "9817ea4d-ad9d-b2fc-7685-9dff1a1bc193",  
                    "accept": "*/*",  
                    "accept-encoding": "gzip, deflate, sdch",  
                    "accept-language": "zh-CN,zh;q=0.8"  
                },  
                "response": {  
                    "X-Application-Context": "hello:dev:8881",  
                    "Content-Type": "application/json;charset=UTF-8",  
                    "Transfer-Encoding": "chunked",  
                    "Date": "Sat, 24 Dec 2016 09:00:22 GMT",  
                    "status": "200"  
                }  
            }  
        }  
    },  
    ...  
]  

 

    操作控制类

     “初识actuator”小节中的示例的控制台汇总输出的所有监控端点,已经在介绍【应用配置类】和【度量指标类端点】时都讲解完了

     实际还有哪些是操作控制类端点呢?实际上,由于之前介绍的所有端点都是用来反映应用自身的属性或是运行中的状态,相对于操作控制类端点没有那么敏感,所以它们都是默认启动用的

     而操作控制类端点拥有更强大的控制能力,如果要使用它们的话,需要通过属性来配置开启操作。

     在原生端点汇总,只提供了一个用来关闭应用的端点:/shutdown(在后续我们引入了Eureka之后,会引入更多控制端点)。可以通过如下配置开启它:endopoints.shutdown.enabled=true

     在配置了上述属性之后,只需要访问该应用的/shutdown端点就能实现关闭该应用的远程操作。由于开放关闭应用的操作本身是一件非常危险的事,所以真正在线上使用的时候,需要对其加入一定的保护机制比如定制actuator的端点路径、整合Spring Security进行安全校验等。

  小结

    本章通过构建一个最基本的Spring Boot工程有一个最直观的感受。同时,也为后续构建各类Spring Cloud组件和微服务应用做了一些基础准备工作。另外,我们对Spring Boot 中的配置原理以及监控管理做了深入的介绍,因为这些内容将在后续的介绍中有所涉及,并且它们有助于理解Spring Cloud组件的运行原理。关于Spring Boot的微服务内容感兴趣的可以另做阅读。

 

 

恭喜,本章完!

posted @ 2022-02-24 13:55  风掠杨柳很强大  阅读(51)  评论(0编辑  收藏  举报