Spring@Springboot知识体系
2022-06-14 23:11:05 2 举报
AI智能生成
为你推荐
查看更多
Spring@Springboot知识体系
作者其他创作
大纲/内容
Spring@Springboot知识体系
spring
spring概述
图解
Core Container
core
Beans
Context
AOP
基于代理的AOP支持
Data Access/Integration
Spring-JDBC:提供以JDBC访问数据库的支持;
Spring-TX:提供编程式和声明式的事务支持;
Spring-ORM:提供对对象/关系映射技术的支持;
Spring-OXM:提供对对象/xml映射技术的支持;
Spring-JMS:提供对JMS的支持。
Spring应用场景
Spring Boot :使用默认开发配置来实现快速开发;
Spring Cloud:为分布式系统开发提供工具集;
Spring Data:对主流的关系型和NoSQL数据库的支持;
Spring Batch:简化及优化大量数据的批处理操作;
Spring Security:通过认证和授权保护应用;
Spring Web Flow:基于Spring MVC提供基于向导流程式的Web应用开发。
spring基础
Spring概述
Spring的简史
xml配置
注解配置
java配置
Spring体系
Spring的模块
核心容器CoreContainer
Spring-Core
Spring-Beans
Spring-Context
Spring-Context-Support
Spring-Expression
Spring-AOP
Spring-Aspects
Messaging
Spring-Messaging
WEB
Spring-Web
Spring-Webmvc
Spring-WebSocket
Spring-Webmvc-Portlet
数据访问/集成(DataAccess/Intefration)
Spring-JDBC
Spring-TX
Spring-ORM
Spring-OXM
Spring-JMS
Spring的生态
Spring Boot
Spring XD
Spring Cloud
Spring Data
Spring Integration
Spring Batch
Spring Security
Spring HATEOAS
Spring Social
Spring AMQP
Spring Mobile
Spring for Android
Spring Web Flow
Spring Web Services
Spring LDAP
Spring Session
Spring项目快速搭建
Maven简介
Maven安装
Maven的pom.xml
dependencies
dependency
变量定义
编译插件
Spring项目的搭建
Spring Tool Suite
https://spring.io/tools/sts/all
IntelliJ IDEA
NetBeans
https://netbeans.org/downloads/
Spring基础配置
依赖注入
声明Bean的注解
@Service在业务逻辑层(service层)
@Repository在数据访问层(dao层)
@Controller在展现层(MVC→SpringMVC)
注入Bean的注解
@Autowired:Spring提供的注解
@Inject:JSR-330提供的注解
@Resource:JSR-250提供的注解
Java配置
@Configuration声明当前类是一个配置类
@Aspect 声明是一个切面
拦截规则@After @Before @Around
PointCut
JoinPoint
spring原理
Spring Core
Bean的Scope
Singleton
对象出生:当创建容器时,对象就被创建了。对象活着:只要容器在,对象一直活着。对象死亡:当销毁容器时,对象就被销毁了。句话总结:单例模式的bean对象的命周期与容器相同
Prototype
对象出生:当使用对象时,创建新的对象实例。对象活着:只要对象在使用中,就一直活着。对象死亡:当对象长时间不用时,被java的垃圾回收器回收了。句话总结:多例模式的bean对象,spring框架只负责创建,不负责销毁。
Request
Session
GlobalSession
Bean的装配
基于xml(手动装配)
创建Bean对象方式
通过全限定类名(默认构造函数)
通过工程方法
静态工厂
工厂类
XML配置
实例工厂
装配Bean属性方式
setter注入
条件:属性必须有setter方法
bean标签下<property>标签
name:属性名
value:属性值,针对基本类型和String类型
ref:针对对象类型,指向的是bean标签的id属性的值
复杂注入(map、list、[]...)
<bean id=\"empService\" class=\"com.wxs.service.EmpService\"> <property name=\"list\"> <list> <value>基本类型和String类型</value> <ref bean=\"对象类型\"></ref> </list> </property></bean>
list类型语法
数组类型与list类型类似只是没有ref标签
map类型
<bean id=\"empService\" class=\"com.wxs.service.EmpService\"> <property name=\"list\"> <map> <entry key=\"\" value=\"\"></entry> </map> </property></bean>
properties类型
<bean id=\"empService\" class=\"com.wxs.service.EmpService\"> <property name=\"p\"> <props> <prop key=\"\" value=\"\"></prop> </props> </property></bean>
有参构造器注入
条件:必须要有构造器
bean标签下<constructor-arg>标签
name属性:属性名
value:值,针对基本类型和Stirng
ref:针对对象类型
p名称空间注入
条件:需要在配置文件中导入p的命名空间(spring提供的),底层还是set方式,所以属性也必须有setter方法
基于注解(自动装配)
添加注解扫描
在配置文件中用<context:component-scan base-package=\"com.wxs\" />配置需要扫描的包
装配Bean
在类上用@Component注解标记,类中的依赖关系用@Autowired注解标记
四个创建对象的注解
Component:无法划分类的时候
Repository:一般用于标注dao层或者说标注数据库操作层
Service:业务层
Controller:控制层/表现层(springmvc替代servlet)
Scope:定义类的单例多例
PreDestory
指定销毁方法
PostConstruct
指定初始化方法
说明
以上四个注解没有区别,只是用于不同场景
装配Bean属性
三个依赖注入的注解
Value
针对基本数据类型和String类型
Autowired
该注解由Spring框架提供
按类型去找,如果找不到就是没有,如果找到多个就报错,解决方式是搭配Qualifier注解指明适用哪个注解
Resource
该注解由JDK提供
先按名字去找,第一种是name属性配置名字@Resource(name = \"名字\"),如果没有指定名字则把变量名当作要寻找的属性名,如果再找不到,最后按类型去找
IoC控制反转
概念
控制:对对象的创建和管理
反转:对对象的控制由程序员转变为框架
目的:让spring来管理对象
优点:降低耦合(类与类之间的依赖关系)
ID依赖注入
组件之间依赖关系由容器在运行期决定,即容器动态将某个依赖关系注入到组件中通过依赖注入机制,我们只需要通过简单的配置,无需任何代码就可以指定目标需要的资源。完成自身的业务逻辑,而不需要关系具体的资源来自何处,由谁实现。
Bean实例化流程
bean信息注册与bean实例化
bean创建
子主题
容器概述
BeanFactory
是spring的心脏,表示它是一个工厂类
负责生产和管理bean的一个工厂
包括:实例化,配置和管理bean以及建立这些对象间的依赖
ApplicationContext常用实现类
ClassPathXmlApplicationContext
读取类路径下的配置文件
FileSystemXmlApplicationContext
读取电脑任意位置的配置文件
AnnotationConfigApplicationContext
用于使用新注解+配置类的方式代替xml配置文件时
ApplicationContext 还继承了ResourceLoader、MessageSource
BeanFactory和ApplicationContext的区别
单例对象适用AplicationContext在构建核心容器时,创建对象采用的是立即加载的方式,即配置文件一读取完,立马创建对象
多例对象适用BeanFactory在构建核心容器时,创建对象采用的是延迟加载方式,即什么时候通过Id获取对象,什么时候创建
容器初始化流程
第一步:刷新前的预处理 prepareRefresh();
第二步:获取BeanFactory;默认实现是DefaultListableBeanFactory加载BeanDefition 并注册到 BeanDefitionRegistryConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
第三步:BeanFactory的预准备工作(BeanFactory进行一些设置,比如context的类加载器等)prepareBeanFactory(beanFactory);
第四步:BeanFactory准备工作完成后进入的后置处理⼯作postProcessBeanFactory(beanFactory);
第五步:实例化并调用实现了BeanFactoryPostProcessor接口的BeaninvokeBeanFactoryPostProcessors(beanFactory);
第六步:注册BeanPostProcessor(Bean的后置处理器),在创建bean的前后等执行registerBeanPostProcessors(beanFactory);
第七步:初始化MessageSource组件(做国际化功能;消息绑定,消息解析);initMessageSource();
第八步:初始化事件派发器initApplicationEventMulticaster();
第九步:子类重写这个方法,在容器刷新的时候可以子定义逻辑onRefresh();
第十步:注册应用的监听器。就是注册实现了ApplicationListener接口的监听器beanregisterListeners();
第十一步:初始化所有剩下的懒加载的单例bean初始化创建懒加载⽅式的单例Bean实例(未设置属性)填充属性初始化⽅法调⽤(⽐如调⽤afterPropertiesSet⽅法、init-method⽅法)调⽤BeanPostProcessor(后置处理器)对实例bean进⾏后置处finishBeanFactoryInitialization(beanFactory);
第十二步:完成context的刷新。主要是调⽤LifecycleProcessor的onRefresh()⽅法,并且发布事件 (ContextRefreshedEvent)finishRefresh();
Spring AOP
AOP基本概念
面向切面编程思想:对共同内容进行抽取,在需要用到的地方用动态代理的方式进行插入,在不修改源代码的基础上,还能对源码进行加强
对目标类方法进行加强的方式
继承:
缺点:需要直到要增强的方法的类才能继承
装饰者模式
缺点:需要有接口,这个接口下除了要增强的方法外别的方法也要实现
动态代理模式
JDK
需要接口但可以指定增强方法,不需要实现全部方法
参数列表:和目标对象相同的类加载器;目标类所有的接口;增强类(可以自定义增强类并实现InvlcationHandler接口并重写其内部方法,也可以在此处直接定义匿名内部类)
细节
proxyPerson.run(); // 执行这个方法 invoke都会执行一遍 执行的内容就是针对该方法的增强
返回值 return 谁调用返回给谁 返回的内容就是最终值而不是需要增强的方法的返回值
通过if-else判断方法名来增强指定方法
CGLIB
不需要接口,可以指定增强方法,但代码量比较大
CGLIB原理
该代理模式是用拦截器和过滤器的方式进行继承,对目标类的方法进行增强
Spring AOP术语
Target(目标对象) 被代理对象
Joinpoint(连接点) 就是需要增强的方法
Pointcut(切入点) 已经把增强代码加入到业务主线进来之后的连接点
Advice(通知/增强) 切入类中用于提供增强功能的方法。其分类有:前置通知 后置通知 异常通知 最终通知 环绕通知
Weaving(织入) 把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,AspectJ采用编译期织入和类装载期织入。
Proxy(代理) 代理对象
Aspect(切面) 是切入点与通知的结合
总结 : Aspect切面= 切入点+增强= 切入点(锁定方法) + 位点(锁定方法中的特殊时机)+ 横切逻辑
AOP的三种方式
自由式
步骤
确定目标类(要被切的类,即需要被加强的类),需要定义切入点,此处切入点为需要增强的方法
确定切面类,即用来切类的刀,需要定义增强后的方法
织入配置,把增强方法指定在切入点之前、之后、环绕、异常、最终 执行
配置文件
织入时机
前置增强
用<aop:before>标签配置
后置增强
用<aop:after>标签配置
在原方法执行结束后介入增强后的方法
环绕增强
用<aop:around>标签配置,需要在增强后的方法中传参:ProceedingJoinPoint类型的对象,这个对象中包含着目标类需要增强的方法,需要在增强后的方法中调用pjp.proceed()方法,相当于调用原方法,在该方法前后需要写自己的业务逻辑实现环绕介入
异常增强
用<aop:after-throwing>标签配置
在原方法发生异常时会介入,一般用于对数据库事务的处理
最终增强
用<aop:after-returning>标签配置
在需要增强的方法正确地返回之后执行
接口规范式
<aop:config> <!-- 定义切点 即需要被增强的方法 --> <aop:pointcut id=\"empCut\" expression=\"execution(..........)\"></aop:pointcut> <!-- 定义切面 指向bean标签中的切面类 包含切点(指向上方的切点) --> <aop:advisor advice-ref=\"bean标签对应的切面类\" pointcut-ref=\"empCut\"></aop:advisor></aop:config>
定义切面类,让其实现特定接口(五类织入时机)
确定目标类(被介入的类),确定其切点
确定切面类(做介入角色的类)
定义的切面类需要实现MethodBeforeAdvice接口并实现befor方法
该方式底层会调用目标类中需要增强的方法,在该切面类中的before方法中只需要写自己的业务逻辑即可
定义的切面类需要实现AfterReturnAdvice接口并实现afterReturn方法
参数
Object returnValue
原方法返回值
Method method
目标方法
Object[] args
目标方法执行需要的参数数组
Object target
目标对象,即被代理的类的对象
切面类需要实现MethodInterceptor接口并实现invoke(MethodInvocation invocation)方法
切面类实现ThrowsAdvice接口,该接口是一个空接口,需要在该切面类中自定义名为afterThrowing(Exception e)方法
注解介入
spring mvc
springmvc概述
springmvc实际上是springframwork的一个模块,这个模块主要是对web的支持
springmvc是基于IoC和aop的
servlet缺点
获取参数比较繁琐,如果类型不是字符串类型则需要进行类型转换,还需要判断是否为空
如果每个servlet对应一个请求,则会产生大量的servlet,如果一个servlet对应多个请求,则违反可单一原则
spring mvc处理流程
springmvc提供了一个servlet,我们把所有的请求都发送给这个servlet,这个servlet我们称之为核心控制器
核心控制器在tomcat启动时就会创建,在其init方法中会读取配置文件并扫描指定的包,会为由@Controller注解标记的类创建对象,并把所有的由@RequestMapping注解标记的映射关系放到HandlerMapping中,键放注解的地址,值放方法
当在地址栏输入地址,核心控制器会根据资源路径从HandlerMapping中寻找要执行的方法,找到后并调用
在控制类的方法中处理请求和响应,用return实现请求转发(携带的参数放到ModelMap中)和重定向(在返回的字符串前加redirect)
三大核心组件
处理器映射器
作用:帮我们找到对应的controller
HandlerMapping
传统开发方式,即配置文件方式
依赖BeanNameUrlHandlerMapping类
注解开发方式,已过时类
AnnotationMethodHandlerAdapter(过时的注解开发方式)
注解开发方式,最新类
RequestMappingHandlerAdapter(最新版本的注解开发方式)
在springmvc内部配置文件中,注解开发方式配置的还是过时的注解驱动类,需要在springmvc配置文件中用<mvc:annotation-driven/>标签配置新版注解驱动类
处理器适配器
作用:帮我们找到响应的方法
方法返回ModelAndView
拦截器
框架提供的有跟过滤器功能类似但更强大的拦截器
拦截器会拦截Controller类中方法的调用
在controller类中方法执行前被拦截
在controller类的方法执行之后但在视图解析前被拦截
方法执行完且视图解析之后拦截
快速入门
1. 定义一个类实现HandlerInterceptor接口
2. 实现该接口中的方法,所有的方法返回值为boolean,真放行,假拦截
该接口中的方法为默认方法,每个方法都有不同的拦截时机
在controller的方法被调用之前执行该方法
在方法被调用视图解析之前调用
在方法执行完视图解析之后调用
3. 在配置文件中配置拦截器,可以配置多个拦截器,哪个在上边,最先执行哪个拦截器
<mvc:interceptors> <mvc:interceptor> <!-- 配置哪个方法需要拦截 --> <mvc:mapping path=\"/**\"> <!-- 配置哪个方法不需要拦截 --> <mvc:exclued-mapping path=\"\"> <!-- 设置拦截器类路径 --> <bean class=\"拦截器类全限定名\"> </mvc:interceptor></mvc:interceptors>
执行顺序
两个兰拦截器,1拦截器配置在前,2拦截器配置在后
视图解析器
将结果渲染成页面
控制类中的注解
@Controller
标记控制类,该类拥有处理请求的能力
@RequesMapping
标注方法,定义请求路径
窄化映射,可以定义到controller类上,隔离各个控制类中的方法
value和path属性
标注这个方法处理请求的地址,支持传数组,可以响应多个请求
method
设置接收的请求的请求方式
@ResponseBody
@CrossOrigin
设置跨域访问
传统方式需要设置响应头setHeader(\"Access-Control-Allow-Origin\
浏览器的同源策略
同源指的是同一个服务器
如果a服务器向b服务器发送ajax请求,b服务器接收并响应数据,在默认情况下,a服务器的ajax拒绝接收b服务器的响应,所以需要在b服务器端设置跨域访问,解决跨域错误问题
@PathVaribale
用于绑定url的占位符,例如:在请求的url中,/emplist/{empId},{empId}就是一个占位符,在参数列表中想要对应占位符的参数前用该注解标注,该注解中的值应当与占位符的值一致。url支持占位符是在spring3.0以后引入的
用于实现restful风格
如果想要实现restful风格,则需要将web.xml文件中核心控制器的请求路径设置为/,但此时将会把所有的静态文件例如js、css等也作为请求发送到核心控制器并去找相应的方法执行,此时就会访问不到静态资源,所以释放静态资源
在springmvc配置文件中配置静态资源,用<mvc:resources location=\"请求地址例如:/js/(以js开头的请求)\" mapping=\"映射位置例如 :/js/**(项目下js文件夹下所有的文件的子文件)\" />
restful风格
用占位符的方式接收参数,占位符的参数名叫啥,前端name应该叫啥
传统风格
RequestMapping(\"/delete\")localhost:8080/delete?id=10
RequestMapping(\"/delete/{id}\")restful风格:localhost:8080/delete/10
@ModelAttribute
被该注解标注的方法会先执行
适用场景:当前端提交表单,带着表单数据向控制类中的某个方法发送请求,但表单数据并不是一个完整的JavaBean对象的数据,此时可以定义一个新的方法,用该注解标注,那么在执行对应请求方法时会先执行该方法,该方法也可以从请求中获取请求参数,可以在该方法中通过请求参数从数据库查询完整数据,并将最后JavaBean对象返回,这样数据就会完整,另一种方式是无返回值方法,可以参参数列表定义一个map集合,将最后的JavaBean放入map集合中,在对应的请求方法的参数列表中也用ModelAttribute注解标注参数,并在注解中给出放入map集合的key
注解语法糖
在spring4.2.x版本及以后出现了复合注解
@GetMapping(\"/\")
@PostMapping
直接指明请求方式
@RestController
@Controller和@ResponseBody的符合注解
参数绑定
默认参数绑定
request
response
session
ModelMap
基本数据类型
在对应方法的参数列表中定义请求参数
类型写你需要的,底层会帮你转,要求参数列表中的参数名与请求参数名一致
原理
mvc会反射你的方法参数列表,根据参数名去找请求参数对应的值,会尝试将数据转成你想要的类型,如果不能转成你想要的,抛异常
bean方式
可以使用对象接收,在参数列表定义对象类型,mvc可以直接自动封装成对象,前提是对象的属性名跟请求参数名一致
绑定包装的bean
数组绑定
一般用于批量删除,在前端定义复选框,复选框的名称相同且和控制类对应方法的数组名一致,springmvc可自动帮你获取参数
集合绑定
应用场景不多,一般用于批量修改,前端修改n条数据,提交多个对象到后台,但只能支持向对象中接收集合,即控制类对应方法中需要定义一个集合,接收参数时会接收到该对象的集合中,而且要求前端name属性为集合名[下标].对象属性名在jsp页面的c:foreach标签中的status属性可以获取遍历的集合的每次索引值
注解方式
@RequestParam注解,标记参数列表
注解属性
value/name
指明要获取的参数名,用于跟请求参数名匹配
required
默认为true,要求请求参数必须有,如果没有,则出现400,设为false则可以没有
defaultValue
用于定义参数列表的默认值,如果请求参数没有传来,则默认值生效
自定义转换器
当前端参数出现springmvc无法自动转换的参数时,例如时间,可以使用自定义转换器
实现convert(T t)方法并返回想要的
将自定义转换器配置到springmvc容器中
在注册新版处理器映射器,处理器适配器驱动时,将自定义转换器配置<mvc:annotation-driven conversion-service=\"自定义转换器id\"/>
配置自定义转换器<bean id=\"\" class=\"org.springframework.format.support.FormattingConversionServiceFactoryBean\"> <property name=\"convers\"> <set><bean class=\"自己定义的转换器类的全限定名\"/></set> </property></bean>
注解方式解决mvc不支持的参数绑定
将spring不支持的绑定类型参数上用@DateTimeFormat(pattern = \"yyyy-MM-dd HH:mm:ss\")
spring dao
spring boot
SpringBoot概述
什么是SpringBoot
SpringBoot核心功能
独立运行的Spring项目
内嵌Servlet容器
提供Starter简化Maven配置
自动配置Spring
准生产的应用监控
无代码声称和xml配置
SpringBoot的优缺点
优点
快速构建项目
对主流开发框架的无配置集成
提供运行时的应用监控
与云计算的天然集成
缺点
SpringBoot版本
SpringBoot快速搭建
http://start.spring.io
SpringToolSuite
InterlliJIDEA
SpringBootCLI
Maven手工构建
简单演示
SpringBoot核心
基本配置
入口类和@SpringBootApplication
@Configuration
@EnableAutoConfiguration
@ComponentScan
关闭特定的自动配置
定制Banner
修改Banner
关闭Banner
main里修改
fluentAPI
SpringBoot的配置文件
application.properties
application.yml
src/main/resources
starter pom
官方starter pom
spring-boot-starter
spring-boot-starter-actuator
spring-boot-starter-remote-shell
spring-boot-starter-amqp
spring-boot-starter-aop
spring-boot-starter-batch
spring-boot-starter-cache
spring-boot-starter-cloud-connectors
spring-boot-starter-data-elasticsearch
spring-boot-starter-data-gemfire
spring-boot-starter-data-jpa
spring-boot-starter-data-mongodb
spring-boot-starter-data-rest
spring-boot-starter-data-solr
spring-boot-starter-freemarker
spring-boot-starter-groovy-templates
spring-boot-starter-hateoas
spring-boot-starter-hornetq
spring-boot-starter-integration
spring-boot-starter-jdbc
spring-boot-starter-jerscy
spring-boot-starter-jta-atomikos
spring-boot-starter-jta-bitronix
spring-boot-starter-mail
spring-boot-starter-mobile
spring-boot-starter-mustache
spring-boot-starter-redis
spring-boot-starter-security
spring-boot-starter-social-facebook
spring-boot-starter-social-linkedin
spring-boot-starter-social-twitter
spring-boot-starter-test
spring-boot-starter-thymeleaf
spring-boot-starter-velocity
spring-boot-starter-web
spring-boot-starter-Tomcat
spring-boot-starter-Jetty
spring-boot-starter-undertow
spring-boot-starter-logging
spring-boot-starter-log4j
spring-boot-starter-websocket
spring-boot-starter-ws
第三方starter pom
Handlebars
Vaadin
Apache Camel
WRO4J
HDIV
Jade Templates(jade4J)
Actitivi
使用XML配置
@ImportResource
外部配置
命令行参数配置
常规属性配置
类型安全的配置(基于properties)
日志配置
Profile配置
SpringBoot运行原理
运作原理
核心注解
@ConditionalOnBean
@ConditionalOnClass
@ConditionalOnExpression
@ConditionalOnJava
@ConditionalOnJndi
ConditionalOnMissingBean
ConditionalOnMissingClass
ConditionalOnNotWebApplication
ConditionalOnProperty
ConditionalOnResource
ConditionalOnSingleCandidate
ConditionalOnWebApplication
实例分析
配置参数
配置Bean
实战
SpringBoot的数据访问
SpringDataJPA
什么是Spring Data JPA
定义数据访问层
配置使用Spring Data JPA
定义查询方法
根据属性名查询
常规查询
限制结果数量
使用JPA的NamedQuery
使用@Query查询
使用参数索引
使用命名参数
更新查询
Specification
排序与分页
定义
使用排序
使用分页
自定义Repository的实现
定义自定义Repository接口
定义接口实现
自定义ReposityFactoryBean
开启自定义支持使用@EnableJpaRepositories的repositoryFactoryBeanClass来指定FactoryBean即可
SpringBoot的支持
JDBC的自动配置
对JPA的自动配置
对Spring Data JPA的自动配置
Spring Boot下的Spring Data JPA
声明式事务
Spring的事务机制
JDBC
DataSourceTransactionManager
JPA
JpaTransactionManger
Hibernate
HibernateTransactionManger
JDO
JdoTransactionManger
分布式事务
JtaTransactionManager
注解事务行为
类级别使用@Transactional
SpringDataJPA的事务支持
SpringBoot的事务支持
自动配置的事务管理器
自动开启注解事务的支持
SpringDataREST
Spring Data REST
什么是Spring Data REST
Spring MVC中配置使用Spring Data REST
继承方式
导入方式
数据缓存Cache
Spring缓存支持
Spring支持的CacheManager
SimpleCacheManager
ConcurrentMapCacheManager
NoOpCacheManager
EhCacheCacheManager
GuavaCacheManager
HazelcastCacheManager
JCacheCacheManager
RedisCacheManager
声明式缓存注解
@Cacheable
@CachePut
@CacheEvict
@Caching
开启声明式缓存支持
切换缓存技术
EhCache
Guava
Redis
非关系型数据库NoSQL
MongoDB
Spring的支持
Object/Document映射注解支持
@Document
@Id
DbRef
@Field
@Version
MongoTemplate
Repository的支持
安装MongoDB
非Docker
Docker安装
配置
使用
opsForValue()
opsForList()
opsForSet()
opsForZSet()
opsForHash()
定义Serializer
Spring Boot的支持
安装Redis
非Docker安装
spring cloud
服务注册发现
概述
服务注册就是维护一个登记簿,它管理系统内所有的服务地址。当新的服务启动后,它会向登记簿交待自己的地址信息。服务的依赖方直接向登记簿要 Service Provider 地址就行了
分类
zookeeper
Consul
Etcd
eureka
Nacos
核心概念
Eureka Server
服务注册
服务提供者启动时,会通过 Eureka Client 向 Eureka Server 注册信息Eureka Server 会存储该服务的信息Eureka Server 内部有二层缓存机制来维护整个注册表
提供注册表
服务消费者在调用服务时,如果 Eureka Client 没有缓存注册表的话,会从 Eureka Server 获取最新的注册表
同步状态
Eureka Client 通过注册、心跳机制和 Eureka Server 同步当前客户端的状态。
Eureka Client
Eureka Client 是一个 Java 客户端,用于简化与 Eureka Server 的交互。Eureka Client 会拉取、更新和缓存 Eureka Server 中的信息。因此当所有的 Eureka Server 节点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者,但是当服务有更改的时候会出现信息不一致。
流程
Register: 服务注册
服务的提供者,将自身注册到注册中心,服务提供者也是一个 Eureka Client。当 Eureka Client 向 Eureka Server 注册时,它提供自身的元数据,比如 IP 地址、端口,运行状况指示符 URL,主页等。
Renew: 服务续约
Eureka Client 会每隔 30 秒发送一次心跳来续约。 通过续约来告知 Eureka Server 该 Eureka Client 运行正常,没有出现问题。 默认情况下,如果 Eureka Server 在 90 秒内没有收到 Eureka Client 的续约,Server 端会将实例从其注册表中删除,此时间可配置,一般情况不建议更改。
Eviction 服务剔除
当 Eureka Client 和 Eureka Server 不再有心跳时,Eureka Server 会将该服务实例从服务注册列表中删除,即服务剔除。
Cancel: 服务下线
Eureka Client 在程序关闭时向 Eureka Server 发送取消请求。 发送请求后,该客户端实例信息将从 Eureka Server 的实例注册表中删除。该下线请求不会自动完成,它需要调用以下内容:DiscoveryManager.getInstance().shutdownComponent();
GetRegisty: 获取注册列表信息
Eureka Client 从服务器获取注册表信息,并将其缓存在本地。客户端会使用该信息查找其他服务,从而进行远程调用。该注册列表信息定期(每30秒钟)更新一次。每次返回注册列表信息可能与 Eureka Client 的缓存信息不同,Eureka Client 自动处理。
Remote Call: 远程调用
当 Eureka Client 从注册中心获取到服务提供者信息后,就可以通过 Http 请求调用对应的服务;服务提供者有多个时,Eureka Client 客户端会通过 Ribbon 自动进行负载均衡。
集群部署
数据模型
服务提供方启动
服务提供者在启动的时候,会在ZooKeeper上注册服务。所谓注册服务,其实就是在ZooKeeper的/dubbo/com.foo.BarService/providers节点下创建一个子节点,并写入自己的URL地址,这就代表了com.foo.BarService这个服务的一个提供者。
服务消费者启动
服务消费者在启动的时候,会向ZooKeeper注册中心订阅自己的服务。其实,就是读取并订阅ZooKeeper上/dubbo/com.foo.BarService/providers节点下的所有子节点,并解析出所有提供者的URL地址来作为该服务地址列表。
消费者远程调用提供者
服务消费者,从提供者地址列表中,基于软负载均衡算法,选一个提供者进行调用,如果调用失败,再选另一个提供者调用。
增加服务提供者
增加提供者,也就是在providers下面新建子节点。服务消费方监听provider节点,一旦该节点的内容有变动,provider就会将一个变更通知推送给所有客户端,客户端收到通知后就会主动去provider那拉取最新的服务地址列表。
这里有必要介绍ZK的数据发布与订阅。发布订阅一般有两种设计模式:推和拉。在推模式中,服务器端主动将数据更新发送给所有订阅的客户端;拉模式则是由客户端主动发起请求来获取最新数据,通常客户端都采用定时进行轮询拉取的方式。ZK采用推拉相结合的模式:客户端向服务端注册自己需要关注的节点,一旦该节点的数据发生变更,那么服务端就会向相应的客户端发送watcher事件通知,客户端接收到这个消息通知后,需要主动到服务端获取最新的数据。
减少服务提供者
所有提供者在ZooKeeper上创建的节点都是临时节点,利用的是临时节点的生命周期和客户端会话相关的特性,因此一旦提供者所在的机器出现故障导致该提供者无法对外提供服务时,该临时节点就会自动从ZooKeeper上删除,同样,zookeeper会把provider节点数据变更通知推送给consumer,consumer就会前来拉取最新的服务地址。
集群部署架构
Consul Server
Consul Client
原理图
配置中心
Apollo
Spring Cloud Config
选型分析
API 网关
网关概述
API Gateway 基础
API网关诞生的背景
在没有API网关之前,客户端是如何与服务端交互的?
客户端与服务端直接交互
每个服务端都需要自己实现权限校验、限流、waf等功能
微服务粒度较细,客户端所需API粒度较大
客户端需要多次调用服务端接口
不通客户端需要不同数据
pc端
mobile端
服务端功能演进较快,要对客户端屏蔽改变
服务端的协议适合直接暴露到外部吗?
需要协议转换来搞定
API网关需要具备哪些能力?
路由
API聚合
协议转换
流量控制
熔断降级
黑白名单
身份认证
日志
监控
高扩展
高性能
高可用
控制台(可视化管理)
网关分类
流量网关
处理入口流量
统一入口
安全
流控
业务网关
业务鉴权
业务处理
业务编排
API Gateway生态
编程语言实现
Go语言
Tyk
Tyk Open Source API Gateway written in Go
跟Kong、APISIX类似,面向应用,实现权限校验、限流等等
https://tyk.io/
https://github.com/TykTechnologies/tyk
Star 5k
KrakenD
Ultra performant API Gateway with middlewares
核心功能、聚焦API聚合
https://www.krakend.io/
https://github.com/devopsfaith/krakend
Star 2K
JavaScript语言
Express Gateway
A microservices API Gateway built on top of Express.js
https://www.express-gateway.io/
https://github.com/expressgateway/express-gateway
Star 2k
C++语言
Envoy
Gloo
An Envoy-Powered API Gateway
https://www.solo.io/
https://github.com/solo-io/gloo
Star 2.1k
Ambassador
open source Kubernetes-native API gateway for microservices built on the Envoy Proxy
https://www.getambassador.io/
https://github.com/datawire/ambassador
Star 2.5k
Nginx+lua
Openresty
发展历史
衍生产品
Kong
The Cloud-Native API Gateway
https://konghq.com/
https://github.com/Kong/kong
Star 25k
APISIX
Cloud-Native Microservices API Gateway
https://apisix.apache.org/
https://github.com/apache/incubator-apisix
企业版
https://openresty.com.cn/cn/about/
tengine
基于Nginx的1.8分支衍生,做了很多的修改,当然nginx里面有什么,tengine也一直在紧随nginx官方的步伐
最新的2.3.2版本已经升级nginx内核到1.17.3版本
http://tengine.taobao.org/
网关方案分析
产品介绍
Nginx
模块编译
Lua及C++开发(OpenResty)
具备URL转发映射及反向代理功能
效率高
如具备身份认证与安全、审查与监控,需要模块化开发,开发成本高
限于HTTP的解析,非JAVA语言开发
基于OpenResty的 API 网关服务和网关服务管理层
基于Nginx的,所以在性能和稳定性上表现不错
插件扩展功能
前置的负载均衡器分发请求
网关热更新,不重启服务
多种集群缓存
需要自研相应功能插件
有一定的学习成本
Netflix 的 Zuul
核心是一系列的过滤器
JAVA开发
可以扩展自己需要的过滤器
性能和线上大面积故障
Spring Cloud 的 Zuul
Spring Cloud整合和增强
JAVA原生,设计简单代码不多,容易读懂;同步 Servlet,采用多线程阻塞模型;
增加了安全验证、动态路由、负载分配等
线程本身需要消耗 CPU 和内存资源,多线程之间切换开销多;
预热后性能更会好,Servlet容器把.class文件中的数据读到内存中;
更新需要重启中断服务;
网络请求处理位于高层次网络层
Spring Cloud Gateway
Spring Cloud的开源项目之一
与整合增强zuul地位不一样
效率相对较高
基于JAVA,运行体量大
依赖使用Spring多套框架
netty自研API网关
利用Netty实现的filter
利用了netty的高性能
可以实现的filter来增加各种功能
需要从头开发,踩坑会较多
filter越多性能会不断下降
缓存不容易做好
概要描述
重点对比
语言
zuul:JAVA
优势
kong:LUA
设计
zuul:设计简单代码不多,容易读懂
kong:脚本作用于Nginx的不同工作阶段,需要原理性理解
功能扩展
zuul:通过filter重复开发
kong:通过插件扩展功能
负载层次
zuul:顶位负载网络层
kong:四层或七层网络层负载
负载均衡器
zuul:后置的负载均衡器分发请求
kong:前置的负载均衡器分发请求
网关更新
zuul:会中断服务
kong:热更新,不中断服务
性能
zuul:性能平稳
kong:性能优秀
Hystrix
产生背景
分布式系统环境下,服务间类似依赖非常常见,一个业务调用通常依赖多个基础服务。对于同步调用,当库存服务不可用时,商品服务请求线程被阻塞,当有大批量请求调用库存服务时,最终可能导致整个商品服务资源耗尽,无法继续对外提供服务。并且这种不可用可能沿请求调用链向上传递,这种现象被称为雪崩效应。
雪崩效应常见场景
硬件故障:如服务器宕机,机房断电,光纤被挖断等。
流量激增:如异常流量,重试加大流量等。
缓存穿透:一般发生在应用重启,所有缓存失效时,以及短时间内大量缓存失效时。大量的缓存不命中,使请求直击后端服务,造成服务提供者超负荷运行,引起服务不可用。
同步等待:服务间采用同步调用模式,同步等待造成的资源耗尽。
雪崩效应应对策略
硬件故障:多机房容灾、异地多活等。
流量激增:服务自动扩容、流量控制(限流、关闭重试)等。
缓存穿透:缓存预加载、缓存异步加载等。
同步等待:资源隔离、MQ解耦、不可用服务调用快速失败等。资源隔离通常指不同服务调用采用不同的线程池;不可用服务调用快速失败一般通过熔断器模式结合超时机制实现。
参考资料
https://blog.csdn.net/loushuiyifan/article/details/82702522
Hystrix设计目标:
对来自依赖的延迟和故障进行防护和控制——这些依赖通常都是通过网络访问的
阻止故障的连锁反应
快速失败并迅速恢复
回退并优雅降级
提供近实时的监控与告警
Hystrix遵循的设计原则:
防止任何单独的依赖耗尽资源(线程)
过载立即切断并快速失败,防止排队
尽可能提供回退以保护用户免受故障
使用隔离技术(例如隔板,泳道和断路器模式)来限制任何一个依赖的影响
通过近实时的指标,监控和告警,确保故障被及时发现
通过动态修改配置属性,确保故障及时恢复
防止整个依赖客户端执行失败,而不仅仅是网络通信
功能说明
资源隔离
总结
资源隔离主要指对线程的隔离:Hystrix提供了两种线程隔离方式:线程池和信号量
线程池隔离
保护应用程序以免受来自依赖故障的影响,指定依赖线程池饱和不会影响应用程序的其余部分。当引入新客户端lib时,即使发生问题,也是在本lib中,并不会影响到其他内容。当依赖从故障恢复正常时,应用程序会立即恢复正常的性能。当应用程序一些配置参数错误时,线程池的运行状况会很快检测到这一点(通过增加错误,延迟,超时,拒绝等),同时可以通过动态属性进行实时纠正错误的参数配置。如果服务的性能有变化,需要实时调整,比如增加或者减少超时时间,更改重试次数,可以通过线程池指标动态属性修改,而且不会影响到其他调用请求。除了隔离优势外,hystrix拥有专门的线程池可提供内置的并发功能,使得可以在同步调用之上构建异步门面(外观模式),为异步编程提供了支持(Hystrix引入了Rxjava异步框架)。
线程池的主要缺点是增加了计算开销。每个命令的执行都在单独的线程完成,增加了排队、调度和上下文切换的开销。因此,要使用Hystrix,就必须接受它带来的开销,以换取它所提供的好处。通常情况下,线程池引入的开销足够小,不会有重大的成本或性能影响。但对于一些访问延迟极低的服务,如只依赖内存缓存,线程池引入的开销就比较明显了,这时候使用线程池隔离技术就不适合了,我们需要考虑更轻量级的方式,如信号量隔离。
线程隔离-信号量
上面提到了线程池隔离的缺点,当依赖延迟极低的服务时,线程池隔离技术引入的开销超过了它所带来的好处。这时候可以使用信号量隔离技术来代替,通过设置信号量来限制对任何给定依赖的并发调用量。下图说明了线程池隔离和信号量隔离的主要区别:
熔断
Hystrix在运行过程中会向每个commandKey对应的熔断器报告成功、失败、超时和拒绝的状态,熔断器维护并统计这些数据,并根据这些统计信息来决策熔断开关是否打开。如果打开,熔断后续请求,快速返回。隔一段时间(默认是5s)之后熔断器尝试半开,放入一部分流量请求进来,相当于对依赖服务进行一次健康检查,如果请求成功,熔断器关闭。
熔断器工作原理
熔断器配置
Circuit Breaker主要包括如下6个参数:1、circuitBreaker.enabled是否启用熔断器,默认是TRUE。2 、circuitBreaker.forceOpen熔断器强制打开,始终保持打开状态,不关注熔断开关的实际状态。默认值FLASE。3、circuitBreaker.forceClosed熔断器强制关闭,始终保持关闭状态,不关注熔断开关的实际状态。默认值FLASE。4、circuitBreaker.errorThresholdPercentage错误率,默认值50%,例如一段时间(10s)内有100个请求,其中有54个超时或者异常,那么这段时间内的错误率是54%,大于了默认值50%,这种情况下会触发熔断器打开。5、circuitBreaker.requestVolumeThreshold默认值20。含义是一段时间内至少有20个请求才进行errorThresholdPercentage计算。比如一段时间了有19个请求,且这些请求全部失败了,错误率是100%,但熔断器不会打开,总请求数不满足20。6、circuitBreaker.sleepWindowInMilliseconds半开状态试探睡眠时间,默认值5000ms。如:当熔断器开启5000ms之后,会尝试放过去一部分流量进行试探,确定依赖服务是否恢复
熔断器执行流程
第一步,调用allowRequest()判断是否允许将请求提交到线程池如果熔断器强制打开,circuitBreaker.forceOpen为true,不允许放行,返回。如果熔断器强制关闭,circuitBreaker.forceClosed为true,允许放行。此外不必关注熔断器实际状态,也就是说熔断器仍然会维护统计数据和开关状态,只是不生效而已。
第二步,调用isOpen()判断熔断器开关是否打开如果熔断器开关打开,进入第三步,否则继续;如果一个周期内总的请求数小于circuitBreaker.requestVolumeThreshold的值,允许请求放行,否则继续;如果一个周期内错误率小于circuitBreaker.errorThresholdPercentage的值,允许请求放行。否则,打开熔断器开关,进入第三步。
第三步,调用allowSingleTest()判断是否允许单个请求通行,检查依赖服务是否恢复如果熔断器打开,且距离熔断器打开的时间或上一次试探请求放行的时间超过circuitBreaker.sleepWindowInMilliseconds的值时,熔断器器进入半开状态,允许放行一个试探请求;否则,不允许放行。
回退降级
降级,通常指务高峰期,为了保证核心服务正常运行,需要停掉一些不太重要的业务,或者某些服务不可用时,执行备用逻辑从故障服务中快速失败或快速返回,以保障主体业务不受影响。Hystrix提供的降级主要是为了容错,保证当前服务不受依赖服务故障的影响,从而提高服务的健壮性。要支持回退或降级处理,可以重写HystrixCommand的getFallBack方法或HystrixObservableCommand的resumeWithFallback方法。
降级回退方式
Fail Fast 快速失败
快速失败是最普通的命令执行方法,命令没有重写降级逻辑。 如果命令执行发生任何类型的故障,它将直接抛出异常。
Fail Silent 无声失败
Netflix Feign
是一个http请求调用的轻量级框架,可以以Java接口注解的方式调用Http请求,而不用像Java中通过封装HTTP请求报文的方式直接调用。Feign通过处理注解,将请求模板化,当实际调用的时候,传入参数,根据参数再应用到请求上,进而转化成真正的请求,这种请求相对而言比较直观。
Feign处理流程
PHASE 1. 基于面向接口的动态代理方式生成实现类
在Feign 底层,通过基于面向接口的动态代理方式生成实现类,将请求调用委托到动态代理实现类,基本原理如下所示:
PHASE 2. 根据Contract协议规则,解析接口类的注解信息,解析成内部表现:
Feign 默认的协议规范
基于Spring MVC的协议规范SpringMvcContract:
PHASE 3. 基于 RequestBean,动态生成Request
PHASE 4. 使用Encoder 将Bean转换成 Http报文正文(消息解析和转码逻辑)
PHASE 5. 拦截器负责对请求和返回进行装饰处理
在请求转换的过程中,Feign 抽象出来了拦截器接口,用于用户自定义对请求的操作:
PHASE 6. 日志记录
PHASE 7 . 基于重试器发送HTTP请求
PHASE 8. 发送Http请求
Feign 真正发送HTTP请求是委托给 feign.Client 来做的:
注意事项
https://blog.csdn.net/luanlouis/article/details/82821294
负载均衡
F5:硬件负载均衡器,功能很好,但是成本很高。
lvs:重量级的四层负载软件。
nginx:轻量级的四层负载软件,带缓存功能,正则表达式较灵活。
haproxy:模拟四层转发,较灵活。
负载均衡概述
负载均衡,英文叫Load Balance,意思就是将请求或者数据分摊到多个操作单元上进行执行,共同完成工作任务。负载均衡(Load Balance)建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。
作用
其一是将大量的并发处理转发给后端多个节点处理,减少工作响应时间;
其二是将单个繁重的工作转发给后端多个节点处理,处理完再返回给负载均衡中心,再返回给用户。
DNS负载均衡
这种是属于较早出现的技术,其利用域名解析实现负载均衡,在DNS服务器配置多个A记录,这些A记录对应的服务器构成集群互相减轻服务压力。大型网站总是部分使用DNS解析,作为第一级负载均衡。
二层负载均衡(MAC)
二层负载均衡又叫链路层负载均衡,其对应OSI模型的第二层,基于MAC地址进行服务分发。
三层负载均衡(IP)
三层对应OSI模型的网络层,三层负载均衡提供一个虚拟IP对外提供服务,当请求进入负载均衡器后转发至集群中某个真实IP,这里的虚拟IP可能是一个外网IP,而真实IP可能是内网IP。
四层负载均衡(TCP)
OSI模型的四层主要协议是TCP/UDP,其特点是在IP负载均衡的基础上基于IP及端口号来进行负载均衡。
F5、LVS、Nginx、HAProxy
HAProxy、Nginx、Apache、MySQL Proxy
七层负载均衡(HTTP)
负载均衡算法
轮循均衡(Round Robin)
权重轮循均衡(Weighted Round Robin)
随机均衡(Random)
权重随机均衡(Weighted Random)
响应速度均衡(Response Time探测时间)
最少连接数均衡(Least Connection)
处理能力均衡(CPU、内存)
DNS响应均衡(Flash DNS)
哈希算法
IP地址散列(保证客户端服务器对应关系稳定)
Ribbon
架构图
https://blog.csdn.net/fly910905/article/details/100023415?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param
差异对象
0 条评论
回复 删除
下一页