面试高频
问题总结
登录时候
token别盗用怎么办?
Nginx负载均衡算法(项目后面用gateway实现的)
round-robin负载均衡算法
每个请求按时间逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除
缺点:可靠性低和负载分配不均衡。
加权
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。(比如某个服务器是8G,某个又是4G),权重越高,访问概率越大。
ip_hash
上述方式存在一个问题,在负载均衡系统中,假如用户在某台服务器上登录了,那么该用户第二次请求的时候,因为我们是负载均衡系统,每次请求都会重新定位到服务器集群中的某一个,那么已经登录某一个服务器的用户再重新定位到另一个服务器,其登录信息将会丢失,这样显然是不妥的。
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session不能跨服务器的问题。
注意:
此策略适合有状态服务,比如session
当有服务器需要剔除,必须手动down掉
当一台上游服务器损坏,下线了,不能简单的直接从配置中移除,因为移除后,hash算法就会改变,就会影响其他的原本路由到其他服务器的请求也会发生变化。
一致性hash
这个能环节上一个问题。
通过这种方法,可以使得发生扩容或者宕机的时候,路由不会发生大规模的变化。
4、least_conn
把请求转发给连接数较少的后端服务器。轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_conn这种方式就可以达到更好的负载均衡效果。
nacos服务注册和发现
feign服务调用
https://www.jianshu.com/p/e0218c142d03
概念
Feign是一个http请求调用的轻量级框架,封装了Http调用流程,依赖服务发现组件来实现远程接口调用,实现服务之间的解耦。
大概过程:
(1) 基于面向接口的动态代理方式生成实现类
(2) 根据Contract协议规则,解析接口类的注解信息,解析成内部表现
(3) 基于 RequestBean,动态生成Request
根据传入的Bean对象和注解信息,从中提取出相应的值,来构造Http Request 对象
(4) 使用Encoder 将Bean转换成 Http报文正文
(5) 拦截器负责对请求和返回进行装饰处理(这个拦截器是可以自定义)
(6) 日志记录
(7) 基于重试器发送HTTP请求
Feign 内置了一个重试器,当HTTP请求出现IO异常时,Feign会有一个最大尝试次数发送请求
(8) 发送Http请求
Feign 真正发送HTTP请求是委托给 feign.Client 来做的。
Feign 默认底层通过JDK 的 java.net.HttpURLConnection 实现了feign.Client接口类,在每次发送请求的时候,都会创建新的HttpURLConnection 链接,这也就是为什么默认情况下Feign的性能很差的原因。可以通过拓展该接口,使用Apache HttpClient 或者OkHttp3等基于连接池的高性能Http客户端。
Feign优化
GZIP压缩:减小数据大小,加快网页加载速度。
替换为HttpClient客户端(使用HTTP连接池提供性能)
HttpURLConnection(不支持连接池)和HttpClient(可以用连接池)
HttpURLConnection是JDK自带的HTTP客户端技术,并不支持连接池,
在一般情况下,如果只是需要向Web站点的某个简单页面提交请求并获取服务器响应,HttpURLConnection完全可以胜任。但在绝大部分情况下,Web站点的网页可能没这么简单,这些页面并不是通过一个简单的URL就可访问的,可能需要用户登录而且具有相应的权限才可访问该页面。在这种情况下,就需要涉及Session、Cookie的处理了,如果打算使用HttpURLConnection来处理这些细节,当然也是可能实现的,只是处理起来难度就大了。
简单来说,HttpClient就是一个增强版的HttpURLConnection,HttpURLConnection可以做的事情HttpClient全部可以做;HttpURLConnection没有提供的有些功能,HttpClient也提供了,但它只是关注于如何发送请求、接收响应,以及管理HTTP连接。
hystrix原理待更新
https://blog.csdn.net/loushuiyifan/article/details/82702522
背景
业务之间具有复杂的依赖和调用关系,因此,微服务中各个子服务之间依赖关系比较复杂,如果某个上游子服务因为网络故障或者操作系统资源不足出现接口调用异常,也会导致下游业务异常,如果上游服务没有很好的请求拒绝策略,会导致请求不断增加,大量的请求积压会导致当前服务和下游服务宕机,继而引起雪崩效应。
简介
主要提供了几种容错方法:
- 资源隔离(线程池和信号量两种机制)
- 熔断(失败率达到阈值)
- 降级(超时降级,资源不足时候降级)
工作流程
Hystrix整个工作流如下:
-
构造一个HystrixCommand或HystrixObservableCommand对象,用于封装请求,并在构造方法配置请求被执行需要的参数;
-
执行命令,Hystrix提供了4种执行命令的方法,后面详述;
-
判断是否使用缓存响应请求,若启用了缓存,且缓存可用,直接使用缓存响应请求。Hystrix支持请求缓存,但需要用户自定义启动;
-
判断熔断器是否打开,如果打开,跳到第8步;
-
判断线程池/队列/信号量是否已满,已满则跳到第8步;
-
执行HystrixObservableCommand.construct()或HystrixCommand.run(),如果执行失败或者超时,跳到第8步;否则,跳到第9步;
-
统计熔断器监控指标;
-
走Fallback备用逻辑
-
返回请求响应
从流程图上可知道,第5步线程池/队列/信号量已满时,还会执行第7步逻辑,更新熔断器统计信息,而第6步无论成功与否,都会更新熔断器统计信息。
线程池隔离
Hystrix通过命令模式对发送请求的对象和执行请求的对象进行解耦,将不同类型的业务请求封装为对应的命令请求。
通常情况下,线程池引入的开销足够小,不会有重大的成本或性能影响。但对于一些访问延迟极低的服务,如只依赖内存缓存,线程池引入的开销就比较明显了,这时候使用线程池隔离技术就不适合了,我们需要考虑更轻量级的方式,如信号量隔离。
信号量 因为请求的线程和执行的线程都是一个,所以是阻塞的
通过设置信号量来限制对任何给定依赖的并发调用量
信号量隔离主要是通过控制并发请求量,防止请求线程大面积阻塞,从而达到限流和防止雪崩的目的。
线程池和信号量 总结对比
线程池和信号量都可以做线程隔离,但各有各的优缺点和支持的场景,对比如下
线程池和信号量都支持熔断和限流。相比线程池,信号量不需要线程切换,因此避免了不必要的开销。但是信号量不支持异步,也不支持超时,也就是说当所请求的服务不可用时,信号量会控制超过限制的请求立即返回,但是已经持有信号量的线程只能等待服务响应或从超时中返回(正因为这样,它不支持超时),即可能出现长时间等待。线程池模式下,当超过指定时间未响应的服务,Hystrix会通过响应中断的方式通知线程立即结束并返回。
线程池隔离无法传递http header,因为是不同的线程,具有自己的thread local
服务熔断
服务降级
降级,通常指务高峰期,为了保证核心服务正常运行,需要停掉一些不太重要的业务,或者某些服务不可用时,执行备用逻辑从故障服务中快速失败或快速返回,以保障主体业务不受影响。Hystrix提供的降级主要是为了容错,保证当前服务不受依赖服务故障的影响,从而提高服务的健壮性。要支持回退或降级处理,可以重写HystrixCommand的getFallBack方法或HystrixObservableCommand的resumeWithFallback方法。
Hystrix在以下几种情况下会走降级逻辑:
- 执行construct()或run()抛出异常
- 熔断器打开导致命令短路
- 命令的线程池和队列或信号量的容量超额,命令被拒绝
- 命令执行超时
服务监控
springsecurity原理待更新
gateway原理待更新
怎么保证redis和数据库数据保证一致(好像前端页面也可以进行缓存)
每次获取数据的时候,先查询redis里面是否有数据,如果没有,我就从数据库里面查询,查询完再放到redis里面。如果是更新数据,那就更新到数据库以后,我把redis里面数据删除,删除后redis就为空,这样下次获取数据就只能从数据库获得。
秒杀系统
加密MD5
第一次:前端用户输入后传递到后端过程加密一次
第二次:从后端写入到数据库当中进行第二次 加密
数据库设计
商品表,订单表,秒杀商品表,订单秒杀表;因为活动特别多,如果只用一个表,会很麻烦。
秒杀功能实现
1、判断库存
2、判断是否重复抢购
这样才可以抢购
3、生成订单和秒杀订单
谷粒学院在线教育
简介
项目经历主要包括一个关于Java后端开发的在线教育项目。该项目主要分为前台系统和后台系统,前台系统实现了数据显示、课程列表显示、课程支付等功能,后台系统主要实现了课程管理、教师管理、权限管理、用户登录注册、短信模块、视频存储等模块。项目采用前后端分离开发,后端主要采用springboot+springcloud微服务架构,基于JWT+token+cookie实现单点登录,使用springsecurity进行权限管理,Spring Cloud实现请求转发、功能模块微服务化、服务调用、请求转发;
项目总体架构和表关系
功能模块
1.讲师管理模块(service_edu)
2.课程分类管理模块(service_edu)
3.课程视频模块(视频,章、节service_vod)
5.订单管理(看下后台订单状态,购买,取消后买,未支付)service_order
6.banner管理(轮播图或者是幻灯片)
7.权限管理(管理员,普通用户,管理员具有删除各种信息权限)service_acl模块
common:
- common-utills模块:统一返回结果(R),JWT,MD5,
- service-base: redis,swagger,异常处理
service
service_edu:讲师管理,课程管理
service_oss:头像存储,
service_vod:视频点播服务
service_ucenter:用户登录模块
service_msm:短信验证服务
service_order:订单管理模块
service_cms:banner(有疑问)
service_acl:权限管理模块
数据库设计关系
edu-course和edu_course_description是一对一但是分成两个表,原因是:个人理解 因为简介使用text储存的 所以单独分出来 减少冗余 提高查询速度。
service-edu
mybatis-plus:只是对mybatis一个增强工具,并没有对她进行改变,使得效率更高
主键ID生成策略
参考资料:分布式系统唯一ID生成方案汇总:https://www.cnblogs.com/haoxinyue/p/5208136.html
1.自动增长,mysql里面 AUTO INCREMENT
缺点:比如用户数据多,可能要 放在三个表正当中, id:1~10000 10001 ~20000.。。就是说后面还需要的到上个表当中的最后一个id,不方便。
2.UUID 每次随机生成唯一的值
缺点:无法进行排序
3. Redis生成ID
当使用数据库来生成ID性能不够要求的时候,我们可以尝试使用Redis来生成ID。这主要依赖于Redis是单线程的,所以也可以用生成全局唯一的ID。可以用Redis的原子操作 INCR和INCRBY来实现。
4.mp自带策略:雪花策略(也是项目中使用的策略)
使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。
网络跨域
NetworkError
访问协议:http,https
IP地址:
端口号:
添加课程最后发布信息的时候
内连接:查询两张有关联的表,就下图绿色框,只能查询前端,后端
左外连接:左外连接右边,左边表数据全部查出来,不管运维有没有关联都能查,mysql没有关联,所以mysql查不出来
右外连接就是相反。
一般用内连接和左外连接多一些。
在我们这个场景里面,对于课程,可能没有讲师,也可能没有描述,所以用内连接不合适。
课程评论功能 需要远程调用
day15.
表:edu_comment
service-oss
endpoint
accessKeyId
accessKeySecret
创建OSSClient实例:OSSClient ossClient
设置文件流:InputStream inputStream = file.getInputStream();
Nginx:反向代理服务器
科普:正向代理代理的是客户端,反向代理代理的是服务端
三个作用:
请求转发:我们用的功能
负载均衡:后面是网关实现的
动静分离:如果访问是java代码,就去找Tomcat,如果是图片静态资源去找静态服务器,内容不同,找的对象不同。静态资源Nginx可以直接返回。
sercice-vod
阿里云视频点播服务
加密之后有域名才可以播放
加密之后,地址就不可以再播放,此时存储地址没有意义,所以数据库里面存储的不是地址,存储的是id,有了ID可以得到播放地址和播放凭证
根据视频id获取播放凭证
//创建初始化对象
DefaultAcsClient client = initObject.initVodClient("LTAI4GGnytWA3JTwjsXHbNac", "veqAkwrnLZD9CKIHUcJMfKDgH9ha8Z");
GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();
GetVideoPlayAuthResponse response = new GetVideoPlayAuthResponse();
request.setVideoId("00105b81a8aa440f99e3f985ee071c5b");
//得到播放凭证
response = client.getAcsResponse(request);
System.out.println("playauth:"+response.getPlayAuth());
删小节的时候把阿里云视频也要删掉(day10)
删小节是service-edu当中,删除视频是在service-vod当中,一个服务需要调用另外一个服务
当然也可以吧VOD的依赖引入到edu当中,但是这样就会有关联,就不是微服务
服务注册的几个步骤:
引入依赖,application.properties里面配置,启动类当中加入@EnableDiscoveryClient
微服务
什么是微服务
三个服务是用不同的端口启动,这就是微服务风格。
微服务是一种架构风格,把一个项目拆分成多个独立服务,每个服务独立运行在自己的进程当中,
微服务与单体架构区别
(1)单体架构所有的模块全都耦合在一块,代码量大,维护困难。
微服务每个模块就相当于一个单独的项目,代码量明显减少,遇到问题也相对来说比较好解决。
(2)单体架构所有的模块都共用一个数据库,存储方式比较单一。
微服务每个模块都可以使用不同的存储方式(比如有的用redis,有的用mysql等),数据库也是单个模块对应自己的数据库。
(3)单体架构所有的模块开发所使用的技术一样。
微服务每个模块都可以使用不同的开发技术,开发模式更灵活。
什么样的项目适合微服务
什么是Spring Cloud
Spring Cloud是一系列框架的集合。它利用Spring Boot的开发便利性简化了分布式系统基础设施的开发。
springcloud相关组件
服务发现——Netflix Eureka (Nacos)
服务调用——Netflix Feign
熔断器——Netflix Hystrix 容错保护
服务网关——Spring Cloud GateWay
分布式配置——Spring Cloud Config (Nacos)
消息总线 —— Spring Cloud Bus (Nacos)
客户端负载均衡-Netflix Ribbon
nacos 注册中心 可以替换到springcloud的很多组件
可以做到服务发现,分布式配置,消息总线
服务注册
服务发现
常用注册中心:
-
Eureka(原生,2.0遇到性能瓶颈,停止维护)
-
Zookeeper(支持,专业的独立产品。例如:dubbo)
-
Consul(原生,GO语言开发)
-
Nacos
service-cms banner
crm-banner数据库的表
热门课程 名师显示
可以根据id(最新课程),也可以根据浏览数量
redis缓存(这里用途是banner)
一般首页访问量比较大,可以把首页数据放到redis缓存里面。
一般把经常查询、不经常修改、不是特别重要的数据放到redis里面
Redis两个重要插件:redisTemplate 对缓存的操作, CacheManager针对缓存的管理,设置数据过期时间
service-msm(day12登录注册功能)
service-ucenter
登录业务介绍
Token模式
业务流程图{用户访问业务时,必须登录的流程}
优点:
无状态: token无状态,session有状态的
基于标准化: 你的API可以采用标准化的 JSON Web Token (JWT)
缺点:
占用带宽
无法在服务器端销毁
注:基于微服务开发,选择token的形式相对较多,因此我使用token作为用户认证的标准
单点登录的三种方式(SSO)
在任何一个模块登录后,其他模块不在需要登录
1、session广播机制
session的默认过期时间 30min
可以做到,致命缺点:如果有几十个模块,就很浪费资源,是早期的方式
2、使用cookie+redis实现
cookie是客户端技术,存到浏览器里面。
通过redis设置过期时间可以做到跟session一样。
3、使用token方式(token就是令牌机制。自包含令牌)
token就是按照一定规则生成的字符串,这个字符串可以包含用户信息。
token在生成字符串的时候可以设置过期时间。
1.把字符串返回,字符串返回有两种方式:
1、cookie
2、在地址栏中访问
如果获取到,就是登录。
什么是JWT
Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。
JWT令牌机制
令牌机制就是上面的token,刚刚说了,按照一定规则生成的字符串,规则可以自己去订,但是一般采用官方通用的方式,就是JWT令牌。
字符串通过.分成了三个子串。
头信息:
{
"alg": "HS256",
"typ": "JWT"
}
JWT头部分是一个描述JWT元数据的JSON对象,通常如下所示。
有效载荷
有效载荷部分,是JWT的主体内容部分,也是一个JSON对象,包含需要传递的数据。 JWT指定七个默认字段供选择。
iss:发行人
exp:到期时间
sub:主题
除以上默认字段外,我们还可以自定义私有字段,如下例:
{
"sub": "1234567890",
"name": "Helen",
"admin": true
}
请注意,默认情况下JWT是未加密的,任何人都可以解读其内容,因此不要构建隐私信息字段,存放保密信息,以防止信息泄露。
JSON对象也使用Base64 URL算法转换为字符串保存。
签名哈希(防伪标志)
签名哈希部分是对上面两部分数据签名,通过指定的算法生成哈希,以确保数据不会被篡改。
首先,需要指定一个密码(secret)。该密码仅仅为保存在服务器中,并且不能向用户公开。然后,使用标头中指定的签名算法(默认情况下为HMAC SHA256)根据以下公式生成签名。
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(claims), secret)
在计算出签名哈希后,JWT头,有效载荷和签名哈希的三个部分组合成一个字符串,每个部分用"."分隔,就构成整个JWT对象。
JWT的用法
客户端接收服务器返回的JWT,将其存储在Cookie或localStorage中。
此后,客户端将在与服务器交互中都会带JWT。如果将它存储在Cookie中,就可以自动发送,但是不会跨域,因此一般是将它放入HTTP请求的Header Authorization字段中。当跨域时,也可以将JWT被放置于POST请求的数据主体中。
JWT问题和趋势 有点复杂
https://zhuanlan.zhihu.com/p/329848235
https://learnku.com/articles/17883?order_by=vote_count&
JWT默认不加密,但可以加密。生成原始令牌后,可以再次对其进行加密。
当JWT未加密时,一些私密数据无法通过JWT传输。
JWT的最大缺点是服务器不保存会话状态,所以在使用期间不可能取消令牌或更改令牌的权限。因此token加密前的对象不应该包含敏感信息,一旦信息泄露,任何人都可以获得令牌的所有权限。为了减少盗用,JWT的有效期不宜设置太长。对于某些重要操作,用户在使用时应该每次都进行进行身份验证。
为了减少盗用和窃取,JWT不建议使用HTTP协议来传输代码,而是使用加密的HTTPS协议进行传输。
service-msm短信业务 用到了redis, 没有数据库
redis:验证码几分钟有效。
短信发送成功后,把验证码存储到redis里面,并设置有效时间,用的时候,先从redis里面取,取到就用,取不到就重新发送短信。
这里redis不是用来缓存,而是用来设置失效时间。
service-ucenter用户中心
用户表
ucenter
登录流程
检测用户是否存在时,要把获取的密码值用MD5加密后再去跟数据库中密码去对比。
用户登录成功后,生成一个token值,返回。
注册功能
疑问点
中间有一步查询手机号是否重复,索引怎么设置
如果我们程序员在开发的时候没有设置这个加密,能不能直接取出这个密码
登录前端部分:
登录成功后,调到首页,然后显示用户信息。
这个拦截器是前端的,第三步,把cookie里面的token字符串放到header请求头里面,(因为后端是从token也就是header获取的,也可以通过cookie(cookie不能跨域),但是一般时通过header获取)保证接口可以调到。
微信扫描登录
OAuth2解决的问题
主要解决两个问题
1、开放系统间授权
2、分布式访问(就是上面说的微服务)
流程
1、生成二维码流程,通过往微信地址里面传递参数,再重定向到那个地址,就可以生成二维码
可以看下官方文档:
https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html
# 微信开放平台 appid
wx.open.app_id=你的appid
# 微信开放平台 appsecret
wx.open.app_secret=你的appsecret
# 微信开放平台 重定向url
wx.open.redirect_url=http://你的服务器名称/api/ucenter/wx/callback
2、扫描二维码后的流程。
callback
@GetMapping("callback")
public String callback(String code, String state, HttpSession session) {
//得到授权临时票据code
System.out.println("code = " + code);
System.out.println("state = " + state);
}
整合阿里云视频播放
1、根据地址播放:只能播放不加密的视频
2、根据播放凭证播放,加不加密都可以播放,而且播放凭证有过期时间。
#不同的服务器,地址不同
aliyun.oss.file.endpoint=your endpoint
aliyun.oss.file.keyid=your accessKeyId
aliyun.oss.file.keysecret=your accessKeySecret
#bucket可以在控制台创建,也可以使用java代码创建
aliyun.oss.file.bucketname=guli-file
获取文件流信息:
service-order 课程支付模块
数据库的表格
t_order, t_Pay_Log
生成订单
生成微信二维码 跟前面不一样
前面登录时请求一个地址直接生成一个二维码
而这里请求一个地址只会生成一个地址,还需要下载一个vue的组件
1、根据订单号查询订单信息
2、使用map设置生成二维码需要参数
3、发送httpclient请求,传递参数xml格式,微信支付提供固定地址(https://api.mch.weixin.qq.com/pay/unifiedorder)
4、得到返回请求,将xml转化为map,将返回二维码操作状态码,二维码地址放进map
5、返回map
查询订单状态
如果支付成功,首先改变t_order里面的状态码,其次往t_pay_log加一条记录。
查询订单状态主要包括两步:
1、查询状态:这一步是固定的,因为要通过微信的接口去做。
封装参数,发送httpclient请求,设置参数(xml),秘钥,然后返回请求,转化成map,返回map
2、如果成功,更改状态码,其次加一条支付记录。
前端需要每隔3s调用接口根据订单号查询一次状态,成功就跳转。(支付成功后,要清楚定时器)
支付流程总结
记住:在这里,查询订单状态是在order里面的模块,但是在edu里面曾经有一个查询课程详情的模块,在这里还需要在edu远程调用Oder里面判断是否支付过。因为显示也不一样。
可以编个问题
如果用户打开二维码,但是一直不支付,怎么解决?
可以设置一个字段,每执行一次定时器,字段自增,超多一定程度,清空二维码和定时器。
编问题
HTTP协议有一个缺陷,通信只能由客户端发起。
这里当时采用的是推送技术,都是轮询,每隔几秒钟,由浏览器向服务器发出HTTP请求,由浏览器返回最新的数据给客户端的浏览器,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
可以使用websocket去解决,WebSocket 是独立的、创建在 TCP 上的协议。进行全双工通信的协议。
WebSocket的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
(1)建立在 TCP 协议之上,服务器端的实现比较容易。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
gateway网关
作用
客户端 服务端之间的一面墙,可以起到很多作用,比如请求转发,负载均衡,权限控制。
负载均衡流程
service-acl
springsecurity
主要包括两部分:用户认证和用户授权
(1)用户认证指的是:就是用户登录
(2)用户授权指的是验证某个用户是否有权限执行某个操作。管理员、普通用户
Spring Security其实就是用filter,多请求的路径进行过滤。
(1)如果是基于Session,那么Spring-security会对cookie里的sessionid进行解析,找到服务器存储的sesion信息,然后判断当前用户是否符合请求的要求。
(2)如果是token,则是解析出token,然后将当前请求加入到Spring-security管理的权限信息中去
2、认证与授权实现思路
如果系统的模块众多,每个模块都需要就行授权与认证,所以我们选择基于token的形式进行授权与认证,用户根据用户名密码认证成功,然后获取当前用户角色的一系列权限值,并以用户名为key,权限列表为value的形式存入redis缓存中,根据用户名相关信息生成token返回,浏览器将token记录到cookie中,每次调用api接口都默认将token携带到header请求头中,Spring-security解析header头获取token信息,解析token获取当前用户名,根据用户名就可以从redis中获取权限列表,这样Spring-security就能够判断当前请求是否有权限访问。
流程图如下:
springsecurity代码执行过程:
nacos再学习(使用nacos代替了springcloud的config)
配置中心可以做什么 服务注册, 服务调用是feign
简单来说,就是如果集群的所有机器都改配置文件,这样很麻烦,所以让集群每个机器去读配置中心的文件。
springboot 配置文件加载顺序
项目的几种开发环境
dev:开发环境
test:测试环境
prod:生产环境
实验室项目:
总体概述
随着新能源资源的接入,不确定性性,火电厂的减少,调频资源不足,仅仅靠发电侧调频不可以,还要靠负荷侧资源。
DDR资源:空调,电厂,储能,电动汽车。
不同类型资源调频特性不同,如果不去协调就会影响资源的调控效率。
目标:研究不同类型资源的调频特性,聚合调频特性,协同控制,发用电协调,性能指标体系。
对于电厂,储能电站,单体容量大,
商民负荷,单体容量小。建模后,还有用聚合算法对分散资源进行整合。
总体框架
特性分析实现:
各类型资源调频特性研究
空调
建立空调的一阶电路模型,通过建立室内温度和功率的微分方程,得到空调的最大的调控容量和调频 时长。
工业负荷调频特性(电解铝)
通过改变电压,得到电解铝的功率容量,维持时间。
电动汽车:
通过储能电池的SOC模型,得到电动汽车的调节深度和持续时长
聚合
构建了不同外部影响因素对响应资源响应能力的影响模型。
每台空调的参数和初始状态具有随机性,但是有一定的概率分布关系。
通过蒙特卡洛概率模型,抽样,建立估计量。得到一定数量的空调的聚合调频特性,就是时间跟功率关系,可以理解为一个空调集群,知道他的规模,室外温度,室内温度设置区间,P,R(空调的电路模型参数),这些概率分布,这些空调能提供的功率量为。。MW,维持时间多长。
基于生成对抗网络的需求响应小样本集的扩展方法
概念
**为了构建了不同外部影响因素(政策激励性措施,外部环境)对负荷侧资源响应能力的模型,后面要采用数据挖掘或者深度学习的方法,但是这些方法是需要大量的样本数据做支撑。**但实际能够体现动态响应特性的样本量非常少,寻找合适的小样本集扩展方法十分必要。
生成器对抗网络,生成器负责学习真实样本的分布特征,并生成与真实样本分布特征高度相似的新样本。
过程
生成对抗网络由生成器G和判别器D两部分构成,二者均为神经网络模型。
生成器负责学习真实样本的分布特征,并生成与真实样本分布特征高度相似的新样本。判别器相当于一个二分类器,用于判断输入数据是来自真实样本是生成器输出的新样本,输出结果越大,代表输入数据来自真实样本的概率越大。 因此,生成器和判别器之间形成了博弈关系,只有当生成器输出样本的分布特征与真实样本高度相似时,才能“欺骗”判别器,使判别器无法区分真实样本和生成器输出样本,此时博弈达到均衡,训练获得的生成器可用于小样本集扩展。
每一次训练迭代过程中,生成器和判别器的权重等参数交替更新。首先更新生成器参数,固定判别器的神经网络参数不变,将具有已知分布特征的样本输入生成器(一般采用高斯随机分布的样本),假设生成器产生的新样本符合真实样本分布特征,并将该样本输入判别器,将判别器的输出结果作为生成器损失,并基于此,更新生成器的神经网络参数。然后固定更新后的生成器参数不变,更新判别器参数,将更新后的生成器产生的新样本和真实样本混合后输入判别器中,根据判别器输出结果来更新判别器参数,提高其准确区别两种样本的能力。
动态需求响应资源的聚合调频特性研究
采用的蒙特卡洛方法,每台空调的参数和初始状态也是相互独立且具有随机性的,但其存在一定的概率分布关系
多类型资源协调
空调超离散模型
基于最优控制的多资源协调策略设计
一是确定最优的需求侧资源控制总量u(t) 的计算方法,二是确定多个需求侧资源的协调策略和每个资源的动作量Pddr 。
二次型方程
x是系统状态,u是控制的输入,下面的u*
LQR的求解办法,
通过聚合和协调的方式。
通过求解我可以确定控制资源的总量,第i个资源的动作量
u*是控制总量
为什么采用下面这么复杂的而不用上面的那种多目标优化问题
上面优化做法:建立一个目标方程,这个目标方程包括总量和经济性能两个角度,满足两个约束,总花费成本小于Nmax,总量小于集合里面的资源总和。然后用常规的粒子群算法去求过,但是会出现一些问题,
(1),如果参数α和β设置不当,导致求解速度很慢且所得解的质量特别差。基本蚁群算法计算量大,求解所需时间较长,满足不了控制需求。
蚁群算法收敛速度慢、易陷入局部最优。
当然也可以有一些解决方案,蚁群算法中α,β的选取往往是通过经验来取得的,而选取不当时会造成算法的性能大大降低,因此可以利用其他算法对蚁群系统参数α,β进行训练。
群算法出现过早收敛于非全局最优解以及时间过长的缺点,可以通过使用蚁群算法进行搜索,然后用其他算法对蚁群算法得到的有效路由路径,通过选择、交叉、变异等优化过程,产生性能更优的下一代群体。
基于优先级排序的聚合负荷协同控制方法
由状态感知、实时分析、科学决策和精准执行这4部分组成。
状态感知实现对单个需求响应资源执行的动作类型的实时认知,
实时分析用于修正时隙内的调控量以及确定调控类型,
科学决策确定参与调节的负荷个体,
精准执行生成参与调节的负荷个体的控制信号。
改编部分
1、通过最优控制策略确定需要的资源总量Pneed;通过系统的常数状态空间矩阵、系统的控制输入、系统的状态、控制总量的权重,建立二次型,这个二次型的含义包括经济和控制性能两个角度,通过求解二次型得到需要的调频资源总量Pneed。
2、结合下面的策略计算单体资源。首先确定是消纳还是消减,以消减为例,我对B集合里面的资源的控制宽度按照从小到大进行一个排序,然后找到一个能跟他互补的资源,找到以后,就相当于把这两个资源进行一个打包,放到集合里面,如果没有找到互补资源,就舍弃掉。此时的有效功率就变成了这两个资源的Pddri的最大值。
互补定义:(首先一个资源的有控制周期,控制宽度,要满足控制宽度相加大于控制周期最大值。)
具体过程
状态感知:通过云平台采集的各热水器实时数据,将任意时隙内单体资源的调度状态分为可消纳状态A(消耗能源)、可削减状态B和不可调度状态D。(以热水器为例)。
A:Tk + D < Tmax,意思就是还可以往上调节温度
B:Tk >Tmin,意思是只要设定值大于最低阈值即可。
实时分析:修正功能(需求响应期间根据需要响应的负荷量进行修正)
根据Pneed数值的±号,确定需求响应类型,是应该多消耗资源还是少消耗资源。
科学决策:根据云平台采集的实时温度和实时功率,结合状态感知和实时分析产生的结果,,设计科学决策,确定各个热水器个体制定选择规则。可以结合上面改变内容。
如果是消减状态,就把B里面的资源按照λ值按照顺序排列,形成一个队列,然后根据所需要的值选择前面n个资源。(其中λ是跟他的当前温度,设定温度,成本,调频时间有关系)
精确执行:生成控制信号发送