上一篇:《SpringCloud01—基础知识》
在构建springCloud框架之前,先通过本章了解一下用于构建微服务的基础框架–springBoot
在如今容器化大行其道的时代,Spring Boot除了可以很好融入Docker之外,其自身就支持嵌入式的Tomcat、Jetty 等容器。所以,通过Spring Boot构建的应用不再需要安装Tomcat,将应用打包成war,再部署到Tomcat这样复杂的构建与部署动作,只需将SpringBoot应用打成jar包,并通过java -jar命令直接运行就能启动一个标准化的Web应用,这使得Spring Boot应用变得非常轻便。
按照以上步骤便可以快速搭建一个springBoot的web项目,目录结构如下所示
打开当前工程下的pom.xml文件,可以看到一下内容
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.3.4.RELEASEversion>
<relativePath/>
parent>
<groupId>com.cloudgroupId>
<artifactId>demoartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>demoname>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>11java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
之前所介绍的,Spring Boot默认将该Web应用打包为jar的形式,而非 war的形式,因为默认的Web模块依赖会包含嵌入式的Tomcat,这样使得我们的应用jar自身就具备了提供Web服务的能力,后续我们会演示如何启动它。
父项目parent配置指定为spring-boot-starter-parent,该父项目中定义了Spring Boot版本的基础依赖以及一些默认配置内容,比如,配置文件application.properties的位置等。
在项目依赖dependencies配置中,包含了下面两项:
在Spring Boot中创建一个RESTful API的实现代码同Spring MVC应用一样,只是不需要像Spring MVC那样先做很多配置,而是像下面这样直接开始编写Controller内容:
@RestController
public class HelloController {
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public String inde(){
return "Hello SpringCloud";
}
}
在Spring Boot中实现单元测试同样非常方便,下面我们打开src/test/下的测试入口com.cloud.demo.DemoApplicationTests类,编写一个简单的单元测试来模拟HTTP请求,测试之前实现的/hello接口,该接口应返回Hello world字符串。
具体代码实现如下所示。
@SpringBootTest
class DemoApplicationTests {
private MockMvc mvc;
@Before
public void setUp() throws Exception {
mvc = MockMvcBuilders.standaloneSetup(new HelloController()).build();
System.out.println("初始化mock模块");
}
@Test
void hello() throws Exception {
setUp();
String responseString = mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk()) //返回的状态是200
.andDo(print()) //打印出请求和相应的内容
.andReturn().getResponse().getContentAsString(); //将相应的数据转换为字符串;
System.out.println("获取结果为:" + responseString);
}
}
在快速入门示例中,我们介绍 Spring Boot的工程结构时,提到过 src/main/resources目录是Spring Boot的配置目录,所以当要为应用创建个性化配置时,应在该目录下进行。
Spring Boot的默认配置文件位置为src/main/resources/application.properties。关于SpringBoot应用配置内容都可以集中在该文件中,根据我们引用的Starter模块不同,可以在这里定义容器端口号,数据库连接信息、日志级别等。
比如,我们需要自定义Web模块的服务端口号,可以在application.properties中添加server.port=8888来指定服务端口为8888 ,也可以通过spring.application.name=hello来指定应用名(该名字在后续Spring Cloud中会被注册为服务名)。
Spring Boot的配置文件除了可以使用传统的properties文件之外,还支持现在被广泛推荐使用的YAML文件。
YAML采用的配置格式不像properties 的配置那样以单纯的键值对形式来表示,而是以类似大纲的缩进形式来表示。下面是一段YAML 配置信息:
environments:
dev:
url: http://dev.bar.com
name: Developer Setep
prod:
url: http://foo.bar.com
name: My Cool App
与其等价的properties配置如下:
environments.dev.url= http://dev.bar.com
environments.dev.name= Developer Setep
environments.prod.url= http://foo.bar.com
environments.prod.name= My Cool App
虽然通过YAML的配置方式我们可以看到,配置信息利用阶梯化缩进的方式,其结构更为清晰易读,同时配置内容的字符量也得到显著减少。但是YAML目前还有一些不足,它无法通过@PropertySource注解来加载配置。
值得注意的是,YAML将属性加载到内存中保存的时候是有序的,所以当配置文件中的信息需要具备顺序含义时,YAML 的配置方式比起properties 配置文件更有优势。
除了可以在Spring Boot 的配置文件中设置各个Starter模块中预定义的配置属性,也可以在配置文件中定义一些我们需要的自定义属性。比如在 application.properties中添加:
book.name=SpringCloud
book.auth=ninesun
然后在实体类中使用@Value注解加载这些参数
@Component
public class Book {
@Value("${book.name}")
private String name;
@Value("${book.auth}")
private String auth;
}
在application.properties 中的各个参数之间可以直接通过使用PlaceHolder的方式来进行引用,就像下面的设置:
book.name=SpringCloud
book.auth=ninesun
book.desc=${book.name} is writing 《${book.name}》
book.desc参数引用了上文中定义的book.name和 book.author属性,最后该属性的值就是ninesun is writing 《springCloud》。
在一些特殊情况下,我们希望有些参数每次被加载的时候不是一个固定的值,比如密钥、服务端口等。在 Spring Boot的属性配置文件中,可以通过使用$ {random}配置来产生随机的int 值、long值或者string字符串,这样我们就可以容易地通过配置随机生成属性,而不是在程序中通过编码来实现这些逻辑。
# 随机字符串
com.cloud.demo.value=${random.value}
# 随机int
com.cloud.demo.number=${random.int}
# 随机long
com.cloud.demo.bignumber=${random.long}
# 10以内的随机数
com.cloud.demo.test1=${random.int(10)}
# 10-20的随机数
com.cloud.demo.test2=${random.int[10,20])}
我们在开发应用的时候,通常同一套程序会被应用和安装到几个不同的环境中,比如开发、测试、生产等。其中每个环境的数据库地址、服务器端口等配置都不同,如果在为不同环境打包时都要频繁修改配置文件的话,那必将是个非常烦琐且容易发生错误的事。
对于多环境的配置,各种项目构建工具或是框架的基本思路是一致的,通过配置多份不同环境的配置文件,再通过打包命令指定需要打包的内容之后进行区分打包,Spring Boot也不例外,或者说实现起来更加简单。
在Spring Boot中,多环境配置的文件名需要满足application-{profile } .properties的格式,其中{profile }对应你的环境标识,如下所示。
所以我们如果想添加其他环境只需要在application-x 来配置,然后在application.properties文件中进行激活即可
在微服务架构中,我们将原本庞大的单体系统拆分成多个提供不同服务的应用。虽然各个应用的内部逻辑因分解而得以简化,但是由于部署应用的数量成倍增长,使得系统的维护复杂度大大提升。对于运维人员来说,随着应用的不断增多,系统集群中出现故障的频率也变得越来越高,虽然在高可用机制的保护下,个别故障不会影响系统的对外服务,但是这些频繁出现的故障需要被及时发现和处理才能长期保证系统处于健康可用状态。为了能对这些成倍增长的应用做到高效运维,传统的运维方式显然是不合适的,所以我们需要实现一套自动化的监控运维机制,而这套机制的运行基础就是不间断地收集各个微服务应用的各项指标情况,并根据这些基础指标信息来制定监控和预警规则,更进一步甚至做到一些自动化的运维操作等。
为了让运维系统能够获取各个微服务应用的相关指标以及实现一些常规操作控制,我们需要开发一套专门用于植入各个微服务应用的接口供监控系统采集信息。而这些接口往往有很大一部分指标都是类似的,比如环境变量、垃圾收集信息、内存信息、线程池信息等。既然这些信息那么通用,难道就没有一个标准化的实现框架吗?
当我们决定用Spring Boot来作为微服务框架时,除了它强大的快速开发功能之外,还因为它在Starter POMs中提供了一个特殊依赖模块spring-boot-starter-actuator。引入该模块能够自动为Spring Boot构建的应用提供系列用于监控的端点。
同时,SpringCloud 在实现各个微服务组件的时候,进一步为该模块做了不少扩展,比如,为原生端点增加了更多的指标和度量信息(比如在整合 Eureka的时候会为/health端点增加相关的信息),并且根据不同的组件还提供了更多有空的端点(比如,为API网关组件Zuul提供了/routes端点来返回路由信息)。
spring-boot-starter-actuator模块的实现对于实施微服务的中小团队来说,可以有效地省去或大大减少监控系统在采集应用指标时的开发量。当然,它也并不是万能的,有时候也需要对其做一些简单的扩展来帮助我们实现自身系统个性化的监控需求。所以,在本节将详细介绍一些关于spring-boot-starter-actuator模块的内容,包括原生提供的端点以及一些常用的扩展和配置方式等。
添加依赖即可引入
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
说明监控页面的基地址是/actuator,我们在浏览器端打开地址http://localhost:1111/actuator/,可以看到
通过在快速入门示例中添加 spring-boot-starter-actuator模块,我们已经对它有了一个初步的认识。接下来,我们详细介绍一下spring-boot-starter-actuator模块中已经实现的一些原生端点。根据端点的作用,可以将原生端点分为以下三大类:
management.endpoints.web.exposure.include=*
由于Spring Boot为了改善传统Spring应用繁杂的配置内容,采用了包扫描和自动化配置的机制来加载原本集中于XML 文件中的各项内容。虽然这样的做法让我们的代码变得非常简洁,但是整个应用的实例创建和依赖关系等信息都被离散到了各个配置类的注解上,这使我们分析整个应用中资源和实例的各种关系变得非常困难。
而这类端点可以帮助我们轻松获取一系列关于Spring应用配置内容的详细报告,比如自动化配置的报告、Bean 创建的报告、环境属性的报告等。
/conditions:该端点用来获取应用的自动化配置报告,其中包括所有自动化配置的候选项。同时还列出了每个候选项是否满足自动化配置的各个先决条件。所以,该端点可以帮助我们方便地找到一些自动化配置为什么没有生效的具体原因。该报告内容将自动化配置内容分为以下两部分。
访问链接:http://localhost:1111/actuator/conditions
/beans:该端点用来获取应用上下文中创建的所有Bean
访问链接:http://localhost:1111/actuator/beans
在如上示例中,我们可以看到在每个Bean中都包含了下面这些信息。
还有很多端点,此处就不一一列举有需要可以自行去了解。
下一篇:《SpringCloud03—服务治理:SpringCloud Eureka》