API 开放平台项目(已整理,已废弃)
项目大纲
前端
- React 18
- Ant Design Pro 5.x 脚手架
- Ant Design & Procomponents 组件库
- Umi 4 前端框架
- OpenAPI 前端代码生成
后端
- Java Spring Boot
- MySQL 数据库
- MyBatis-Plus 及 MyBatis X 自动生成
- API 签名认证(Http 调用)
- Spring Boot Starter(SDK 开发)
- Dubbo 分布式(RPC、Nacos)
- Swagger + Knife4j 接口文档生成
- Spring Cloud Gateway 微服务网关
- Hutool、Apache Common Utils、Gson 等工具库
- 项目介绍和计划
- 需求分析
- 业务流程和子系统介绍
- 技术选型(各技术作用讲解)
- 前后端项目初始化
- 前端 Ant Design Pro 框架最新版本教程
- 后端 Spring Boot 万用模板使用
- 数据库表设计
- 前后端代码自动生成(强烈推荐,大幅提高开发效率!)
- 登录页开发
- 接口管理功能开发(Ant Design 高级组件使用)
- 模拟 API 接口项目开发
- HTTP 接口调用
- API 签名认证详解及开发
- 客户端 SDK 开发(Spring Boot Starter)
- 管理员接口发布 / 下线功能开发
- 接口列表页开发
- 在线调试接口功能开发
- 接口调用统计开发
- 后端开发
- 优化方案分析及对比
- API 网关详解
- 网关介绍及优点
- 10 种网关应用场景
- 网关分类及技术选型
- Spring Cloud Gateway 网关实现
- 详细带读官方文档
- 统一业务处理:用户鉴权及接口调用次数统计
- 项目分布式改造
- 公共模块抽象
- RPC 和 HTTP 调用详解及对比
- Dubbo 框架讲解及示例项目开发
- Dubbo 业务实战
- 管理员统计分析功能
- 前端 2 种可视化库的使用
- 后端聚合查询接口开发
- 项目扩展点及上线分析
一、初始化前后端框架
项目前端初始化---脚手架安装
直接使用开始使用 - Ant Design Pro,按照他的步骤安装即可。
1、安装库(电脑安装一次即可)
(base) wangjia@wangbangjia ~ % sudo npm i @ant-design/pro-cli -g
2、在指定目录创建项目框架
(base) wangjia@wangbangjia 星球项目 % pro create yuapi-frontend
? 🐂 使用 umi@4 还是 umi@3 ? umi@4
🧎🏻全量区块暂时不支持 umi@4
3、安装依赖:yarn install安装package.json对应的依赖-----node_modules时,一定要在项目根目录!!!!
即可得到前端框架了
注意版本号控制
切换nodeMac下的nodeJs版本切换和升级_mac npm版本切换_-HaiXin的博客-CSDN博客
yarn版本控制yarn卸载与版本降级升级_yarn降级_votaries的博客-CSDN博客
注意还要使用yarn安装所有的依赖--缺少啥依赖就会报错--再安装也行
直接敲 yarn 安装依赖
这个依赖还是很重要的!
sudo yarn add eslint-plugin-unicorn --dev
前端与后台服务交互
大致流程:
1.UI 组件交互操作;
2.调用 model 的 effect;
3.调用统一管理的 service 请求函数;
4.使用封装的 request.js 发送请求;
5.获取服务端返回;
6.然后调用 reducer 改变 state;
7.更新 model。
2、项目后端初始化--
使用springboot-init框架就好了。
启动之前要application.yml配置Redis、数据库的连接信息。之后MySQL连接IDEA,
二、正式业务
- 第一期 -- 初始化和展示
- 项目设计、技术选型
- 基础项目的搭建
- 接口管理
- 用户查看接口
1、数据库表设计
--- 建立接口信息表
使用http://sqlfather.yupi.icu/ 根据字段生成sql语句
*后端生成SQL表的 CRUD
---MybatisX-generator
MyBatisX Generator 可以根据数据库表结构信息快速生成与数据库交互所需的
实体类、Mapper 接口、XML 映射文件等代码
第三幅图本地还会有module也要勾选
最终生成的generator目录结构
将每个文件粘贴复制到对应的目录中 删掉generator即可
后端增删改查 -- 调用现有代码完成。
*前端生成后端接口CRUD
前端:实现登录功能 + 接口信息增删改查
怎么让前端调用后台的接口,去实现接口信息的增删改查管理?
前端接口调用:oneapi插件自动生成 -- 使用openapi规范
已经有了后端,想要前端直接生成调用后端的代码,只需要将后端基于openapi的文档提供给前端即可
获取后端openapi的JSON文档:后端主页的分组URL连在ip:port/工程名/后面即可
例如后端主页地址http://localhost:7529/api/doc.html#/home
查看到分组URL为/v3/api-docs 所以
最终后端基于openapi的文档地址为http://localhost:7529/api/v3/api-docs
将config/config.ts中openAPI 对应的path改为http://localhost:7529/api/v3/api-docs并设置项目名
然后package.json运行openapi即可生成前端增删改查 调用后端的接口 在service/yuapi-backend中6个文件
看不懂,先熟悉一下。
然后跟着做完成测试。
测试:使用真实的后端接口,就要使用dev方式运行。
用户中心项目copy以下注册页面代码
成功使用后端数据生成接口信息,让前端调用 以用户身份登录成功。
第一节即将结束。先步道乐跑打卡吃饭,最近一段时间,又开始起飞。
** 问题解决
为啥刷新页面,就需要重新登陆?
--- 1、前端没有种上Cookie
---2、前端发请求没有带上Cookie
在requestConfig.ts 发送请求配置中添加withCredentials: true
(用于指定跨域请求时是否发送身份凭证(如 cookies、HTTP 认证等))
权限管理:
只有管理员可以操作的接口信息管理
service/access.ts为权限管理判断
还可以直接对数据库操作,设置其userRole 是user还是admin
管理员页面填充接口信息
TableList的index.ts的columns变量中改为自己需要展示的列,然后修改request的方法
无登录2;39;40
由于之前没有刚开始就删除国际化配置,之后再执行的,导致出现故障,现在登录界面无法加载,也就是权限校验没法执行,技术解决不了,趁着还没有进行太多,直接重新,从头来过。
- 第二期 -- 接口调用
- 继续开发接口管理前端页面
- 开发模拟api接口
- 开发调用这个接口的代码
- 保证调用的安全性 (api签名认证)
- 客户端SDK开发
- 管理员接口 发布 与调用
- 接口文档展示、接口在线调用
注意:Ant-design Pro给出的框架,什么增删改查就是个模板,根本上还是要自己调用,或者进行修改。
1、完成了第二期接口管理前端页面 -- pages/InterfaceInfo
对于表单的处理,最重要的就是定义好columns,其余要考虑的就是调用组件完成添加、删除、修改即可。
2、开发模拟API接口 -- yuapi-interface
也就是写一个能发送请求并响应的springboot小项目
3、调用接口
几种http调用方式
HttpClient、RestTemplate、第三方库(Hutool,OKHTTP)
使用Hutool
4、API签名认证
本质: 1、签发签名 2、使用签名(校验签名)
Cookie是第一次使用要权限校验,之后会保存在浏览器中,每次发请求登录就会将用户信息加在请求报文中,实现“无校验登录”
但是由于调用API用户资格无法得知,每一次调用API都要进行一次权限认证。
通过Http request Header传递参数
参数1、accessKey:调用的表示 userA、userB
参数2、secretKey:秘钥 --- 该参数不放到请求头中传递,用于生成签名
类似用户名和密码(区别:ak、sk无状态的)
不可将秘钥直接在服务器间传递,有可能被拦截。
加密方式:对称加密、非对称加密、MD5签名(不可解密)
参数3、用户请求参数
MD5加密:
参数4、sign参数
用户参数 + 秘钥 => 签名生成算法得到值(不可解密) (比如:yupi + abcdefgh = diaehufishroser)
服务器校验方法:
服务器用相同的参数和算法来生成签名,再与用户传的进行校验。
怎么放重放? (例如配置了代理,代理拦截获取签名,直接重放后发送)
参数5、加nonce随机数,只能用一次(服务端要保存已使用过的随机数)
参数6、加timestamp时间戳,检验时间戳是否过期
现在正在做的就是 按照6个参数 完成API签名认证 (客户端制作签名、服务端认证签名)
客户端咋做? :根据参数 + 加密算法 ==》 生成签名 在发送请求时,将签名放在请求头中。
使用Hutool工具发送http请求,获取相应数据、打印。
服务端咋做? :根据发送请求的URL映射到具体的API(方法),完成签名校验,返回响应数据。
API签名认证很灵活,采用什么签名算法只是一个选择问题。最重要的就是选择哪些参数用来生成最终的API签名要根据具体场景来选择。(比如userId、appid、固定值等)
思考:难道开发者每次调用接口都要写一遍签名算法?
开发一个简单易用的SDK
理想情况:开发者只需要关注调用哪些接口,传递什么参数,就像调用自己的代码一样。
开发starter好处:开发者引入之后,可以在applocation.yml中写配置,自动创建客户端。
spring-boot-configuration-processor作用是自动生成配置的代码提示
建立加分项 --- 写starter:
首先就是确定包含那些依赖;其次在Resources中写文件夹META-INF的spring.factories中指定配置的注册类xxxClientConfig,在注册类中通过注解@ConfigurationProperties("yuapi.client")读取到配置类信息
使用sdk,咋就创建bean失败了,改了好久,最基本的spring创建bean到地了。先不改了,之后还会有延伸,到时再改
第三期
- 开发接口发布/下线的功能(管理员)
- 前端去浏览接口、查看接口文档、申请签名(注册)
- 在线调试(用户)
- 统计用户调用接口的次数
- 优化系统-API网关
1、开发接口发布/下线的功能(管理员)
发布接口(仅管理员): 1、校验该接口是否存在 2、判断该接口是否可调用 3、修改接口数据库中的状态字段为1
todo 判断该接口是否可以调用时 由固定方法名 改为 根据测试地址来调用
下线接口(仅管理员): 1、校验该接口是否存在 2、修改接口数据库中的状态字段为0
在controller层 写发布与下线接口
controller 层写上线,下线接口就还可以,但是引入YuApiClient就不行了,显示是无法生产bean,刚写的是没问题的,直接用yupi的也是出现这个问题,继续找找吧,肯定是个小问题,找不到,就继续看视频,晚上再找。
依然还是没有找到,只用不用注入的bean就行,这个问题很奇怪,我在注入的时候,都还有提示,自动导入jdk,也都不报错,但是要用到实例的bean就报错了。
晚上准备API签名认证 API网关的代码讲解录制发布到B站上
一来是再次梳理一遍、二来就是以便后来项目复习快速回忆
刚刚在InterfaceInfoController中补充写了接口的操作函数--后端发布 & 下线的接口,但是前端仅仅是显示,咋进行调用?
前端不用写任何关于接口调用的方法,直接使用openapi生成
后端改了,想要前端进行调用,直接使用openapi生成一下
1、做了主页展示接口并实现调用 --- pages/Index 加载展示接口列表(√)
2、查看文档接口页面 --- pages/InterfaceInfo中展示 单个接口信息(√)
3、实现用户注册时生成签名 在UserServiceImpl在插入数据前 生成ak、sk 然后插入。(√)
由于后端初始化项目User内没有ak、sk字段,还要在实体以及对应的mapper中添加字段
现在出现的最大的问题就是 使用openapi根据后端代码自动生成前端调用后端的接口 生成的不全!!到底是后端缺少了啥,还是openapi生成出现了问题?
不是少一俩个函数,实体也都少了,不解决没法进行。有些函数之前写也还有啊,怎么就没了?
标准json数据格式:
[
{
"name": "username", "type": "string"
}
]
注意调用逻辑:前端 -> 后端 -> 接口服务
然后 接口服务 -> 后端 -> 前端
第四期
1、开发接口调用次数的统计 2、优化整个系统的架构(API网关)网关是啥?啥作用?应用场景及实现?结合业务去应用网关。
todo 调用接口测试失败,显示是json格式不匹配 下午解决---原来是自己id赋值没有把对象中的id数值取出来,导致直接把对象赋值给了id。
1、用户接口信息表 建表,使用MybatisX-Generator生成对应的三层代码文件,分别移动后,并对dao层实体-mapper、Service层方法、controller层增删改查 所有代码基本处理(√)
2、
统计每个接口的调用次数,是针对每个接口都写一下统计的方法?大量重复工作! 使用AOP优点:独立于接口,在每个接口调用之后统计次数+1 缺点:只存在于单个项目中,如果每个团队都要开发自己的模拟接口,那么都要写一个切面,仍然大量重复工作。终极解决方案:网关文档:Spring Cloud Gateway 中文文档
*API网关:
关键点:根据断言的路由及局部的过滤器yml配置;全局过滤器鉴权、签名认证、调用次数校验及+1等功能实现。
定义 :API网关是一种集成了配置发布、环境管理、接入认证,用户鉴权、访问控制等功能的 API管理和服务治理的工具。
使用API网关托管API,即可高效,安全、低成本的管理服务。API网关作为请求的单一入口点,将请求分配给相应的服务,然后收集结果并将其传递给请求者。而不是让客户单独请求访问每项微服务。
- 核心功能:路由、鉴权
- 管理上处理:负载均衡、跨域、业务处理、访问控制、发布控制、流量染色、接口保护
- 日志上处理:监控日志、报表
路由:起到转发的作用。比如有接口A和接口B,网关会记录这些信息,根据用户访问的地址和参数,转发请求到对应的接口。(服务器/集群)/a -> 接口A/b -> 接口B 负载均衡:路由的基础上/c -> 服务A / 集群A(随机转发到其中的某一个机器) 统一鉴权:判断用户是否具有权限进行操作。无论访问什么接口,都统一去判断权限,不用重复写。 统一处理跨域:网关统一处理跨域,不在每个项目单独处理 统一业务处理:把一些每个项目中都要做的通用的逻辑放到上层(网关),统一处理,比如本项目的次数统计 访问控制:黑白名单,比如限制DDOS ip 发布控制:灰度发布,比如上线新接口,先给新接口分配20%流量,老接口80%,再慢慢调整比重 流量染色:给请求(流量)添加一些标识,一般是设置请求头中,添加新的请求头统一接口保护:限制请求、信息脱敏、降级(熔断)、限流、超时时间统一日志:统一的请求、相应信息记录 统一文档:将下游项目的文档进行整合,在一个页面统一查看网关的分类:全局网关(接入层网关):作用是负载均衡业务网关(微服务网关):会有一些业务逻辑,作用是将请求转发到不同的业务、项目、接口、服务。实现1、Nginx(全局网关)、Kong网关(API网关)编程成本高2、Spring Cloud Gateway 性能高、可以用java代码写逻辑
建议开启日志 logging:level:org:springframework:cloud:gateway: trace
核心概念路由:根据什么条件断言:一组规则、条件,用来确定如何转发路由过滤器:对请求进行一系列的处理,比如添加请求头、添加请求参数请求流程:1、客户端发起请求2、Handle Mapping:根据断言,去将请求转发到对应的路由3、Web Handle:处理请求(一层层经过过滤器)4、实际调用服务俩种配置方式1、配置式(方便、规范)2、编程式(灵活)断言(作用:根据断言转发路由)1、After在XX时间之后2、Before在XX时间之前3、Between在XX时间之间4、请求类别5、请求头(包含Cookie)6、权重7、查询参数8、客户端地址过滤器(基本功能:对请求头、请求参数、响应头的增删改查)1、添加请求头2、添加请求参数3、添加响应头4、降级(设置备份地址)
鱼皮经验:
基础核心知识掌握了,其他的应用类的知识,晓得是什么,应用场景就行了,不会就直接查文档。
第五期1、实现统一的用户鉴权、统一的接口调用次数统计(把API网关应用到项目中)2、完善功能
业务逻辑
1、用户发送请求到API网关2、请求日志3、(黑白名单)4、用户鉴权(判断ak、sk是否合法)5、请求的模拟接口是否存在6、请求转发,调用模拟接口7、响应日志8、调用成功,接口调用次数 + 19、调用失败,返回一个规范的错误码
* 具体实现
* 1、请求转发
* 使用前缀匹配断言:所有路径为/api/**的请求进行转发,转发到http://localhost:8123/api/**
* 比如请求网关:http://localhost:8090/api/name/get?name=yupi
* 转发到: http://localhost:8123/api/name/get?name=yupi
* spring:
* cloud:
* gateway:
* routes:
* - id: yuapi_route
* uri: http://localhost:8123
* predicates:
* - Path=/api/** 现在是分布式项目,但是没有引入微服务,微服务啥子?
*签名认证ak-sk:
本质:1、签发签名 2、校验签名
关键点:生成签名工具
后台生成签名工具 & 网关重新生成进行比对校验
ak-sk 机制基础:
1、ak-sk 由用户注册时提供的用户名产生,并作为用户信息的一部分存储在用户信息表中;
2、accessKey被视为公钥,用于标识用户的身份;secretKey 则被视为私钥,用于加密签名;
accessKey是身份标识,根据请求者accessKey在数据库中拿到对应的有资格用户User,并拿到对应的secretKey,和请求者的body现场生成serverSign请求者在发送请求时就会调用签名生成工具生成签名sign,存储在请求头中,拿出来。将sign与serverSign对比。
ak-sk机制:请求者根据ak-sk已经生成了签名sign(请求体+秘钥),在发送请求时,将ak和sign一起放在请求头中,API网关拿到请求头中的ak与sign,根据ak去数据库确定是哪个用户,拿到对应的sk,重新现场生成serverSign,再完成签名校验。
后台签名工具
存储生成密钥参数的hashmap
// 存储秘钥,放在请求头中private Map<String,String> getHeaderMap(String body){Map<String, String> hashMap = new HashMap<>();hashMap.put("accessKey",accessKey); // 秘钥一定不能发送给后端hashMap.put("nonce", RandomUtil.randomNumbers(4));hashMap.put("body",body);hashMap.put("timestamp",String.valueOf(System.currentTimeMillis() / 1000));//使用签名工具生成 签名hashMap.put("sign",genSign(body,secretKey));return hashMap;}
生成签名工具:
public class SignUtils {public static String genSign(String body, String secretKey){// 创建 SHA256算法 的消息摘要器Digester md5 = new Digester(DigestAlgorithm.SHA256);// 将请求体和密钥拼接起来以生成待签名的内容String content = body + "." + secretKey;// 使用消息摘要器计算内容的哈希值,并以十六进制形式返回return md5.digestHex(content);} }
将签名封装到请求头中完成发送请求
public String getUserNameByPost(User user){String json = JSONUtil.toJsonStr(user);HttpResponse httpResponse = HttpRequest.post("http://localhost:8123/api/name/user/").addHeaders(getHeaderMap(json)).body(json).execute();System.out.println(httpResponse.getStatus());String result = httpResponse.body();System.out.println(result);return result;} }
API网关用户鉴权
1、获取请求头中的accessKeyHttpHeaders headers = request.getHeaders();String accessKey = headers.getFirst("accessKey"); 2、根据accessKey获取到对应的调用者User invokeUser = innerUserService.getInvokeUser(accessKey); 3、获取到接口调用者的secretKey String secretKey = invokeUser.getAccessKey(); 4、根据body内参数与secretKey生成服务端的签名String serverSign = SignUtils.genSign(body,secretKey); 5、将服务端现场生成的签名和请求头中的签名进行对比if(sign == null || !sign.equals(serverSign)){ return handleNoAuth(response); }
现在是API网关内部的签名认证错误!!!就是sign与serversign不同!!!真是出鬼了!!!到底是哪里出了问题??? --原来是写错了,手欠,排查了好久.
*项目架构 --调用接口流程:
- 平台管理员
- 上线接口:管理员可以将开发完成的接口上线,使其可供接口使用者调用。
- 下线接口:管理员可以将某个接口下线,即停止该接口的调用。
- 管理接口:
- 增:管理员可以添加新的接口到平台,包括接口名称、接口描述、接口URL等信息。
- 删:管理员可以删除平台上的某个接口。
- 改:管理员可以修改接口的信息,如接口名称、接口描述、接口URL等。
- 查:管理员可以查看平台上所有接口的信息,包括接口名称、接口描述、接口URL等。
- 发布接口:管理员可以发布开发完成的接口,以供接口使用者调用。
- 测试接口:管理员可以对接口进行测试,以确保其功能的正确性和稳定性。
- 接口使用者
- 浏览接口:使用者可以浏览平台上的所有接口,包括接口名称、接口描述、接口URL等信息。
- 开通接口:使用者可以开通某个接口,使其可供自己调用。
- 调用接口:使用者可以通过接口URL调用已开通的接口,向其发送请求并获取响应。
信息管理请求
接口调用请求
调用接口流程:
1、前端发送请求:在InterfaceInfo下(也就是接口详细信息)首先是点击《调用》按钮触发点击提交事件,本质上就是提交表单,所以在onfinish函数提交表单,调用invokeInterfaceInfoUsingPOST
函数发送请求(这个是根据后端invokeInterfaceInfo函数使用openapi生成)到
后端/api/interfaceInfo/invoke 。
2、后端接收请求:在controller层接收到,对请求的接口进行基本的有无/合理判断,获取当前登录用户的ak、sk,并根据yuapi-client-sdk封装好的客户端,根据登录用户的ak、sk进行
向模拟接口yuapi-interface发送请求
3、在yuapi-interface内根据ak、sk进行权限等鉴定,最后返回结果。
现在问题是:
前端发送到的地址是/api/interfaceInfo/invoke(后端backend)、但是会被API网关拦截,
目的路由是http://localhost:8123/api/name/user,后端backend也是会调用hutool发送http请求到模拟接口,,所以调用过程到底是谁调的?
--- 点击按钮请求的是前端页面,页面显示的端口是前端端口。请求到了前端之后,前端在逻辑处理里面调用后端,如果接入了网关,前端调用后端的端口应该是网关端口,从网关的策略中转发到对应的后端端口
五个模块:API网关-Web系统-模拟接口、公共模块、客户端SDK。
第六期
1、在API网关项目中,没有Mybatis,在获取用户的ak、sk需要读取数据库,想要实现在API网关项目中 快速调用其他项目中的代码,即复用其他项目代码 -- RPC 2、开发监控统计功能
怎么调用其他项目的方法? 1、复制代码和依赖、环境 2、HTTP请求(提供一个接口controller,供其他项目调用) 3、RPC 4、把公共的代码打个jar包,其他项目去引用(客户端SDK)
HTTP请求怎么调用? 1、提供方开发一个接口(地址、请求方法、参数、返回值) 2、调用方使用HTTP Client之类的代码包去发送HTTP请求RPC 作用:像调用本地方法一样调用远程方法 1、对开发者更透明,减少了很多的沟通成本 2、RPC向远程服务器发送请求时,未必要使用HTTP协议,也可以是TCP/IP
《使用dubbo框架,运用RPC快速远程调用方法》
过程分析:
整合运用zookeeper注册中心:通过内嵌的方式运行,更方便。最先启动注册中心,先启动provider,再启动consumer。1、backend项目作为服务提供者,提供三个方法:a.实际情况是应该去数据库中查是否已分配给用户b.从数据库中查询模拟接口是否存在,以及请求方法是否匹配(还可以校验请求参数)c.调用成功,接口调用次数 + 1 invokeCount2、gateway项目作为服务调用者,调用这3个方法
在分布式系统中,在微服务架构常见问题:
- 服务和服务地址如何进行映射和管理
- 服务注册后,如何被及时发现
- 服务异常时,如何进行降级
- 服务宕机后,如何及时下线
- 服务如何有效的水平扩展
- 服务发现时,如何进行路由
- 注册中心如何实现自身的高可用
一个下午和一个晚上,就干了dubbo框架下RPC服务。晚上总算是跑通了。
明天继续干。争取明天,第一个项目,终结。
*使用dubbo框架实现RPC:
Dubbo是一个高性能、轻量级的开源Java RPC框架(RPC意思是远程调用)
关键点三大类:依赖配置、启动类服务类引用类注解、注册中心nacos安装启动。
1、消费者与提供者安装依赖(dubbo框架 & nacos注册中心);配置yml自动完成注册<dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo</artifactId><version>3.0.9</version></dependency><dependency><groupId>com.alibaba.nacos</groupId><artifactId>nacos-client</artifactId><version>2.1.0</version> </dependency>
dubbo:application:name: dubbo-springboot-demo-providerprotocol:name: dubboport: -1registry:id: nacos-registryaddress: nacos://localhost:8848
2、springboot项目启动类写@Enabledubbo;提供服务的类写@DubboService;消费服务@DubboReference3、映射接口要是相同的路径、内部声明相同的方法提供者:映射接口com/yupi/project/provider/DemoService.java
消费者:映射接口com/yupi/project/provider/DemoService.java
内部声明相同的方法,实现快速调用
4、实现调用
注入:
@DubboReference(check=false) private DemoService demoService;
*抽象公共服务
抽象公共服务
1、项目名:yuapi-common
2、目的:让方法、实体类在多个项目间复用,减少重复编写。
3、服务抽取:数据库中查是否已分配给用户秘钥(根据 accessKey 拿到用户信息,返回用户信息,为空表示不存在)
4、从数据库中查询模拟接口是否存在(请求路径、请求方法、请求参数,返回接口信息,为空表示不存在)
5、接口调用次数 + 1 invokeCount(accessKey、secretKey(标识用户),请求接口路径)
6、步骤:新建干净的 maven 项目,只保留必要的公共依赖抽取 service 和实体类install 本地 maven 包让服务提供者引入 common 包,测试是否正常运行让服务消费者引入 common 包
@Resource 与 @DubboReference区别:
1、@Resource是Spring中注入bean ,对象存储在容器中 (同一个项目中的引用)
2、@DubboReference是Dubbo框架下RPC引用 (不同项目中的引用)
正在写获取统计数据的操作,使用的很多新东西,没必要敲,直接看,看分析结果。
* 客户端SDK
主要是封装了获取请求拿到ak,sk与请求体,生成签名sign的功能。这样对于以后的项目可以直接调用。
*统计分析:
最开始通过MySQL统计,每次调用后,网关发起RPC调用,调用次数+1;
但是这样子在使用Jmeter压测工具分析时会出现调用次数统计不准确,我分析出来是由于没有在事务层面加锁,导致数据库出现并发写的问题。
想过直接在事务层面加锁,但是会大大降低效率。最后想到可以使用Redis的Zset来实现排序,其中权重参数score用来存储调用次数。
总结复习: 1、查看接口统计信息饼图还没处理好2、扩展的点自己试着做,找大佬项目学习3、首先是宏观:掌握 各个流程。再细节上:从头到尾把每个细节处理点掌握;代码掌握;业务逻辑!技术:RPC、签名认证啥的宏观上你得明确每个技术点;细节上代码 看看参考项目要掌握哪些东西。 第一个项目,不要搞成夹生饭!!!
先业务-三层架构逻辑 -》》 再具体方法代码逻辑
*面经:
1、项目是你自己做的吗?你为什么做这样的一个项目?你做这个项目的背景(初衷)是什么?(几乎每次都被问到)
答:
我的初衷是尽可能地帮助和服务更多的用户和开发者,让他们更加方便快捷地获取他们想要的信息和功能。接口开放平台它可以帮助开发者快速接入一些常用的服务,从而提高他们的开发效率,比如天气服务、随机头像和短网址等服务,它们是一些应用或者小程序中常见的功能,所以提供这些接口可以帮助开发者更加方便地实现这些功能。这些接口也可以让用户在使用应用时获得更加全面的功能和服务,从而提高他们的用户体验。所以我认为接口开放平台是一个有意义的项目,可以为用户和开发者带来更多的便利和价值。
(注:因为我个人已经将项目上线,并能够提供一些真实的接口服务。有条件的同学尽量将项目上线。此外有两场的面试官想要查看数据库,我开了屏幕共享给他们看,所以要对数据库的表结构和设计有一定的了解。)
2、项目的架构你是怎么设计的?
答:Nginx部署 + 分布式架构
我采用前后端分离的架构,前端使用 Nginx 部署,通过 Nginx 反向代理将请求转发到 web 项目,因为项目刚刚上线,所以这里暂时采用了单机部署的模式,未来可能采取水平扩容的方式,增加多台节点,通过 Nginx 的负载均衡,将请求平均的分发到我的每个节点上,以支撑更高的并发。我的 web 项使用 Spring Boot 开发,并连接到了数据库和 Redis ,数据库使用的是 Mysql ,主要用来存储用户的信息和接口的信息;通过 redis 实现了分布式 session ,因为考虑到未来要使用分布式架构,为了避免使用 tomcat 保存 session 有用户登录失效的问题。
(注:这里我说出了反向代理,水平扩容,负载均衡等技术名词,很多面试官会根据这些名词进行延伸提问(引导面试官往自己熟悉的东西上提问)比如:说说什么是正向代理/反向代理?什么是水平扩容?什么是负载均衡?你了解哪些负载均衡的算法?提前准备好这些知识之后,就可以跟面试官一顿输出了。)
3、你怎么做的技术选型?为什么要用这些技术?
答:springboot自动装配+ MySQL存表 + Redis分布式session锁缓存
使用 SpringBoot 是因为通过自动装配能够提高项目的开发效率,还能够很好的整合其他服务。使用 Mysql 的原因是因为考虑到未来有用户充值交易,限制调用次数等场景需要用事务保证数据的完整性和一致性。使用 Redis 的原因是因为可以用来实现分布式 session ,锁,缓存等功能。因为 Redis 是一个单独的中间件,不同客户端可以往同一个 Redis 或者集群中存放 session /加锁,这样就能保证资源能够在分布式服务下都可见。并且由于 Redis 也是单线程的,同时也支持 lua 脚本,可以保证并发安全的问题,所以可以很简单的实现分布式锁的功能。
注:被面试官追问自动装配的原理你了解过吗?自动装配是怎么实现的?分布式 session 的原理?
4、你的开发流程是什么?先实现还是先技术选型?
答:参考现有结合自己 + 先产品后技术。技术为业务服务!
我先参考了一些已有的产品,根据这些产品,总结出来比较好的功能点,再结合自己想要实现的一些功能特色,去做了一个项目整体设计,有了产品原型后再进行技术选型。使用什么样的技术去解决什么样的业务问题。
5、为什么你要使用网关?
答:隐藏真实接口地址 + 全局管理鉴权路由访控流控等功能
我这个平台的关键点就在于提供接口服务,要保证接口的可用性和稳定性,所以将接口服务独立部署在另一台机器上,隐藏真实的接口地址及端口,调用接口服务的请求都必须经过网关流量染色之后..(这里细节太多,比如 rpc 调用获取用户 sk ,重新生成签名认证等等)之后,将请求转发到真实的接口地址,防止接口被恶意调用、盗刷。
(注:这个问题要对网关做了什么事情非常非常熟悉,建议反复观看鱼皮大佬的直播回放。)
6、为什么使用 RPC 调用?有了解过其他的方式吗?
答:调用操作数据库服务 + Open Feign
网关内签名认证,验证接口等功能需要操作数据库,因为如果在网关引入数据库的操作的话,不仅会增加项目体积,而且违背了设计原则的单一职责原则,所以我考虑通过服务间调用的方式,常见有两种方式,第一种是 Open feign ,原理是构造了一个 HTTP 请求,并会添加很多的请求头, body 是使用 json 字符串传输,所以调用效率会比较低,更加适合外部服务间的调用。然后我了解到 RPC 是可以基于 TCP 协议,避免了无用的请求头,以及可以通过将数据序列化为二进制流的形式传输,效率更加高效,更加安全,所以更适用于我这个场景。最终我选择了 Dubbo RPC 框架来实现这个功能。
7、你的接口调用次数统计以及排行是怎么实现的?
答:
通过 Mysql 统计,每次调用结束后,网关都会发起一个 rpc 请求,调用次数+1。
注:这里我会抛出一个设计缺陷,在实际测试过程中,通过 jmeter 压测工具,会出现调用次数不准的情况,原因是因为没有在业务层面加锁,导致数据库出现并发写的问题。并且并发量大的话,对数据库造成很大的压力。引导面试官问出,那你有什么更好的解决方案吗?
答:如果在业务层面加一个写锁的话,会影响业务的执行效率,所以我想使用 Redis 去解决, Redis 有一个数据结构 Zset 支持排序, score 可以用来存储调用次数,并且 Redis 是单线程,可以解决并发问题。
注:这里被追问过 Zset 的底层实现,以及如何将这些数据进行持久化保存,防止 Redis 宕机导致数据丢失,可以从 AOF , RDB 展开来讲,或者在后台开启一个定时任务,定时将这些数据进行落库。
8、你做过什么优化吗?你接口的性能怎么样?
答:修改存储引擎
我有一个接口是随机返回土味情话,我在数据库中插入了几千条土味情话,当调用接口时随机返回一条。在还没有优化前,接口的 qps 在300左右,但是考虑到这个接口只有读操作,没有增删改操作,所以我将这张表的存储引擎从 Innodb 改为了 MyISAM ,接口的 qps 提升到了1500。
(注:被面试官追问为什么改为 MyISAM 有这么大的性能提升? Innodb 和 MyISAM 有什么区别?这个问题一定要根据自己实际情况来答,根据自己擅长的方面,比如对查询语句做了索引优化,提升了接口的性能。)
总而言之,面试官会从各个角度去深挖项目的细节,考量你是不是真的自己做的,是不是真的理解?所以要做到对项目的所有细节都非常的熟悉。当完全理解项目之后,就能够提前预测到面试官会怎么问,并在面试过程中说出一些技术名词引导面试官,然后对这些问题,和延伸的知识点能够完全掌握后,相信一定可以征服面试官。
相关文章:
API 开放平台项目(已整理,已废弃)
项目大纲 前端 React 18Ant Design Pro 5.x 脚手架Ant Design & Procomponents 组件库Umi 4 前端框架OpenAPI 前端代码生成 后端 Java Spring BootMySQL 数据库MyBatis-Plus 及 MyBatis X 自动生成API 签名认证(Http 调用)Spring Boot Starter&#…...
魔棒无人直播系统有哪些优势?
随着科技的发展,越来越多新鲜事物的出现,它们代替了我们做很多的事情,开始解放着自己的双手,其中,无人直播的出现,就让直播变得更加简单。 因为是无人直播,所以全程不需要真人出镜,…...
[Flutter]WindowsOS中相关配置
Flutter项目在Windows平台上如何配置 目录 Flutter项目在Windows平台上如何配置 写在开头 正文 1、OS准备 2、编译环境准备 ① 下载AndroidStudio ② 下载dart ③ 下载flutter ④ 下载并安装VS ⑤ 在AS中配置dart和flutter 3、配置中遇到的问题 写在结尾 写在开头…...
[C语言]时间戳
时间戳的概念 时间戳就是定义一个时间点作为0秒, 之后每过一秒依此加一, 将当前的时间戳换算成年月日, 再加上起点, 获得的就是现在时刻的时间. 根据地球时区的偏移, 比如北京时间是东八区, 做一个偏移量的加减. 0起点: 1900年1月1日0时0分0秒. 0偏移地点: 英国伦敦 时间戳…...
Unity游戏资源更新(AB包)
目录 前言: 一、什么是AssetBundle 二、AssetBudle的基本使用 1.AssetBundle打包 2.BuildAssetBundle BuildAssetBundleOptions BuildTarget 示例 3.AssetBundle的加载 LoadFromFile LoadFromMemory LoadFromMemoryAsync UnityWebRequestAsssetBundle 前…...
GPT分区格式
GPT分区格式 [rootlocalhost ~]# gdisk /dev/sdb -bash: gdisk: 未找到命令 [rootlocalhost ~]# yum -y install gdisk- gdisk命令用于查看磁盘使用情况和磁盘分区(GPT分区格式) - 命令格式:gdisk [选项...] [设备路径] - 常用选项&…...
SVN管理-备份还原篇
背景: 当你没有svn的时候,写代码战战兢兢,又怕代码丢失白干,搞了svn做版本管理,随着时间的推移,所有的版本信息都在唯一的svn服务器,又开始担心服务器宕机,数据丢失问题,…...
程序的重定位
可以理解为编译和链接 过程中产生的地址项都是临时的相对的。编译的时候的地址,在链接时会被修改。最终链接后生成的bin文件的地址项,在加载运行时 也会被修改。 链接器会对所有的输入文件进行扫描,之后就可以确定段的大小,符号定…...
【STM32F103】TIM定时器PWM
定时器分类 STM32F1中除了互联型产品(STM32F103C8T6为64KB Flash 中容量产品),其余有8个定时器。 可以8个定时器分为高级,通用,基本三种。 高级定时器有两个,分别是TIM1和TIM8。 通用定时器有四个&…...
图论及其应用的一些论断---选择题
在任意一个网络N=(X,Y,I,A,c)中,最大流的值等于最小割的容量。在任意6个人的集会上,要么有3个人互相认识,要么有3个人互不认识。若G为无向简单图,则图G的边数ε,点数v之间有: ε < = ( v 2 ) ε<=\binom{v}{2} ε<=...
腾讯云轻量应用服务器镜像操作系统如何选择?
腾讯云轻量应用服务器镜像怎么选择?镜像是指轻量服务器的操作系统,可以选择宝塔Linux面板8.0.4腾讯云专享版,如果需要Win系统建议选择Windows Server 2012 R2 中文版,腾讯云服务器网txyfwq.com分享腾讯云轻量应用服务器镜像操作系…...
鸿蒙原生应用/元服务开发-发布基础类型通知类型与接口
基础类型通知主要应用于发送短信息、提示信息、广告推送等,支持普通文本类型、长文本类型、多行文本类型和图片类型。 表 基础类型通知中的内容分类 目前系统仅通知栏订阅了通知,将通知显示在通知栏里。基础类型通知呈现效果示意图如下所示。 图1基础类…...
Apisix常见问题
1.通过接口操作路由时X-API-KEY cd /usr/local/apisix/conf vim config-default.yaml注释掉这一部分 #allow_admin: # http://nginx.org/en/docs/http/ngx_http_access_module.html#allow# - 0.0.0.0/24 # If we dont set any IP list, then a…...
Docker 安装Mysql
目录 Docker Mysql安装 ✨安装和配置mysql ✨远程连接mysql远程连接 MySQL 是世界上最流行的开源数据库。根据 DB-Engines的调查数据,MySQL 是第二受欢迎的数据库,仅次于 Oracle 数据库。MySQL在过去由于性能高、成本低、可靠性好,已经成…...
Pillow图像处理(PIL.Image类的详细使用)
文章目录 Opencv、Matplotlib(plt)、Pillow(PIL)、Pytorch读取数据的通道顺序Python图像处理库(PIL、Pillow、Scikit-image、Opencv)Pillow 官方文档(超详细,超推荐)一、PIL库与Pillow库的区别二、Pillow库(…...
嵌入式开发——ADC开发
学习目标 了解ADC开发流程掌握采样方式能够使用ADC进行芯片内部通道进行采样能够使用ADC对外部电路进行采样学习内容 GD32F4的ADC 特点: 16个外部模拟输入通道;1个内部温度传感通道(VSENSE);1个内部参考电压输入通道(VREFINT);1个外部监测电池VBAT供电引脚输入通道。ADC开…...
FreeSWITCH t38测试
主叫 192.168.100.205 被叫 192.168.100.121 主叫侧发送multipage.tif 被叫侧接收传真,保存为recv.tif 主叫侧: originate [fax_enable_t381][fax_verbose1][fax_disable_v170][fax_ident77777777][fax_enable_t38_request1]sofia/internal/1234192.168.100.121:…...
跑腿配送系统技术探析
概述 跑腿配送系统是一种基于现代科技的服务平台,通过智能化的技术手段,实现用户需求的快速响应和高效配送。本文将探讨该系统的核心技术原理,以及在实际开发中的一些代码示例。 技术原理 1. 用户请求与任务分配 跑腿配送系统的第一步是…...
【数据不完整?用EM算法填补缺失】期望值最大化 EM 算法:睹始知终
期望值最大化算法 EM:睹始知终 算法思想算法推导算法流程E步骤:期望M步骤:最大化陷入局部最优的原因 算法应用高斯混合模型(Gaussian Mixture Model, GMM)问题描述输入输出Python代码实现 算法思想 期望值最大化方法&a…...
PMP证书可以挂靠吗?
PMP证书不是国内的证书,挂靠不了呀,想挂靠,可以考软考/一建等,里面也有项目管理相关的证书。 PMP证书虽然不能挂靠,但是用处还是很大的,例如提升个人能力、薪资待遇,还有持证可享一些城市的福利…...
HTML语义化的理解
HTML语义化是指在编写HTML代码时,合理地选择适当的标签和属性来描述页面的结构和内容,使得代码更具有可读性、可维护性和可访问性。 可读性:通过使用语义化的标签,可以清晰地表达页面的结构和内容,使得代码更易于阅读和…...
(Java企业 / 公司项目)注册,配置中心Nacos的怎么使用?(含相关面试题)(一)
在企业项目中使用Nacos实现的功能操作,以及如何在自己的环境中搭建Nacos环境,包含demo 一. 官网介绍:home (nacos.io) 文档地址:Nacos 快速开始 二. 准备Nacos环境 在公司里面很多的服务以及环境都是自己搭建的所以我在这里就从…...
计算机网络---知识点
ARPANET----NFSNET—ANSNET—Internet发展及协议 移动互联网 物联网 无线自组网、无线传感器网络、无线个域网 ISO/OSI网络体系结构 TCP/IP网络体系结构 对等通信、PDU 电路交换、报文交换、分组报文交换 虚电路、数据报 信道复用技术 网络性能的主要指标(…...
力扣42. 接雨水
双指针法 思路: 将数组前后设置为 left、right 指针,相互靠近;在逼近的过程中记录两端最大的值 leftMax、rightMax,作为容器的左右边界;更新指针规则: 如果数组左边的值比右边的小,则更新 left…...
SpringSecurity-2.7中跨域问题
SpringSecurity-2.7中跨域问题 访问测试 起因 写这篇的起因是会了解到 SSM(CrosOrigin)解决跨域,但是会在加入SpringSecurity配置后,这个跨域解决方案就失效了,而/login这个请求上是无法添加这个注解或者通过配置(WebMvcConfig)去解决跨域,所以只能使用SpringSecurity提供的.c…...
Java解决字典序最小回文串
Java解决字典序最小回文串 01 题目 给你一个由 小写英文字母 组成的字符串 s ,你可以对其执行一些操作。在一步操作中,你可以用其他小写英文字母 替换 s 中的一个字符。 请你执行 尽可能少的操作 ,使 s 变成一个 回文串 。如果执行 最少 操…...
【力扣100】207.课程表
添加链接描述 class Solution:def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:# 思路是计算每一个课的入度,然后使用队列进行入度为0的元素的进出# 数组:下标是课程号,array[下标]是这个课程的入度# 哈希…...
2024年生成式AI支出将翻倍,到2027年将超1500亿美元
据国际数据公司(IDC)的预测,2023年全球企业在生成式人工智能(GenAI)解决方案上的投资已达194亿美元,预计在2024年将翻番。该预测还指出,包括GenAI软件、相关硬件和服务在内的支出将在2027年达到1511亿美元,…...
【代码随想录】刷题笔记Day42
前言 这两天机器狗终于搞定了,一个控制ROS大佬,一个计院编程大佬,竟然真把创新点这个弄出来了,牛牛牛牛(菜鸡我只能负责在旁边喊加油)。下午翘了自辩课来刷题,这次应该是元旦前最后一刷了&…...
数据库云平台新数科技完成B轮融资,打造全链路智能化数据库云平台
数据库云平台软件厂商「北京新数科技有限公司」(以下简称「新数科技」)已于2023年完成B1轮和B2轮融资,分别由渤海创富和彬复资本投资;义柏资本担任本轮融资独家财务顾问。 新数科技成立于2014年,当前产品矩阵包括数据库…...
彩票网站做代理/网络营销的缺点及建议
首先查看配置内mysqlDriver 是否匹配: com.mysql.jdbc.Driver 是 mysql-connector-java 5中的,com.mysql.cj.jdbc.Driver 是 mysql-connector-java 6中的 其次查看pom内驱动是否版本对应、 mysql的版本对应jdbc驱动的版本 Connector/J 5.1 支持Mysql 4.…...
网站标题优化排名/百度开户联系方式
3D 点 Control 3D 点控件效果允许您控制 3 轴 (x,y,z) 的 3D 层位置或锚点。 将 3D 点控件效果拖放到3D图层上首先复制 3D 图层的位置属性,并将其粘贴到 3D 点控件中CTRL+C | Windows Command+C | MAC 在你的图层位置按住 ALT ,点击秒表,然后链接你的 3D 点控件(见下图)完…...
建设网站是否等于开展网络营销/青岛seo排名收费
wc功能是实现一个文件的行数单词数和字符数的统计,这个项目的实现平台是window,我所用的IDE是VS2013,我首先从在百度搜了相关的一些代码,然后自己模仿着写了一个,基本实现了行数,单词数和字符数的统计。转载于:https:/…...
免费网站模板库/三叶草gy5987
展开全部用“”替换文件中的内32313133353236313431303231363533e78988e69d8331333337626137容达到删除目的import java.io.InputStream;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.FileWriter;import java.util.…...
网站制作熊猫建站/域名怎么注册
MySQL索引到底是干什么的?这个问题自己一直理解的很模糊,只知道它相当于书的目录,能加快数据检索速度。但是要深入一点去说,它为什么能加快数据检索速度,从哪能看出它加快了检索速度,说到这可能我就有点迷茫…...
利用店铺网站做灰色优化/安卓系统优化app
开头 这是一次代码优化过程中发现的问题,在功能优化后发现部分数据查不到出来了,问题就在于一条sql上的#和$。 下图为两条sql: 从图上可以看出 wwlr.LabelId in(${showLabels}) 和 wwlr.LabelId in(#{showLabels}),其中showLabe…...