2024-03-04
好的,我在星球的第一分笔记来了。不画饼。这是我oj后一部分的笔记前面的没记。实属是我的错。跪下了磕了。
数据库数据存储:
存json的前提:
你不需要根据某个字段去倒查这条数据
你的字段含义相关,属于同一类的值
你的字段存储空间占用不能太大
以上可以考虑存json数组或json对象
何为sql语句的索引??索引的作用是啥??(加索引一般是根据具体业务来加的)
=========分割线。项目微服务改造=
跑通项目流程
1.合并questionSubmitController代码到questionController中
2.由于后端修改了接口地址,前端需要重修生成接口调用代码(与后端无关前端的事)
单体项目改造为微服务
什么是微服务?
服务:提供某类功能的代码
微服务:专注于提供某类特定功能的代码,而不是把所有的代码全部放到同一个项目中。会把整个大的项目按照一个特定的功能,逻辑进行拆分,拆分为多个子模块,每个子模块独立运行,独立负责一类功能,子模块之间相互调用互不影响。
微服务实现技术?
Spring Cloud
Spring Cloud Alibaba(本项目使用)
Dubbo(DubboX)
RPC(GRPC、TRPC)
本质上是通过HTTP、或者其他网络协议进行通讯来实现的
微服务的几个重要实现因素:服务管理、服务调用、服务拆分
Spring Cloud Alibaba
推荐参考中文文档来学习:https://sca.aliyun.com/zh-cn/
本质是在原有的基础上,进行了增强。在阿里的原有的业务基础上。
Spring Cloud Alibaba 相关技术栈
Spring Cloud Gateway:网关
Nacos:服务注册和配置中心
Sentinel:熔断限流
Seata:分布式事务
RocketMQ:消息队列,削峰填谷
Docker:使用Docker进行容器化部署
Kubernetes:使用k8s进行容器化部署
注意选择对应的版本。https://sca.aliyun.com/zh-cn/docs/2022.0.0.0/overview/version-explain
此处选择2021.0.5.0
Nacos:集中存管项目中所有的服务信息,便于服务之间找到彼此;同时,还支持存储整个项目中的配置
微服务的请求流程:
改造前的思考
从业务需求出发,思考单机和分布式的区别。
用户登录功能:需要改造为分布式登录。
其他内容:
有没有用到单机锁?改为分布式锁(伙伴匹配系统讲过)
有没有用到本地缓存?改为分布式缓存(redis)
需不需要用到分布式事务?比如多个库的操作
改造分布式登录:
1)application.yml增加redis配置
# Redis 配置
# todo 需替换配置,然后取消注释
redis:
database: 1
host: localhost
port: 6379
timeout: 5000
password: 123456
2)补充依赖
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
3)主类取消Redis自动配置的移除(删除exclude = {RedisAutoConfiguration.class})
@SpringBootApplication(exclude = {RedisAutoConfiguration.class})
4) 修改session存储方式:
spring.session.store-type:redis
5) 使用redis-cli或者redis管理工具,查看是否有登录后的信息
微服务的划分
从业务出发,想一下哪些功能职责是一起的?
公共模块:
common 公共模块(yuoj-backend-common):全局异常处理器、请求响应封装类、公共的工具类等
model 模型模块(yuoj-backend-model):很多服务公用的实体类
公用接口模块 (yuoj-backend-service-client):只存放接口,不存放实现类(多个服务之间要共享),需要引入openfeign在创建子模块时。
依赖服务:
注册中心:Nacos
微服务网关:Gateway 聚合所有的接口,统一接收前端请求
业务功能:
用户模块 (yuoj-backend-userService:8101端口)
注册
登录
用户管理
题目模块(yuoj-backend-questionServicet:8102端口)
创建题目(管理v员)
删除题目(管理员)
修改题目(管理员)
搜索题目(用户)
在线做题 (题目详情页)
题目提交
判题模块((yuoj-backend-judgeServicet较重的操作:8103端口)
执行判题逻辑
错误处理(内存溢出、安全性、超时)
自主实现 代码沙箱(安全沙箱)
开放接口(提供一个独立的新服务)
路由划分
用spring boot的context-path统一修改各项目的接口前缀,比如:
用户服务:
/api/user
/api/user/inner(内部调用,网关层面要做限制)
题目服务:
/api/question
/api/question/inner(内部调用,网关层面要做限制)
判题服务:
/api/judge
/api/judge/inner(内部调用,网关层面要做限制)
Nacos注册中心启动
选择2.2.0版本
教程:
https://sca.aliyun.com/zh-cn/docs/2022.0.0.0/user-guide/nacos/quick-start
官网下载Nacos:https://github.com/alibaba/nacos/releases/tag/2.2.0
Nacos教程官网:
https://nacos.io/zh-cn/docs/quick-start.html
安装好后,进入bin目录:
startup.cmd -m standalone
新建工程
springbcloud 有相当多的依赖,不建议自己写,而是用脚手架创建项目:
https://start.aliyun.com/ 给项目增加全局依赖配置文件
依次使用new modules和spring boot Initializr创建各个模块
需要给各模块之间绑定子父依赖关系
父模块定义modules,子模块引入parent语法,可以通过继承父模块配置,统一项目的定义和版本号
同步代码和依赖
1)common公共模块:全局异常处理器、请求响应封装类、公共的工具类等
在外层的pom.xml中引入公共类
2)model模型模块:很多服务公用的实体类
直接复制model包,注意代码沙箱model的引入
3)公用接口模块:只存放接口不存放实现(多个服务之间共享)先无脑搬运所有的service,judgeService也要搬运
需要指定openfeign(客户端调用工具)的版本:
4)具体业务服务实现
给所有业务服务引入公共依赖
主类引入注解:
引入application.yml配置文件
服务内部调用
现在的问题是,题目服务依赖用户服务,但是代码已经分到不同的包,已经找不到啊对应的Bean。
可以使用Open Feign组件实现跨服务的远程调用。
Open Feign:Http调用客户端,提供了更方便的方式来让你远程调用其他的服务,不用关系服务的调用的地址。
Nacos:注册中心获取服务的调用地址
1)梳理服务的调用关系,确定哪些服务(接口)需要给内部调用。
用户服务:没有其他的依赖
题目服务:
判题服务:
实现client接口
注意,每个服务模块有各自的service接口,这里实现的client接口只是对其他模块来进行提供服务。
对于用户服务,有一些不利于远程调用参数、或者实现起来非常简单(工具类),可以直接默认方法,无需远程调用,节约性能。
开启open feign的支持,把我们的接口暴露出去(服务注册到注册中心上),最为API给其他服务调用(其他服务从注册中心寻找)
需修改每个服务提供者的contex-path全局请求路劲
服务提供者:理解为接口的实现类,实际提供服务的模块(服务注册到注册中心上)
服务消费者:理解为为接口的调用方,需要去找到服务提供者,然后调用(其他服务从注册中心寻找)
注意事项:
要给接口的每个方法打上请求注解,注意区分Get、Post
要给请求参数打上注解,比如是get请求就打上RequestParam、post请求就打上RequestBody
FeignClient定义的请求路径一定要和服务提供方实际的请求路径保持一致
注意path处有两种情况,1是带/api/user能够访问的服务。2是带/api/user/inner的服务
并不是什么只有带/api/user/inner才能访问。
4)修改各业务服务的调用代码为feignClient
5)编写feignClient服务的实现类,注意要和其他之前定义的客户端保持一致
6)开启Nacos配置,让服务器之间能够相互发现
所有模块引入Nacos依赖,然后给业务服务(包括网关)增加配置:
给业务服务项目启动类上打上注解,开启服务发现、找到对应的客户端Bean的位置:
全局引入负载均衡依赖器依赖:
7)启动项目,测试依赖能否注入,能否完成相互调用
微服务网关
微服务网关(yuoj-backend-gateway):Gateway聚合所有的接口,统一接受处理前端的请求
为什么要用?
所有的服务端口不同,增大了前端调用成本
所有服务是分散的,你可能需要集中管理、操作,比如集中处理跨域问题、鉴权、接口文档、服务的路由、接口文档的安全性、流量染色、限流....
Gateway:想自定义一些功能,需要对这个技术有比较深度理解
Gateway:是应用层网关,会有一定的业务逻辑(比如根据用户信息判断权限)
Nginx:是接入层的网关:比如每个接入请求的日志,通常没有业务逻辑
接口路由
统一接手前端的请求,转发请求到对应的服务
如何找到路由?可以编写一套路由配置,通过api地址前缀来找到对应的服务
注意这个配置是在gateway网关模块来配置的,图中的url为负载均衡地址。predicates是找到这个路由的匹配方式(函数本人的理解)。图中的路由配置的意思是通过predicates配置的来找的这个url又由于lb://xxx为负载均衡配置,所以会到Nacos注册中心中找到对应id匹配的服务模块。
gateway需要导入的依赖:
聚合文档
以一个全局的视角集中查看管理接口文档
使用Knife4j接口文档生成器:
https://doc.xiaominfo.com/docs/middleware-sources/spring-cloud-gateway/spring-gateway-introduction
1)先给所有业务服务引入依赖,同时开启接口文档的配置
https://doc.xiaominfo.com/docs/middleware-sources/spring-cloud-gateway/spring-gateway-introduction#手动配置聚合manual
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-gateway-spring-boot-starter</artifactId>
<version>4.4.0</version>
</dependency>
Knife4j:
enable: true
2)给网关配置集中管理文档接口
网关项目引入依赖:
引入配置:
3)访问地址即可查看聚合接口文档:
http://localhost:8101/doc.html#/home
(注意上述地址是鱼皮哥的文档接口地址,也是配置在gateway模块中的端口(8801)改下端口号就行了)
分布式Sesson登录(这里还需要去查资料有点不明白)
必须引入spring data redis依赖
解决Cookie跨域问题:
server:
address: 0.0.0.0
port: 8104
servlet:
context-path: /api/judge
#cookie 30天过期
session:
cookie:
max-age: 292000
# (这里是重点)
path: /api
跨域解决:
全局跨域配置:
、
权限校验
可以使用Spring Cloud Gateway的Filter请求拦截,接受到请求后根据请求的路径判断能否访问。
这是来自通过一个拦截器类的方法
扩展:可以在网关实现Sentinel接口实现限流降级,参考教程:
https://sca.aliyun.com/zh-cn/docs/2021.0.5.0/user-guide/sentinel/overview/
扩展:可以使用JWT Token实现用户登录,在网关层面通过toke获取登录信息,实现鉴权
Redisson RateLimiter也可以实现限流,智能BI讲过。
思考
真的有必要使用微服务吗?
真的有必要使用Spring Cloud实现微服务吗?
企业内部一般使用API(RPC、HTTP)实现跨部门、跨服务的调用,数据格式和调用代码全部自动生成,保持统一,同时解耦。
消息队列解耦
这部分等做完BI再回过头来看(函数暂时还没学过mq)
12
0
分享
操作
评论
问答助学
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
