前面的章节我们讲了WebFlux 的原理与运用。本节,继续微服务专题的内容分享,共计16小节,分别是:
本节内容重点为:
/restart
、生命周期:/pause
、/resume
等Spring Cloud致力于为典型的用例和扩展机制提供良好的开箱即用体验,以涵盖其他用例。
SpringCloud (Greenwich.SR5) 云原生官方文档
Cloud Native 是一种应用程序开发样式,鼓励在持续交付和价值驱动型开发领域轻松采用最佳实践。一个相关的学科是构建 12要素 应用程序,其中开发实践与交付和运营目标保持一致-例如,通过使用声明性编程,管理和监视。Spring Cloud通过多种特定方式促进了这些开发风格。起点是一组功能,分布式系统中的所有组件都需要轻松访问这些功能。
Spring Cloud构建于其中的Spring Boot涵盖了许多这些功能。Spring Cloud作为两个库提供了更多功能:Spring Cloud上下文和Spring Cloud Commons。Spring Cloud Context为ApplicationContextSpring Cloud应用程序提供实用程序和特殊服务(引导上下文,加密,刷新作用域和环境端点)。Spring Cloud Commons是在不同Spring Cloud实现中使用的一组抽象和通用类(例如Spring Cloud Netflix和Spring Cloud Consul)。
什么是云原生?有哪些发展方向?终于有人讲明白了!
ApplicationContext
工欲善其事必先利其器!学好 Spring Cloud 需要 Spring Boot 基础,而学好 Spring Boot 需要深刻理解 Spring Framework。Spring 应用上下文又是整个 Spring 框架非常重要的一环。
在前面的章节我们多次提到了 Spring 应用上下文 ApplicationContext
,另外我们在本系列的第一节也提到了注解 Component
“派生性”。那么这其中又有什么联系呢?我们又该如何理解 Spring 应用上下文的层次呢?
回顾一下 Spring 事件 中关键的几个类:
事件类:ApplicationEvent
事件监听器: ApplicationListener
事件广播器:ApplicationEventMulticaster
与其唯一实现类 SimpleApplicationEventMulticaster
事件发送器:ApplicationEventPublisher
Q:BeanFactory
与 ApplicationContext
类层次性:
A:我们看ApplicationContext
这个类,它扩展 ListableBeanFactory
以及 HierarchicalBeanFactory
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
...
}
从结构而言,ApplicationContext
关联了 BeanFactory
实现。ApplicationContext
的抽象实现类 AbstractRefreshableApplicationContext
就包含了属性 beanFactory DefaultListableBeanFactory
实际上就是 AppliationContext
继承 BeanFactoy
。
这里运用的设计模式就是装饰者模式,继承并扩展,底层实现基于被扩展示例。
总结:
BeanFactory
才是真正 Bean 容器,管理 Bean 生命周期。
ApplicationContext
包含了 BeanFactory
职责,并且还有其他功能。
Q: ApplicationContext
继承了 HierarchicalBeanFactory
,给开发人员的提示?
A: ApplicationContext
Bean 生命周期管理能力,来自于 BeanFactory
,并且它又是 HierarchicalBeanFactory
子接口,说明它具备 BeanFactory
的层次性关系。同时,它也有 getParent()
方法返回双亲ApplicationContext
,其子接口 ConfigurableApplicationContext
拥有设置双亲 ApplicationContext
的能力。
类比:
- Parent
BeanFactory
(管理 10 个Bean)- Child
BeanFactory
(管理 20 个Bean)- Parent
ClassLoader
(加载 10 个类)- Child
ClassLoader
(加载 20 个类)
demo演示:设置spring上下文启动
@EnableAutoConfiguration
@RestController
public class SpringBootApplicationBootstrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext parentContext = new AnnotationConfigApplicationContext();
parentContext.setId("test");
// 在"test" 上下文注册一个 "helloWorld" String 类型的 Bean
parentContext.registerBean("helloWorld", String.class, "Hello,World");
// 启动"test" 上下文
parentContext.refresh();
new SpringApplicationBuilder(SpringBootApplicationBootstrap.class)
.parent(parentContext) // 显式地设置双亲上下文
.run(args);
}
@Autowired // String message Bean
@Qualifier("helloWorld") // Bean 名称,来自于 “test” 上下文
private String message;
@RequestMapping("")
public String index() {
return message;
}
}
运行此上下文,并访问:http://localhost:9091/actuator/beans,得到:
null
Spring Boot 1.x 默认情况一个 ApplicationContext。如果独立管理上下文 ,有两个 ApplicationContext。
Spring Boot 2.0 合并一个 ApplicationContext,Spring Cloud 会增加 Bootstrap ApplicationContext。
是不是意味着 bootstrap 要提早加载什么资源?
Spring Boot 实现
org.springframework.boot.builder.ParentContextApplicationContextInitializer
Spring Cloud 实现
org.springframework.cloud.bootstrap.BootstrapApplicationListener
。其监听的事件是 ApplicationEnvironmentPreparedEvent
。推理意思:Environment
已经准备好(被调整)技术关联: Spring 应用上下文层次,Spring 事件
Spring Boot 外部化配置官方文档
我们通常说SpringBoot做健康检查,用的就是此项技术,不过在实际应用中为了保障安全,会设置不同的端点的权限,我们这里只是简单地介绍一下基本情况。
@EnableAutoConfiguration
public class SpringBootApplicationBootstrap {
public static void main(String[] args) {
SpringApplication.run(SpringBootApplicationBootstrap.class,args);
}
}
spring.application.name = first-spring-cloud-app
# 设置 Web 服务端口
server.port = 9090
# 设置 Web 管理端口(服务上下文和管理上线独立)
management.server.port = 9091
# 开放 所有Web 管理 Endpoints
management.endpoints.web.exposure.include = *
启动 spring 应用上下文,并访问地址: http://localhost:9091/actuator
JSON展示:
{
"_links":{
"self":{
"href":"http://localhost:9091/actuator",
"templated":false
},
"auditevents":{
"href":"http://localhost:9091/actuator/auditevents",
"templated":false
},
"beans":{
"href":"http://localhost:9091/actuator/beans",
"templated":false
},
"health":{
"href":"http://localhost:9091/actuator/health",
"templated":false
},
"conditions":{
"href":"http://localhost:9091/actuator/conditions",
"templated":false
},
"configprops":{
"href":"http://localhost:9091/actuator/configprops",
"templated":false
},
"env":{
"href":"http://localhost:9091/actuator/env",
"templated":false
},
"env-toMatch":{
"href":"http://localhost:9091/actuator/env/{toMatch}",
"templated":true
},
"info":{
"href":"http://localhost:9091/actuator/info",
"templated":false
},
"loggers":{
"href":"http://localhost:9091/actuator/loggers",
"templated":false
},
"loggers-name":{
"href":"http://localhost:9091/actuator/loggers/{name}",
"templated":true
},
"heapdump":{
"href":"http://localhost:9091/actuator/heapdump",
"templated":false
},
"threaddump":{
"href":"http://localhost:9091/actuator/threaddump",
"templated":false
},
"metrics-requiredMetricName":{
"href":"http://localhost:9091/actuator/metrics/{requiredMetricName}",
"templated":true
},
"metrics":{
"href":"http://localhost:9091/actuator/metrics",
"templated":false
},
"scheduledtasks":{
"href":"http://localhost:9091/actuator/scheduledtasks",
"templated":false
},
"httptrace":{
"href":"http://localhost:9091/actuator/httptrace",
"templated":false
},
"mappings":{
"href":"http://localhost:9091/actuator/mappings",
"templated":false
},
"refresh":{
"href":"http://localhost:9091/actuator/refresh",
"templated":false
},
"features":{
"href":"http://localhost:9091/actuator/features",
"templated":false
}
}
}
上面的配置文件中我将所有端口开放,所以通过访问 /actuator后得到所有暴露的端点的地址,比如:
"beans":{
"href":"http://localhost:9091/actuator/beans",
"templated":false
},
那么我们此时访问: http://localhost:9091/actuator/beans ,就会得到被Spring监控的Bean的详情:
访问端口:http://localhost:9091/actuator/env
/actuator/pause 和 /actuator/resume 端口 默认失效,首先要在配置文件中开启端点:
management.endpoint.restart.enabled=true
management.endpoint.pause.enabled=true
management.endpoint.resume.enabled=true
/actuator/pause -> ApplicationContext#stop()
-> Spring LifeCycle Beans stop()
。但是 LifeCycle 实例(ApplicationContext)不等于 LifeCycle Bean
/actuator/resume -> ApplicationContext#start()
-> Spring LifeCycle Beans start()
Spring Boot 探索 | Actuator 端点详细说明
本节代码地址:https://github.com/harrypottry/microservices-project/tree/master/spring-cloud-project/spring-cloud-native-application
更多架构知识,欢迎关注本套Java系列文章:Java架构师成长之路