Spring全家桶
Spring概览
- SpringBoot
- SpringCloud
- SpringCloudDataFlow
JDBC
单数据源配置
多数据源配置
连接池
HikariCP
- 速度快
Druid
- 关注监控运维
SpringJDBC
- JDBCTemplate
Spring事务抽象
核心接口
- PlatformTransactionManager
- TransactionDefinition
事务传播
事务隔离
声明式与编程式事务
JDBC异常抽象
- 将数据操作异常转换为DataAccessException
- 原理:数据库的错误码都是固定的,枚举错误码
对象映射
为什么需要对象映射
对象与关系的范式不匹配
Hibernate
- 屏蔽数据库底层细节
- 将开发者从95%的常见数据持久化工作中解放出来
JPA
Java Persistence API,为对象关系映射提供了一种基于POJO的持久化模型
- 简化数据持久化代码的开发工作
- 屏蔽不同持久化API的差异
常用注解
实体
Entity
MappedSuperClass,多个实体类有一个父类,这个注解用于父类
Table(“name”)
主键
Id
GeneratedValue
映射
- Column
关系
- OrderBy
Lombok
MyBatis
MyBatisGenerator
逆向工程从表结构生成PO类
MyBatisPageHelper
分页工具
NoSQL
MongoDB
Redis
- spring对Redis的支持
- Jedis(不是线程安全的,一般使用池化技术,JedisPool)、Lettuce客户端
- RedisTemplate
- Repository支持
- 哨兵模式
- Redis Sentinel是Redis的一种HA方案
- 通过JedisSentinelPool操作
- 集群
- 数据自动分片,分成多个Hash Slot
- 在部分节点失效时有一定的可用性
Spring缓存抽象
基于AOP实现,为不同的缓存提供一层抽象
- 为Java方法增加缓存,缓存执行结果
- 支持ConcurrentMap
- 接口
- Cache
- CacheManager
- 注解:开启缓存支持,EnableCaching
- Cacheable,方法注解
- CacheEvict,缓存清理
本地缓存与分布式缓存
- 分布式:redis
- 本地:Spring缓存、Guava
读写分离
- Lettuce支持读写分析,Jedis不支持
- 只读主、只读从
- 优先读主、优先读从
RedisTemplate
- RedisTemplate<K,V>
- opsForXxx
Redis Repository
- 实体注解
- RedisHash
- Id
- Indexed,索引列
数据访问进阶
Project Reactor
响应式或者反应式编程,是一种面向数据流和变化传播的编程范式。这意味着可以在编程语言中很方便地表达静态或者静态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。如数据双向绑定模型?
- WebFlux 不是 Spring MVC 的替代方案!,虽然 WebFlux 也可以被运行在 Servlet 容器上(需是 Servlet 3.1+ 以上的容器),但是 WebFlux 主要还是应用在异步非阻塞编程模型,而 Spring MVC 是同步阻塞的,如果你目前在 Spring MVC 框架中大量使用非同步方案,那么,WebFlux 才是你想要的,否则,使用 Spring MVC 才是你的首选。https://www.cnblogs.com/quanxiaoha/p/10773773.html
- 适合Reactive的场景:IO密集型
- 网络IO:微服务网关
- 磁盘IO:
核心概念
Operators-Publisher/Subscriber
- Nothing Happens Until You subscribe()
- Flux[0…N] - onNext()、onComplete()、onError()
- Mono [0…1] - onNext()、onComplete()、onError()
Backpressure-反压
- Subscription
- onRequest、onCancel、onDispose
Scheduler-线程调度
- immediate、single、newSingle
- elastic、parallel-固定线程池、newParallel
异常处理
- onError、onErrorReturn、onErrorResume
- doOnError、doFinally
Reactive x Redis
Lettuce支持Reactive访问Redis
Spring Data Redis
- ReactiveRedisConnection
- ReactiveRedisConnectionFactory
- ReactiveRedisTemplate
Reactive x MongoDB
MongoDB官方提供Reactive支持
Spring Data MongoDB
- ReactiveMongoClientFactoryBean
- ReactiveMongoDatabaseFactory
- ReactiveMongoTemplate
Reactive x RDBMS
- R2DBC:Reactive Relational Database Connectivity
- 支持的数据库
- Postgres
- H2
- Microsoft SQL Server
使用APO打印数据访问层摘要(日志)
AOP
- 为什么需要CGLIB?因为通常情况下,Controller、Service都没有接口
- 如何打印SQL
- HikariCP:依赖P6Spy
- Druid:内置SQL输出
Spring MVC
核心
- DispatcherServlet
- Controller
- XXXResolver
- viewResolver
- HandlerExceptionResolver
- MultipartResolver
- HandlerMapping
常用注解
- Controller,定义控制器
- RestController=Controller+ResponseBody
- RequestingMapping
- GetMapping、PostMapping、PutMapping、DeleteMapping
- RequestBody、ResponseBody、ResponseStatus-指定响应码
应用上下文
- 常用接口以及实现
- BeanFactory
- DefaultListableBeanFactory
- ApplicationContext,常用
- ClassPathXmlApplicationContext
- FileSystemXmlApplicationContext
- AnnotationConfigApplicationContext
- WebApplicationContext
- BeanFactory
请求处理机制
一个请求的大致处理流程
- 绑定Attribute
- WebApplicationContext、LocaleResolver、ThemeResolver
- 处理Multipart
- 如果是Multipart请求,将请求转换为MultipartHttpServletRequest
- Handler处理
- 如果找到对应的Handler,执行Controller以及前后置处理器逻辑
- 处理返回的Model,呈现视图
定义处理方法
定义映射关系
- Controller
- RequestMapping
- path、method 指定映射路径与方法
- params、headers 限定映射范围
- consumes、produces 限定请求与响应格式
- RestController、XXXMapping
自定义类型转换
- 自己实现WebMvcConfigurer
- 添加自定义Converter
- 添加自定义的Formatter
定义校验
- 通过Validator对绑定结果进行校验
- Hibernate Validator
- @Valid注解
- BindingResult,用于获取Valid的结果进行自定义的处理逻辑
Multipart上传
- 配置MultipartResolver
- SpringBoot自动配置MultipartAutoConfiguration
- 支持类型multipart/form-data
- MultipartFile类型
视图解析机制
视图解析实现基础
- ViewResolver、View接口
- AbstractCachingViewResolver
- FreeMarkerViewResolver
- @ResponseBody相关逻辑
- HandlerAdapter.handle()完成Response输出
- RequestMappingHandlerAdapter.invokeHandlerMethod()
- HandlerMethodReturnValueHandlerComposite.handleReturnValue()
- RequestResponseBodyMethodProcessor.handleReturnValue()
重定向
- redirect,客户端,302跳转
- forward,服务端
常用的视图
Jackson-based JSON / XML
- JacksonAutoConfiguration
- SpringBoot通过@JsonComponent注册JSON序列化组件
- Jackson2ObjectMapperBuilderCustomizer
- JacksonHttpMessageConvertersConfiguration
- 增加jackson-dataformat-xml以支持XML序列化
Thymeleaf & Freemaker
- ThymeleafAutoConfiguration自动装配
- ThymeleafViewResolver
- @Controller、ModelMap
配置MessageConverter
- 通过WebMvcConfigurer的configureMessageConverters()配置,SpringBoot自动查找HttpMessageConverters进行注册
静态资源与缓存
资源
不推荐在Java中处理静态资源
- 核心逻辑
- WebMvcConfigurer.addResourceHandlers
- 常用配置
1 | spring.mvc.static-path-pattern=/static/** |
缓存
- ResourceProperties.Cache
推荐架构
- 用户->CDN->静态资源
- CDN->Gateway->缓存->应用
异常处理机制
- 核心接口:HandlerExceptionResolver
- 异常处理方法:@ExceptionHandler
- 添加位置:
- @Controller、@RestController(高优先级)
- @ControllerAdvice、@RestControllerAdvice(AOP)
- 添加位置:
- 在异常类中使用ResponseStatus注解,可以返回指定的错误码
SpringMVC的切入点
拦截器
- 核心接口:HandlerInteceptor
- preHandle
- postHandle
- afterCompletion
- 配置拦截器
- 常规方法:WebMvcConfigurer.addInterceptors
- SpringBoot配置:创建一个带@Configuration的WebMvcConfigurer配置类
- 不能带@EnableWebMvc,由Spring托管
- 用途:搭配ThreadLocal统计调用时间、鉴权
访问Web资源
就是http客户端,一般用okhttp
通过RestTemplate访问Web资源
- SpringBoot没有自动配置RestTemplate,可以自己new,也可以使用RestTemplateBuilder。
- 常用方法
- getForObject、getForEntity(Entity包含)
- postForObject、postForEntity
- put
- delete
- 构造URI
- 构造URI:UriComponentsBuilder
- 构造相对于当前请求的URI:ServletUriComponentsBuilder
- 构造指向Controller的URI:MvcUriComponentsBuilder
RestTemplate高阶用法
传递Http Header
- RestTemplate.exchange()
- RequestEntity、ResponseEntity
处理类型转换
解析泛型对象
RestTemplate.exchange()
ParameterizedTypeReference
如果不处理,会报错:无法将LinkedHashMap转换为XXX。
定制RestTemplate
支持的HTTP库
- 通用接口:ClientHttpRequestFactory
- 默认实现:SimpleClientHttpRequestFactory
- Apache HttpComponents(以前的Http Client)
- Netty
- OkHttp
优化底层请求逻辑
- 连接管理
- PoolingHttpClientConnectionManager
- KeepAlive策略
- 超时设置
- connectTimeout
- readTimeout
- SSL校验
- 证书检查策略
通过WebClient访问Web资源
- 以Reactive方式处理HTTP请求的非阻塞式客户端
- 支持的底层HTTP库
- Reactor Netty
- Jetty ReactiveStream HttpClient
Web开发进阶
设计RESTful Service
REST提供了一组架构约束,当作为一个整体来应用时,强调组件交互的可伸缩性,接口的通用性,组件的独立部署、以及用来减少交互延迟,增强安全性,封装遗留系统的中间件。
Richardson成熟度模型
- level0:the swarmp of POX,一个URI处理所有操作
- level1:Resources,有资源概念,但是都是在使用GET、POST
- level2:HTTP Verbs,开始关注HTTP Method的含义
- level3:Hypermedia Controls,超媒体
实现Restful Web Service
- 识别资源
- 找到领域名词,能用CRUD操作的名词
- 将资源组织为集合(即集合资源)
- 如果需要一次性返回多个资源,则将资源合并为复合资源
- 如果无法找到对应的领域名词,则设计为计算或处理函数
- 选择合适的资源粒度
- 服务端角度
- 网络效率
- 表述的多少
- 客户端的易用程度
- 客户端角度
- 可缓存性
- 修改频率
- 可变性
- 服务端角度
- 设计URI
- 使用域或者子域对资源进行合理的分组或划分
- 在URI的路径部分使用斜杆分隔符来表示资源的层级关系
- 使用逗号和分号来表示非层级关系
- 使用-和_来改善长路径中名称的可读性
- 使用&分割参数
- 避免出现文件拓展名
- 选择合适的HTTP方法和返回码
- 设计资源的表述
- JSON
- XML
- HTML
- ProtoBuf
HATEOAS
Hybermedia As the Engine Of Application State,把超媒体作为应用状态的引擎,REST统一接口的必要组成部分。
- 表述中的超链接会提供服务所需的各种REST接口信息,无需事先约定如何访问服务。
- 服务端根据应用状态的不同,返回不同的可操作链接。
SpringDataREST
HAL
Hypertext Application Language,一种简单的格式,为API中的资源提供简单一致的链接
- HAL模型
- 链接
- 内嵌资源
- 状态
Spring Data REST
服务端
@RepositoryRestResource
Resource
PagedResource
客户端
- 配置Jackson JSON,注册HAL支持
- 操作超链接
- 找到需要的Link
- 访问超链接
分布式环境解决Session问题
会话解决方案
- 粘性会话:Sticky Session,机器下线时session失效
- 会话复制:Session Replacation,数据同步代价高,数据容易不同步
- 集中会话:Centralized Session,推荐
Spring Session
- 简化集群中的用户会话管理,无需绑定容器特定解决方案
- 支持的存储
- Redis
- MongoDB
- JDBC
- Hazelcast
- 实现原理:定制HttpSession
- 通过定制的HttpServletRequest返回定制的HttpSession
- SessionRepositoryRequestWrapper
- SessionRepositoryFilter
- DelegatingFilterProxy
- 通过定制的HttpServletRequest返回定制的HttpSession
- 基于Redis实现
- @EnableRedisHttpSession
- 提供RedisConnectionFactory
- 实现AbstractHttpSessionApplicationInitializer
- DelegatingFilterProxy
WebFlux
- 什么是WebFlux
- 用于构建基于Reactive技术栈之上的Web应用程序
- 基于Reactive Streams API,运行在非阻塞服务器上,如Netty、Jetty
- 为什么需要WebFlux
- 对于非阻塞Web应用的需要
- 函数式编程
- 关于性能
- 请求的耗时并不会有很大的改善,改善的是吞吐量
- 仅需要少量固定数量的线程和较少的内存即可实现拓展
- 选型
- 已有的Spring MVC应用,保持现状
- 依赖了大量阻塞式持久化API和网络API,建议使用Spring MVC,如Mysql
- 已经使用了非阻塞技术栈,可以考虑WebFlux
- 使用Java8 Lambda结合轻量级函数式框架,可以考虑WebFlux
- 编程模型
- 基于注解的控制器
- 函数式Endpoints
重新认识SpringBoot
组成部分
- 核心功能
- 自动配置-Auto Configuration
- 起步依赖-Starter Dependency
- 命令行界面-Spring Boot CLI
- Actuator
自动配置的实现原理
- 自动配置
- 基于添加的JAR依赖自动对SpringBoot应用程序进行配置,创建Bean
- SpringBoot的自动配置就是当Spring容器启动后,一些自动配置类(只是自动配置类,并不是当前的组件配置到IOC容器中,自动配置类通过@Conditional注解来按需配置)就自动装配的IOC容器中,不需要我们手动注入,从而简化了开发,省去繁琐的配置。
- 开启自动配置
- @EnableAutoConfiguration
- exclude
- @SpringBootApplication
- @EnableAutoConfiguration
- 自动配置原理
- 条件注解
- Conditional
- ConditionalOnClass
- 条件注解
- 自动配置情况观测
- 添加程序参数,
--debug
- 添加程序参数,
自己实现自动配置
- 步骤
- 编写Java Config,@Configuration
- 添加条件,@Conditional;类条件@ConditionalOnClass、@ConditionalOnMissingClass;属性条件@ConditionalOnProperty、Bean条件、资源条件、Web应用条件、其它条件(Spring4.x以上才有条件注解)
- 定位自动配置,META-INF/spring.factories
- 低版本Spring实现自动配置
- 条件判断:通过BeanFactoryPostProcessor进行判断
- 配置加载:编写JavaConfig并通过component-scan或者XML引入
起步依赖以及实现原理
起步依赖即Starter
maven依赖管理技巧
- 列出依赖树
mvn dependency:tree
- IDEA maven Helper,可视化
- 排除特定依赖:exclusion
- 统一管理依赖
- dependencyManagement
- bom
起步依赖
- 直接面向功能
- 一站式获得所有相关依赖
定制起步依赖
- 主要内容
- autoconfigure模块,包含自动配置代码
- starter模块,包含指向自动配置模块的依赖以及其它依赖
- 命名方式
- xxx-spring-boot-autoconfigure
- xxx-spring-boot-starter
配置加载机制
外化配置加载顺序
Spring Boot 可以将配置外部化,这种模式叫做 “外化配置”。将配置从代码中分离外置,最明显的作用是只要简单地修改下外化配置文件,就可以在不同环境中,可以运行相同的应用代码。
- 开启DevTools时,~/spring-boot-devtools.properties
- 测试类上的@TestPropertySource注解
- @SpringBootTest#proterties属性
- 命令行参数(–server.port=9000)
- STRING_APPLICATION_JSON中的属性(环境变量)
- ServletConfig初始化参数
- ServletContext初始化参数
- java:comp/env中的JNDI属性
- System.getProperties()
- 操作系统环境变量
- random.*涉及的RandomValuePropertySource
- jar包外部的application-profile.properties 或者 yml
- jar包内部的application-profile.properties 或者 yml
- jar包外部的application.properties 或者 yml
- jar包内部的application.properties 或者 yml
- @Configuration类上的PropertySource
- SpringApplication.setDefaultProperties()设置的默认属性
application.properties位置
1 | ./config |
PropertySource抽象
可以自定义从文件、网络(配置中心)等各种地方获取配置项
添加PropertySource
<context:property-placeholder>
@PropertySource
@PropertySources
SpringBoot的@ConfigurationProperties
- 可以将属性绑定到结构化对象上
- 支持Relaxed Binding
- 支持安全的类型转换
- @EnableConfigurationProperties
定制PropertySource
- 步骤
- 实现PropertySource
- 从Environment取得PropertySources
- 将自己的PropertySource添加到合适的位置
- 切入位置
- EnvironmentPostProcessor
- BeanFactoryPostProcessor
运行中的SpringBoot
ActuatorEndpoint
Acturator
监控并管理应用程序
- 访问方式
- HTTP
- JMX
- HTTP访问:
/actuator/<id>
- 配置
1 | management.server.address/port |
依赖:spring-boot-starter-actuator
endpoint
- beans:显示Bean列表
- caches:显示应用缓存
- conditions:配置条件的计算情况
- configprops:显示@ConfigurationProperties的信息
- env:显示ConfigurableEnvironment中的属性
- health:显示健康检查信息,默认HTTP可访问
- httptrace:显示HTTP Trace信息
- info:显示设置好的应用信息,默认HTTP可访问
- loggers:显示并更新日志配置
- metrics:显示应用度量信息
- mappings:显示所有@RequestMapping信息
- scheduledtasks:显示应用的调度任务信息
- shutdown:优雅关闭应用程序,默认不开启
- threaddump:执行ThreadDump
- heapdump:返回Head Dump文件,格式为HPROF,JMX不支持
- prometheus:返回Prometheus抓取的信息,JMX不支持
定制HealthIndicator
SpringBoot自带的HealthIndicator
状态
DOWN、OUT_OF_SERVICE 503
UP、UNKNOWN 200
机制
- 通过HealthIndicatorRegistry收集信息
- HealthIndicator实现具体检查逻辑,内置了很多,如DataSource、Redis、Mongo等基础设施
自定义
- 实现HealthIndicator接口
- 根据自定义检查逻辑返回对应Health状态,Health中包含状态和详细描述信息
通过Micrometer获取运行数据
类比SLF4J,日志门面;Micrometer,度量门面。
特性
- 多维度度量
- 支持Tag
- 预置大量探针
- 缓存、类加载器、GC、CPU、线程池
- 与Spring深度结合
核心度量指标
- 核心接口
- Meter
- 内置实现
- Gauge、TimeGauge
- Timer、LongTaskTimer、FunctionTimer
- Counter、FunctionCounter
- DistributionSummary
结合Spring
- URL
/actuator/metrics
、/actuator/prometheus
自定义度量指标
三种方法
- 通过MeterRegistry注册Meter
- 通过MeterBinder Bean让SpringBoot自动绑定
- 通过MeterFilter进行定制
SpringBootAdmin
为SpringBoot提供一个可视化管理界面以及通知机制
配置
- 服务端,一般使用单独的服务作为服务端,收集其它应用程序的信息
- @EnableAdminServer
- 客户端,具体的应用程序,去连接服务端
- 配置服务端以及Endpoint
- 安全:spring-boot-starter-security
定制容器的运行参数
内嵌容器可选列表
- tomcat
- jetty
- undertow
- reactor-netty
容器配置
- 端口:
server.port
、server.address
- 压缩:
server.compression.enabled/min-response/mime-types
- 错误处理:
server.error.path/include-exception/include-stacktrace/enabled
HTTP2支持
服务端HTTPS配置
- 配置
1 | server.port=8443 |
- 生成证书文件
- keytool工具:
keytool -genkey -alias 别名 -storetype 仓库类型 -keyalg 算法 -keysize 长度 -keystore 文件名 -validity 有效期
- 仓库类型PKCS12、算法RSA、DSA;长度2048
- keytool工具:
客户端HTTPS配置
- 配置HttpClient
- SSLContextBuilder构建SSLContext
- setSSLHostnameVerifier(new NoopHostnameVerifier())
- 配置RequestFactory
- HttpComponentsClientHttpRequestFactory
- setHttpClient
- HttpComponentsClientHttpRequestFactory
HTTP2
- JDK>=JDK9,tomcat>=9.0.0,SpringBoot不支持h2c,需要先配置SSL。
- 配置:
server.http2.enabled
- HTTP库:OKHTTPClient
命令行程序
非Web的SpringBoot项目
关闭Web容器
控制依赖:不添加Web相关依赖
配置方式:
spring.main.web-application-type=none
编程方式
- SpringApplication
- setWebApplicationType
- SpringApplication
常用工具类
- ApplicationRunner,参数是ApplicationArguments
- CommandLineRunner,参数是String[]
- 多个Runner可以使用Order注解指定执行顺序
- 返回码:ExitCodeGenerator,对应Linux进程返回码
可执行Jar包
Jar包内容(不包含JDK、JRE)
- Jar描述,META-INF/MANIFEST.MF
- SpringBootLoader,org/springframework/boot/loader
- 项目内容,BOOT-INF/classes
- 项目依赖,BOOT-INF/lib
程序入口
- MANIFEST.MF
- Main-Class:org.springframework.boot.loader.JarLauncher
- 项目主类
- @SpringApplication
- MANIFEST.MF
- Start-Class: xxx.yyy.zzz
- MANIFEST.MF
可以直接执行的jar包,不需要java命令
- 在spring-boot-maven-plugin中的executable设置为true
- 可以在.conf的同名文件中配置参数,如a.jar,配置文件则为a.conf
- 默认脚本中的一些配置项
- CONF_FOLDER,放置.conf文件的目录位置,只能在环境变量中配置
- JAVA_OPTS,JVM启动的参数,如JVM的GC与内存
- RUN_ARGS,传递给程序执行的参数
- 实现原理是在jar包前面包含了一个8KB的SHELL脚本
Docker打包
通过maven构建docker镜像
- 步骤
- 提供一个Dockerfile文件
- 配置dockerfile-maven-plugin插件
- 执行构建
- mvn package
- mvn dockerfile:build
- 检查结果
- docker images
dockerfile编写
- 提供JRE
- 拷贝JAR
- 运行
Spring Cloud
微服务
微服务:微服务就是一些协调工作的小而自治的服务。
- 异构性
- 语言、存储
- 弹性
- 一个组件不可用,不会导致级联故障
- 拓展
- 单体服务不易拓展,多个较小的服务可以按需拓展
- 优点
- 易于部署
- 与组织结构对齐
- 可组合性
- 可替代性
- 代价
- 分布式系统的复杂性
- 开发、测试过程的复杂性
- 部署、监控的运维复杂性
云原生 CloudNative
云原生技术有利于各组织在公有云,私有云和混合云等新型动态环境中,构建和运行可弹性拓展的应用。
云原生应用要求
- devops,开发和运维一同致力于交付高品质得软件服务于客户
- continuous delivery,持续集成:软件得构建,测试和发布,要更快,更频繁,更稳定
- microservices,以一组小型服务得形式来部署应用
- containers,提供比传统虚拟机更高得效率
CNCF
Cloud Native Computing Foundation
- k8s
- Prometheus
- Envoy
- CoreDNS
- containerd
Factor APP
目的
- 为构建SaaS应用提供行之有效得方法论
- 适用于任意语言和后端服务得开发得应用程序
12-Factors
- 基准代码:一份基准代码,多份部署
- 使用版本管理系统
- 基准代码与应用程序保持一一对应的关系
- 尽管每个应用只对应一份基准代码,单可以同时存在多份部署,如local、dev、prod
- 依赖:显式声明依赖关系
- 通过依赖清单,确切声明所有依赖项,如maven
- 配置:在环境中存储配置,外化配置、配置中心
- 后端服务:把后端服务作为附加资源
- 如数据库、缓存等都视为资源
- 构建,发布,运行:严格分离构建和运行
- 每发布一个版本必须对应一个唯一的发布ID
- 进程:以一个或者多个无状态进程运行应用
- 任何需要持久化的数据都要存储在后端服务内
- 端口绑定:通过端口绑定提供服务
- 并发:通过进程模型进行拓展
- 易处理:快速启动和优雅终止可最大化健壮性
- 追求最小启动时间
- 进程一旦接收终止信号就会优雅终止
- 进程应当在面对突然死亡时保持健壮
- 开发环境和线上环境等价:尽可能得保持开发、预发布、线上环境相同
- 想要做到持续部署就必须缩小本地和线上的差异
- 后端服务是保持开发与线上等价的重要部分,反对在不同环境中使用不同的后端服务。
- 日志:把日志当作事件流
- 管理进程:后台管理任务当作一次性进程运行
Spring Cloud组件
- 服务发现
- 服务熔断
- 配置服务
- 服务安全,Spring Security
- 服务网关,API Gateway
- 分布式消息
- 分布式跟踪
- 云平台支持
服务注册与发现
使用Eureka作为服务注册中心
- 什么是Eureka:AWS上定位服务的REST服务
- Netflix OSS:https://netflix.github.io
- Spring对Netflix的支持:Spring Cloud Netflix
- 已不做更新,如果不是在AWS上面,不推荐使用
启动Eureka服务
依赖:
spring-cloud-starter-netflix-eureka-starter
声明:@EnableEurekaServer
注意:
- 默认端口8761
- Eureka服务端自己不要注册到Eureka上面
1
2
3
4# 自己不注册到Eureka
eureka.client.register-with-eureka=false
#
eureka.client.fetch-registry=false
将服务注册到Eureka
- 依赖:
spring-cloud-starter-netflix-eureka-client
- 声明:@EnableDiscoveryClient、@EnableEurekaClient
- 配置
1 | eureka.client.service-url.default-zone |
Bootstrap属性
- 启动引导阶段加载的属性
- bootstrap.properties/yml
- spring.cloud.bootstrap.name=bootstrap
- 常用配置
- spring.application.name=应用名,用于服务注册
- 配置中心相关
服务发现原理
如何获得服务地址
- EurekaClient:getNextServerFromEureka()
- DiscoveryClient:getInstances,推荐,Spring的抽象
Load Balancer Client
- RestTemplate与WebClient
- @LoadBalaced
- 实际上通过ClientHttpRequestInterceptor实现
- LoadBalancerInterceptor
OpenFeign
Spring
服务注册与发现抽象
- 服务注册:ServiceRegistry
- 服务发现:DiscoveryClient
自动向Eureka服务端注册
- ServiceRegistry
- EurekaSerivceRegistry
- EurekaRegistration
- 自动配置
- EurekaAutoServiceRegistration
- SmartLifecycle
- EurekaClientAutoConfiguration
- EurekaAutoServiceRegistration
使用ZK作为服务注册中心
Zookeeper
- 一个分布式协调服务
- 设计目标:简单、多副本、有序,快(适合读写比在10:1以上的场景,即读多写少)
Spring Cloud Zookeeper
- 依赖
spring-cloud-starter-zookeeper-discovery
、客户端:Apache Curator - 简单配置:
spring.cloud.zookeeper.connect-string=localhost:2181
- 注意:3.5.x还是Beta,但是很多人在生产中使用
使用Zookeeper作为注册中心的问题
- https://developer.aliyun.com/article/601745
- 在实践中,注册中心不能因为自身的任何原因破坏服务之间的可连通性
- 注册中心需要是AP的,但是ZK是CP的,如果ZK脑裂了,则直接不可用,所以一般不能跨机房使用
使用Consul作为服务注册中心
Consul
- 分布式、高可用
- 关键特性:服务发现、健康检查、KV存储、多数据中心支持、安全的服务间通信
- 服务发现的好用功能
- HTTP API
- DNS,xxx.service.consul
- 与nginx联动,ngx_http_consul_backend_module
Spring结合
- 依赖:
spring-cloud-starter-consul-discovery
- 简单配置
1 | spring.cloud.consul.host=localhost |
- docker启动
1 | docker run --name consul -d -p 8500:8500 -p 8600:8600/udp consul |
Nacos作为服务注册中心
Nacos
- 阿里巴巴开源,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台
- 功能
- 动态服务配置
- 服务发现和管理
- 动态DNS服务
Spring结合
- 依赖:
spring-cloud-alibaba-dependencies
、spring-cloud-starter-alibaba-nacos-discovery
- 简单配置
1 | spring.cloud.nacos.discovery.server-addr |
DiscoveryClient定制
- 功能
- 返回该DiscoveryClient能提供的服务名列表
- 返回指定服务对应的ServiceInstance列表
- 返回DiscoveryClient的顺序
- 返回HealthIndicator里显示的描述
- 实现RibbonClient支持
- 实现DiscoveryClient接口
- 实现自己的
ServerList<T extends Server>
,调用上一步的client- Ribbon提供了
AbstractServerList<T extends Server>
- Ribbon提供了
- 提供一个配置类,声明ServerListBean实例
服务熔断
断路器模式
- 在断路器对象中封装受保护的方法调用
- 该对象监控调用和短路情况
- 调用失败触发阈值后,后续调用直接使用断路器返回错误码,不再执行实际调用
- 有自动探活恢复机制
Hystrix实现熔断
@HystrixCommand
- fallbackMethod,commandProperties
Spring结合
spring-cloud-starter-netflix-hystrix
- @EnableCircuitBreaker
Feign支持
- feign.hystrix.enabled=true
- @FeignClient,该注解用于接口上,还需要一个FallbackXXX类,实现一样的接口
- fallback/fallbackFactory
已经不再更新维护,不推荐使用
熔断观测
- 打日志
- 发生熔断时打印特定日志
- 看监控
- 主动向监控系统埋点,上报熔断情况
- 提供与熔断相关的EndPoint,让第三方系统来拉取信息
Resilience4j
Resilience4j
- 受Hystrix启发的轻量级且易于使用的容错库
- 针对Java8与函数式编程设计
- 核心组件
- circuitbreaker:熔断
- ratelimiter:限流
- bulkhead:依赖隔离&负载保护
- retry:自动重试
- cache:应答缓存
- timelimiter:超时控制
实现熔断
- 依赖
resilience4j-spring-boot2
- 基于ConcurrentHashMap的内存断路器
- CircuitBreakerRegistry
- CircuitBreakerConfig
实现限流-Bulkhead
- 目的:防止下游依赖被并发请求冲击;防止发生连环故障。超过阈值的请求先等待,等待超过阈值时间后直接返回。bulkhead隔舱,防水舱。
- 用法:BulkheadRegistry/BulkheadConfig;@Bulkhead(name=”名称”)
- 配置:BulkheadProperties
- backend.xxx
- max-concurrent-call
- max-wait-time
- 命令行验证命令
1 | ab -c 5 -n 10 url |
实现限流-RateLimiter
- 目的:限制特定时间段内的执行次数
- 用法:
- RateLimiterRegistry/RateLimiterConfig
- RateLimiter(name=”名称”)
- 配置:ReteLimiterProperties
- limiters.xxx
- limit-for-period
- limit-refresh-period-in-millis
- timeout-in-millis
服务配置
基于Git
Spring Cloud Config Server
- 目的:提供针对外置配置的HTTP API,把自己作为一个服务注册到注册中心
- 依赖:
spring-cloud-config-server
- @EnableConfigServer
- 支持Git、SVN、Vault、JDBC
- 配置:MultipleJGitEnvironmentProperties
spring.cloud.config.server.git.uri
- 可以是网络URL,也可以是本地路径:file://xxx
- 配置文件的要素
- application,即spring.application.name
- profile,即客户端的spring.profiles.active
- label,配置文件的特定标签,默认master
Spring Cloud Config Client
- 依赖:spring-cloud-starter-config
- 发现配置中心
- 配置文件配置,bootstrap.yml
- spring.cloud.config.url=xxx
- spring.cloud.config.fail-fast=true
- 服务发现
- spring.cloud.config.discovery.enabled=true
- spring.cloud.config.discovery.service-id=configserver
- 配置文件配置,bootstrap.yml
- 配置刷新
- @RefreshScope,用于Bean上面
- Endpoint:/actuator/refresh,或者依赖SpringCloudBus
基于ZK
依赖:spring-cloud-starter-zookeeper-config
启用
- bootstrap.yml
1
2spring.cloud.zookeeper.config.enabled
spring.cloud.zookeeper.connect-string存储格式
/config/application
,profile/key=value
配置
1 | spring.cloud.zookeeper.config.root/default-context/profile-speatator |
- 刷新机制:通知
配置抽象
- 目标:在分布式系统中,提供外置配置支持
- 实现:类似于Spring应用中的Environment与PropertySource,在上下文中添加SpringCloudConfig的PropertySource
基于Consul
依赖
spring-cloud-starter-consul-config
启用
bootstarp.yml
1
spring.cloud.consul.config.enabled/host/port
配置项
- spring.cloud.consul.config.format=KEY_VALUE\YAML\PROPERTIES\FILES
- /config/应用名,profile/data
- /config/application,profile/data
刷新机制:轮询
基于Nacos
依赖:
spring-cloud-alibaba-nacos-config
启用
- bootstrap.yml
1
spring.cloud.nacos.config.server-addr/enabled
配置项
- dataId
- ${prefix}-${spring.profile.active}-${file-extension}
- spring.cloud.nacos.config.prefix
- spring.cloud.nacos.config.file-extension
- spring.cloud.nacos.config.group
- dataId
刷新机制:通知
基于Apollo
- 有版本发布管理
- 灰度发布
- 权限管理、审计
- 客户端配置信息监控
- 开放平台API
Spring Cloud Stream
概览
- 一款用于构建消息驱动的微服务应用程序的轻量级框架
- 特性
- 声明式编程模型
- 引入多种概念抽象
- 发布订阅、消费组、分区
- 支持多种消息中间件
- 核心概念:Binder
- 应用程序与Binder交互,Binder与中间件交互
- @EnableBinding
- @Input、SubscribableChannel
- @Output、MessgaChannel
- 消费组:对于同一个消息,每个组中有且仅有一个消费者收到消息
- 分区:每个Topic下有多个分区,分区内消息可以认为是有序的
- 生产消息
- 使用MessageChannel中的send
- 方法上使用@SendTo,将方法返回值作为消息发送出去
- 消费消息
- 方法上使用@StreamListerner
- 方法参数:@Payload、@Headers、@Header
- 方法上使用@StreamListerner
- 其它:使用Spring Integration
访问RabbitMQ
- 依赖:
spring-cloud-starter-stream-rabbit
、spring-boot-starter-amqp
- 配置
1 | spring.cloud.stream.rabbit.binder.* |
访问Kafka
- 依赖:
spring-cloud-starter-stream-kafka
- 配置
1 | spring.cloud.stream.kafka.binder.* |
Spring定时任务
Spring的抽象
- TaskScheduler、Trigger、TriggerContext
配置定时任务
- @EnableScheduling
- 方法级别:@Scheduled
Spring事件机制
- Spring中的事件:ApplicationEvent
- 发送事件
- ApplicationEventPublisherAware
- ApplicationEventPublisher.publishEvent
- 监听事件
- ApplicationListener
- @EventListener
服务链路追踪
Dapper理解链路治理
服务治理关注点
- 系统中有哪些服务
- 服务的依赖关系
- 一个请求的具体执行路径
- 每个环节的执行是否正常以及其耗时情况
Google Dapper的概念
- Span-基本的工作单元
- Trace-由一组Span构成的树形结构
- Annotation-用于及时记录事件
- cs client send
- sr server received
- ss server send
- cr client received
Sleuth实现链路追踪
- 依赖:
spring-cloud-starter-sleuth
(系统请求处理库),spring-cloud-starter-zipkin
(外部埋点系统) - 日志输出:[appname, traceId,spanId,exportable]
追踪消息链路
追踪消息中间件的消息走向
- 可以使用HTTP进行埋点或者使用MQ进行埋点
服务治理关注点
- 宏观
- 架构设计是否合理
- 哪个链路是关键链路
- 链路的容量水位趋势
- 对系统变更的管理与审计
- 微观上
- 系统的依赖
- 系统的配置
- 系统的主观、客观质量