Spring概览

  • SpringBoot
  • SpringCloud
  • SpringCloudDataFlow

JDBC

单数据源配置

多数据源配置

连接池

HikariCP

  • 速度快

Druid

  • 关注监控运维

SpringJDBC

  • JDBCTemplate

Spring事务抽象

核心接口

  • PlatformTransactionManager
  • TransactionDefinition

事务传播

事务隔离

声明式与编程式事务

JDBC异常抽象

  • 将数据操作异常转换为DataAccessException
  • 原理:数据库的错误码都是固定的,枚举错误码

对象映射

为什么需要对象映射

对象与关系的范式不匹配

image-20230115110742394

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

image-20230119124130259

  • 为什么需要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

image-20230119182325244

请求处理机制

image-20230119193007108

一个请求的大致处理流程

  • 绑定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
2
spring.mvc.static-path-pattern=/static/**
spring.resources.static-locations=

缓存

  • 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方法和返回码

image-20230120180101614

image-20230120192007787

  • 设计资源的表述
    • JSON
    • XML
    • HTML
    • ProtoBuf

HATEOAS

Hybermedia As the Engine Of Application State,把超媒体作为应用状态的引擎,REST统一接口的必要组成部分。

  • 表述中的超链接会提供服务所需的各种REST接口信息,无需事先约定如何访问服务。

image-20230120192623699

  • 服务端根据应用状态的不同,返回不同的可操作链接。

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
  • 基于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
  • 自动配置原理
    • 条件注解
      • Conditional
      • ConditionalOnClass
  • 自动配置情况观测
    • 添加程序参数,--debug

自己实现自动配置

  • 步骤
    1. 编写Java Config,@Configuration
    2. 添加条件,@Conditional;类条件@ConditionalOnClass、@ConditionalOnMissingClass;属性条件@ConditionalOnProperty、Bean条件、资源条件、Web应用条件、其它条件(Spring4.x以上才有条件注解)
    3. 定位自动配置,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 可以将配置外部化,这种模式叫做 “外化配置”。将配置从代码中分离外置,最明显的作用是只要简单地修改下外化配置文件,就可以在不同环境中,可以运行相同的应用代码。

  1. 开启DevTools时,~/spring-boot-devtools.properties
  2. 测试类上的@TestPropertySource注解
  3. @SpringBootTest#proterties属性
  4. 命令行参数(–server.port=9000)
  5. STRING_APPLICATION_JSON中的属性(环境变量)
  6. ServletConfig初始化参数
  7. ServletContext初始化参数
  8. java:comp/env中的JNDI属性
  9. System.getProperties()
  10. 操作系统环境变量
  11. random.*涉及的RandomValuePropertySource
  12. jar包外部的application-profile.properties 或者 yml
  13. jar包内部的application-profile.properties 或者 yml
  14. jar包外部的application.properties 或者 yml
  15. jar包内部的application.properties 或者 yml
  16. @Configuration类上的PropertySource
  17. SpringApplication.setDefaultProperties()设置的默认属性

application.properties位置

1
2
3
4
5
6
7
8
./config
./
CLASSPATH中的/config
CLASSPATH中的/

# 通过下面的配置指定文件名、路径
spring.config.name=xxx
spring.config.location=xxx

image-20230120231837376

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
2
3
4
5
6
management.server.address/port
management.endpoints.web.base-path=/actuator
management.endpoints.web.path-mapping.<id>=xxx

# 开启与关闭
management.endpoint.<id>.enabled=true
  • 依赖: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.portserver.address
  • 压缩:server.compression.enabled/min-response/mime-types
  • 错误处理:server.error.path/include-exception/include-stacktrace/enabled

HTTP2支持

服务端HTTPS配置

  • 配置
1
2
server.port=8443
server.ssl.*:key-store、key-store-type、key-store-password
  • 生成证书文件
    • keytool工具:keytool -genkey -alias 别名 -storetype 仓库类型 -keyalg 算法 -keysize 长度 -keystore 文件名 -validity 有效期
    • 仓库类型PKCS12、算法RSA、DSA;长度2048

客户端HTTPS配置

  • 配置HttpClient
    • SSLContextBuilder构建SSLContext
    • setSSLHostnameVerifier(new NoopHostnameVerifier())
  • 配置RequestFactory
    • HttpComponentsClientHttpRequestFactory
      • setHttpClient

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

常用工具类

  • 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
  • 可以直接执行的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

https://12factor.net/

  • 基准代码:一份基准代码,多份部署
    • 使用版本管理系统
    • 基准代码与应用程序保持一一对应的关系
    • 尽管每个应用只对应一份基准代码,单可以同时存在多份部署,如local、dev、prod
  • 依赖:显式声明依赖关系
    • 通过依赖清单,确切声明所有依赖项,如maven
  • 配置:在环境中存储配置,外化配置、配置中心
  • 后端服务:把后端服务作为附加资源
    • 如数据库、缓存等都视为资源
  • 构建,发布,运行:严格分离构建和运行
    • 每发布一个版本必须对应一个唯一的发布ID
  • 进程:以一个或者多个无状态进程运行应用
    • 任何需要持久化的数据都要存储在后端服务内
  • 端口绑定:通过端口绑定提供服务
  • 并发:通过进程模型进行拓展
  • 易处理:快速启动和优雅终止可最大化健壮性
    • 追求最小启动时间
    • 进程一旦接收终止信号就会优雅终止
    • 进程应当在面对突然死亡时保持健壮
  • 开发环境和线上环境等价:尽可能得保持开发、预发布、线上环境相同
    • 想要做到持续部署就必须缩小本地和线上的差异
    • 后端服务是保持开发与线上等价的重要部分,反对在不同环境中使用不同的后端服务。
  • 日志:把日志当作事件流
  • 管理进程:后台管理任务当作一次性进程运行

Spring Cloud组件

image-20230121213817174

  • 服务发现
  • 服务熔断
  • 配置服务
  • 服务安全,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
2
eureka.client.service-url.default-zone
eureka.client.instance.prefer-ip-address

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

使用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
2
3
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
spring.cloud.consul.discovery.prefer-ip-address=true
  • docker启动
1
2
3
4
docker run --name consul -d -p 8500:8500 -p 8600:8600/udp consul

# 客户端DNS
dig @127.0.0.1 -p 8600 xxx.service.xxx

Nacos作为服务注册中心

Nacos

  • 阿里巴巴开源,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台
  • 功能
    • 动态服务配置
    • 服务发现和管理
    • 动态DNS服务

image-20230122002717756

Spring结合

  • 依赖:spring-cloud-alibaba-dependenciesspring-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>
    • 提供一个配置类,声明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
  • 配置刷新
    • @RefreshScope,用于Bean上面
    • Endpoint:/actuator/refresh,或者依赖SpringCloudBus

基于ZK

  • 依赖:spring-cloud-starter-zookeeper-config

  • 启用

    • bootstrap.yml
    1
    2
    spring.cloud.zookeeper.config.enabled
    spring.cloud.zookeeper.connect-string
  • 存储格式/config/applicationprofile/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
  • 刷新机制:通知

基于Apollo

  • 有版本发布管理
  • 灰度发布
  • 权限管理、审计
  • 客户端配置信息监控
  • 开放平台API

Spring Cloud Stream

概览

  • 一款用于构建消息驱动的微服务应用程序的轻量级框架
  • 特性
    • 声明式编程模型
    • 引入多种概念抽象
      • 发布订阅、消费组、分区
    • 支持多种消息中间件
  • 核心概念:Binder
    • 应用程序与Binder交互,Binder与中间件交互
    • @EnableBinding
    • @Input、SubscribableChannel
    • @Output、MessgaChannel
  • 消费组:对于同一个消息,每个组中有且仅有一个消费者收到消息
  • 分区:每个Topic下有多个分区,分区内消息可以认为是有序的
  • 生产消息
    • 使用MessageChannel中的send
    • 方法上使用@SendTo,将方法返回值作为消息发送出去
  • 消费消息
    • 方法上使用@StreamListerner
      • 方法参数:@Payload、@Headers、@Header
  • 其它:使用Spring Integration

访问RabbitMQ

  • 依赖:spring-cloud-starter-stream-rabbitspring-boot-starter-amqp
  • 配置
1
2
3
spring.cloud.stream.rabbit.binder.*
spring.cloud.stream.rabbit.bindings.<channelName>.consumer.*
spring.rabbitmq.*

访问Kafka

  • 依赖:spring-cloud-starter-stream-kafka
  • 配置
1
2
3
spring.cloud.stream.kafka.binder.*
spring.cloud.stream.kafka.bindings.<ChannelName>.consumer.*
spring.kafka.*

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进行埋点

服务治理关注点

  • 宏观
    • 架构设计是否合理
    • 哪个链路是关键链路
    • 链路的容量水位趋势
    • 对系统变更的管理与审计
  • 微观上
    • 系统的依赖
    • 系统的配置
    • 系统的主观、客观质量