- @FeignClient注解的作用是什么?(告诉Feign Starter,在项目启动时,为此注解描述的接口创建实现类-代理类)
- 如何理解基于Feign方式的远程服务调用?(底层封装了服务调用过程,明修栈道暗度陈仓)
- Feign方式如何实现负载均衡?(底层基于ribbon组件实现)
- Feign接口指向的对象是谁?(代理对象-feign接口的实现类对象)
- 常用服务发现、服务调用方式有哪些?
* 这部分内容中你接触到了哪些设计模式呢?(单例,享元,代理,工厂,模板方法,策略,观察者,…)
常见Bug分析
- SocketTimeoutException,例如:
- NullPointerException,例如:
- 负载均衡类的配置问题,例如:
- 端口被占用,例如
- UnknownHostException,例如
- Fien接口对象依赖注入异常,例如:
- 数据读取超时,例如:
- 服务访问时的404异常,例如:
- Feign接口方法中@PathVariable注解参数定义问题,例如:
- 读数据超时,例如:
- 依赖注入异常,例如:
课后作业
- 完成课上知识点总结。
- 实践基于RestTemplate和Feign方式的服务调用。
- 预习05-Nacos配置中心应用实践。
- 尝试完成Idea中Http Client 工具的应用?(基于此工具进行restful风格的请求测试)
- 修改sca-consumer端默认的负载均衡策略?(自己查资料实现)
方案1:修改sca-consumer配置文件(application.yml),添加如下语句,例如:
sca-provider: #这个是要进行远程调用的服务id(服务名)
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #负载均衡算法
对于方案1写法,在写的过程没有提示,编写困难,但是将来的可运维性会比较好,我们这部分配置写到配置中心,不需要重启服务即可实现配置的动态发布,动态更新。
方案2:修改sca-consumer的启动类,在启动类中添加如下方法,例如:
@Bean
public IRule ribbonRule() {
return new RandomRule();
}
对于方案2的写法,编写相对简单,编写过程都有提示,但是将来的可运维性比较差,项目打包以后,我们无法再修改负载均衡算法。
Day04~Nacos配置中心应用实践
=============================================================================
核心知识点
- 配置中心诞生背景。
- 市场上主流的配置中心。
- Nacos配置中心简介。
- Nacos配置中心入门实践。
- Nacos配置中心的配置管理模型。
常见问题分析
- 什么是配置中心?(存储项目配置信息的一个服务,这个服务可以实现配置的动态发布和更新)
- 为什么要使用配置中心?(集中管理配置信息,动态发布配置信息,服务自动感知配置)
- 市场上有哪些主流的配置中心?(Apollo,nacos,……)
- 配置中心一般都会配置什么内容?(可能会经常变化的配置信息,例如连接池,日志、线程池、限流熔断规则)
- 什么信息一般不会写到配置中心?(服务端口,服务名,服务的注册地址,配置中心地址)
- 项目中为什么要定义bootstrap.yml文件?(此文件被读取的优先级比较高,可以在服务启动时读取配置中心的数据)
- Nacos配置中心宕机了,我们的服务还可以读取到配置信息吗?(可以从服务的本地内存读取)
- 微服务应用中客户端如何感知配置中心数据变化?(1.4.x版本的nacos客户端会基于长轮询机制从nacos获取配置信息)
- 服务启动后没有从配置中心获取我们的配置数据是什么原因?(依赖,bootstrap.yml,配置单词,格式,配置模型)
- 你项目中使用的日志规范是什么?(SLF4J~门面模式)
- 你了解项目中的日志级别吗?(debug,info,warn,error可以基于日志级别控制日志的输出)
- Nacos配置管理模型的背景?(环境不同配置不同)
- Nacos配置中的管理模型是怎样的?(namespace>group>service/data-id)
- Nacos客户端(微服务)是否可以读取共享配置?(可以)
常见Bug分析
- mysql中没有配置中心数据,例如:
- 包导入错误,例如:
- 配置中心配置格式不正确,例如:
- 程序中服务读取配置时,找不到配置,例如:
课后作业
- 总结课上知识点
- 完成文档中的共享配置应用.
- 预习06-sentinel限流熔断操作实践。
- 尝试设计并完成一个本地cache的应用(拓展-CopyOnWriteArrayList)。
在ProviderCacheController,进行本地缓存设计应用,例如:
private CopyOnWriteArrayList cache=new CopyOnWriteArrayList<>();
@GetMapping(“/provider/cache02”)
public List doUseLocalCache02(){
if(!useLocalCache){//假如useLocalCache的值为false,表示不开启本地cache.
log.info(“select data from database”);
return Arrays.asList(“A”,“B”,“C”);//假设这些数据来自数据库
}
if(cache.isEmpty()){
synchronized (this) {
if (cache.isEmpty()) {
//模拟从数据库获取数据
log.info(“select data from database”);
List data = Arrays.asList(“A”, “B”, “C”);
//将数据放入cache中
cache.addAll(data);
}
}
}
log.info(“select data from cache”);
return cache;
}
Day05-Sentinel 限流应用实践
===============================================================================
核心知识点
- 服务限流、降级的背景(服务的治理)
- Sentinel限流入门实践(控制台8180-定义规则,客户端服务应用规则:依赖,配置)
- Sentinel常用限流模式(直接->当前url,关联->保证核心业务,链路->红绿灯)
- @SentinelResource注解作用及限流异常处理(AOP设计)
- Sentinel默认异常限流处理类(DefaultBlockExceptionHandler)
常见问题分析
- 为什么要进行限流、降级? (系统处理能力有限,可以通过限流方式,保证系统可靠运行,以退为进)
- 你了解Sentinel限流有哪些算法? (计数器,令牌桶,漏桶,滑动窗口算法~sentinel默认)
- Sentinel常用限流模式?(直接,关联->保证核心业务,链路->红绿灯)
- @SentinelResource注解的作用,你用过哪些属性?(在链路限流中描述资源节点,切入点方法)
- Sentinel常用限流效果有哪些?(快速失败,预热,排队)
- Sentinel中限流被触发时出现的异常类型是什么?(都是BlockException类型的子类)
- 如何对限流结果进行处理?(有默认处理方案-DefaultBlockExceptionHandler,也可以自定义.)
- Sentinel限流的基本原理?(底层对服务请求进行拦截,然后通过流控规则限定对资源访问)
常见Bug分析
- sentinel 服务启动不起来?(要配置jdk环境变量path,要使用JDK8版本)
- sentinel 面板不显示我们的服务?(依赖,配置>一定要注意缩进,先访问,放大招-清idea缓存重启)
- 配置完sentinel后,业务服务启动不了了?(大部分都是配置错了)
课后作业
- 总结课上知识点.
- 了解常用限流算法.
- 预习并尝试完成Sentinel服务降级,热点规则设计,系统规则设置,授权规则设置.
- 预习07~spring cloud gateway网关。
- 基于spring mvc 拦截器对系统中指定资源进行时间访问限制?
第一步:拦截器原理分析(回顾spring mvc中的拦截器),例如:
第二步:自定义拦截器,例如:
package com.jt.provider.interceptor;
public class TimeInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println(“preHandle”);
//1.获取当前时间
LocalTime now = LocalTime.now();//LocalTime为jdk8中的一个获取当前时间的api
//2.获取当前的小时并进行逻辑判断
int hour = now.getHour();//8:10~8
System.out.println(“hour=”+hour);
if(hour<9||hour>18){
throw new RuntimeException(“请在9~18时间范围内访问”);//return false
}
return true;//false请求到此结束,true表示放行,会去执行后续的拦截器或controller对象
}
}
第三步:配置拦截器,例如:
package com.jt;
@Configuration
public class SpringWebConfig implements WebMvcConfigurer {
/**
- 注册拦截器(添加到spring容器),并指定拦截规则
- @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TimeInterceptor())
.addPathPatterns(“/provider/sentinel01”);
}
}
第四步:打开浏览器,对/provider/sentinel01路径进行访问,对访问结果进行访问。
Day06-Sentinel 进阶应用实践
===============================================================================
核心知识点
- Sentinel降级(熔断)入门实现(出现不稳当的系统服务时,暂停对此服务的访问)
- Sentinel实现热点参数限流(热点视频,文章,…)
- Sentinel系统规则配置(例如cpu使用率,QPS,…),
- Sentinel授权规则配置(黑白名单,黑白设计由业务决定)
常见问题分析
- 如何理解熔断?(可以理解为暂时关闭不稳定的服务,要学会舍得)
- 如何自定义熔断异常处理规则?(实现BlockExceptionHandler接口)
- 如何理解热点参数?(频繁访问的数据,系统底层如何判定哪些数据是频繁访问-lru)
- 系统规则是全局规则吗,常见规则有哪些? (是,响应时间-RT,QPS,CPU,线程数)
- 授权规则需要我们自己写请求解析类吗?(需要,实现RequestOriginParser接口)
常见Bug分析
- 请求参数单词错误。
- …
课后作业
- 总结课上知识点。
- 了解Lru算法解决了什么问题?
- 总结几个Sentinel中用到设计模式?
- 预习API网关Gateway限流实现(07-网关应用实践)。
Day07-Gateway 应用实践
============================================================================
核心知识点
- API 网关(Gateway)诞生背景
- 市场主流微服务网关(Spring Cloud Gateway,zuul,…)
- API Gateway实现服务的保护和转发(重点)
- API Gateway层面的负载均衡实现(重点,lb://sca-provider)
- API Gateway请求处理原理分析(重点:官方图,了解关键代码,执行过程)
- API Gateway中常用谓词(predicate)对象及实践。
常见问题分析
- 为什么要使用api网关?(服务保护,统一url访问,统一身份认证,统一跨域设计,。。。)
- 网关入门实践的步骤? (依赖,配置,启动,服务访问)
- 网关项目中的负载均衡是如何实现?(底层基于Ribbon实现,可以在RibbonLoadBalancerClient中加断点分析)
- 说说SpringCloud gateway处理请求的基本流程?(官方,断点)
- 网关中的谓词对象类型?(GatewayPredicate)
- 网关中的谓词对象是如何创建的?(谓词工厂)
- 你在网关中配置过哪些常用谓词?(Path,Method,Before,Query,Header,…)
常见BUG分析
- 配置文件格式不正确,例如
- 服务访问被拒绝,例如
- 服务注册失败(nacos没启动),例如:
- 503 异常(找不到可用的服务)
课后作业
- 总结课上知识点
- 练习基于Gateway实现负载均衡方式的配置。
- 练习常用谓词(Predicate)应用。
- 预习并尝试完成网关中的过滤器以及sentinel限流设计。
Day08-Gateway 应用进阶实践
==============================================================================
核心知识点
- API Gateway中过滤器(Filter)的类型及实践。
- API Gateway中基于sentinel实现服务限流(API,路由id)。
- API Gateway中基于自定义限流结果的处理(GatewayCallbackManager)。
常见问题分析
- 网关中的过滤器是如何分类的?(GlobalFilter,GatewayFilter:需要手动配置)
- 我们是否可以自定义谓词,过滤器对象?(可以,参考官方默认的定义)
- 网关层面如何基于sentinel实现限流?(有关sentinel的两个依赖,配置,JVM参数)
- 网关层面的限流类型有哪些?(路由id,API分组)
- 我们是否可以对限流结果进行自定义处理?(可以)
课堂练习
- 网关中设置黑白名单?
第一步:在配置文件添加如下配置,例如:
web:
request: # 注意假如属性名是两个单词,要用"-"进行连接,例如black-urls
black-urls: # 系统底层解析这部分时,会自动以"-"作为分隔符,将内容存储到list集合
• /nacos/provider/echo/a
• /nacos/provider/echo/b
第二步:在项目中添加一个全局过滤器,例如:
package com.jt.filter;
import org.apache.http.HttpHeaders;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.ArrayList;
import java.util.List;
/**
• 基于此全局过滤器对请求url进行黑白名单识别
• @ConfigurationProperties 注解描述类时,用于告诉系统底层
• 要从配置文件中读取指定配置信息(prefix属性用于指定读取哪部分
• 前缀对应的信息)
*/
@ConfigurationProperties(prefix = “web.request”)
@Component
public class BlackUrlGlobalFilter implements GlobalFilter, Ordered {//Authentication(认证)
private List blackUrls=new ArrayList<>();
/**
• 当系统底层读取@ConfigurationProperties(prefix = “web.request”)
• 注解中描述的内容时,会自动基于名字调用此set方法
*/
public void setBlackUrls(List blacks) {
this.blackUrls = blacks;
}
/**
• 此方法为一个处理请求的方法
• @param exchange 基于此对象获取请求和响应
• @param chain 过滤链对象
• @return SpringWebFlux中的Mono对象(一个Publisher对象),
• 是springframework5.0后推出的新特性,
*/
@Override
public Mono filter(ServerWebExchange exchange,
GatewayFilterChain chain) {
//1.获取请求和响应对象
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
//2.获取请求url
String urlPath=request.getURI().getPath();//nacos/provider/echo/gateway
System.out.println(“blackPath=”+blackUrls);
System.out.println(“urlPath=”+urlPath);
//3.对请求url进行黑白名单分析
//黑名单则请求到此结束
if(blackUrls.contains(urlPath)){
//设置响应状态码
response.setStatusCode(HttpStatus.UNAUTHORIZED);//401
//设置请求头中响应数据内容类型
response.getHeaders()
.add(HttpHeaders.CONTENT_TYPE,“text/html;charset=utf-8”);
//构建一个数据buffer对象
DataBuffer dataBuffer=
response.bufferFactory()
.wrap(“请求url是黑名单”.getBytes());
//将数据封装到Mono对象
return response.writeWith(Mono.just(dataBuffer));
}
//白名单则放行(执行下一步,假如有下个过滤器,就执行下一个过滤器)
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -1;
}
}
• 自定网关层面的限流异常处理对象?
package com.jt.callback;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.fastjson.JSON;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.HashMap;
import java.util.Map;
@Component
public class GatewayRequestBlockHandler implements BlockRequestHandler {
@Override
public Mono handleRequest(
ServerWebExchange serverWebExchange,
Throwable throwable) {
Map<String,Object> map=new HashMap<>();
map.put(“state”,429);
map.put(“message”,“two many request”);
String jsonStr= JSON.toJSONString(map);
// return ServerResponse.ok()
// .body(Mono.just(jsonStr), String.class);
return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)
.contentType(MediaType.TEXT_PLAIN)
.body(Mono.just(jsonStr), String.class);
}
}
课后作业
- 总结课上知识点
- 完成黑白单全局过滤器的设计
- 完成网关层面基于路由ID和API分组方式的限流
- 完成网关层面自定义限流异常的处理.
- 微服务架构下ajax请求响应处理实践。
第一步:业务描述(通过sca-ui工程向网关工程发送ajax请求,并进行响应处理)
第二步:创建sca-ui工程的html页面,然后通过触发按钮发送ajax请求,例如
Title
The Index Page
Buy
第三步:在sca-gateway的配置文件或配置中心中添加跨域配置,例如:
spring:
cloud:
gateway:
globalcors: #跨域配置
cors-configurations:
‘[/**]’:
allowedOrigins: “*”
allowedMethods: “*”
第五步:按项目架构设计启动服务,进行测试。
http://localhost:8080/index.html
- 将路由配置写到配置中心进行实践?(自己动手丰衣足食)
第一步:在sca-gateway项目中添加配置依赖,例如:
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-config
第二步:修改application.yml配置文件名称为bootstrap.yml,并添加配置中心配置。
spring:
cloud:
nacos:
config:
server-addr: localhost:8848
file-extension: yml
第三步:在nacos的public命名空间中创建sca-gateway.yml配置,内容如下:
说明,此配置添加后,可以将bootstrap.yml中网关部分的配置注释掉。
第四步:启动nacos,sentinel,provider,gateway服务,然后进行访问测试。
Day09~单点登录系统初步设计及实现
=============================================================================
核心知识点
- 单点登录系统诞生的背景。
- Java中单点登录系统解决方案。
- 单点登录系统(SSO)中的服务划分及关系设计。
- 单点登录系统中父工程的创建及初始化。
- 系统基础服务(sso-system)工程的创建及初始化
- 系统基础服务(sso-system)工程中pojo对象设计及实现
常见问题分析
- 为什么要做单点登录设计?(业务简化,代码复用,不需要每个服务都登录一次)
- 你知道哪些SSO系统解决方案?(基于用户登录状态信息的存储进行方案设计)
- 单点登录系统中你的服务是如何设计的,工程结构是怎样的?
- 项目中使用的连接池什么?(HikariCP)
- Java中连接池设计需要遵循的数据源规范是谁?(javax.sql.DataSource)
- 连接池这块你能想到的设计模式有哪些?(单例,享元,桥接,slf4j门面)
- 如何排除springboot工程中junit4依赖?
- SpringBoot工程中如何基于junit4的单元测试?
- SpringBoot工程中如何基于Junit5进行单元测试?
- SpringBoot单元测试类应该写在哪个位置?
- 基于idea的为类自动生成序列化id?
第一步:修改idea中的配置。
第二步:在User类上按alt+enter,例如:
- @Autowired注解描述的Mapper对象有红色波浪线,但运行没有错误,如何去除红色波浪线。
常见Bug分析
- MySql指令不可用,例如:
- 单元测试类位置写错了,例如:
- 单元测试类定义的位置不正确,例如
- Springboot工程中中存在多个启动类,例如
- DataSource包导入错误,例如:
- 单元测试方法不能有参数,例如: