好的,我在星球的第一分笔记来了。不画饼。这是我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)
0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
下载 APP