当前位置: 首页 > news >正文

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 等工具库
  1. 项目介绍和计划
  2. 需求分析
  3. 业务流程和子系统介绍
  4. 技术选型(各技术作用讲解)
  5. 前后端项目初始化
    1. 前端 Ant Design Pro 框架最新版本教程
    2. 后端 Spring Boot 万用模板使用
  6. 数据库表设计
  7. 前后端代码自动生成(强烈推荐,大幅提高开发效率!)
  8. 登录页开发
  9. 接口管理功能开发(Ant Design 高级组件使用)
  10. 模拟 API 接口项目开发
  11. HTTP 接口调用
  12. API 签名认证详解及开发
  13. 客户端 SDK 开发(Spring Boot Starter)
  14. 管理员接口发布 / 下线功能开发
  15. 接口列表页开发
  16. 在线调试接口功能开发
  17. 接口调用统计开发
    1. 后端开发
    2. 优化方案分析及对比
  18. API 网关详解
    1. 网关介绍及优点
    2. 10 种网关应用场景
    3. 网关分类及技术选型
  19. Spring Cloud Gateway 网关实现
    1. 详细带读官方文档
    2. 统一业务处理:用户鉴权及接口调用次数统计
  20. 项目分布式改造
    1. 公共模块抽象
    2. RPC 和 HTTP 调用详解及对比
    3. Dubbo 框架讲解及示例项目开发
    4. Dubbo 业务实战
  21. 管理员统计分析功能
    1. 前端 2 种可视化库的使用
    2. 后端聚合查询接口开发
  22. 项目扩展点及上线分析

一、初始化前后端框架

项目前端初始化---脚手架安装

直接使用开始使用 - 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. 项目设计、技术选型
  2. 基础项目的搭建
  3. 接口管理
  4. 用户查看接口

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

由于之前没有刚开始就删除国际化配置,之后再执行的,导致出现故障,现在登录界面无法加载,也就是权限校验没法执行,技术解决不了,趁着还没有进行太多,直接重新,从头来过。

  • 第二期 -- 接口调用
  1. 继续开发接口管理前端页面
  2. 开发模拟api接口
  3. 开发调用这个接口的代码
  4. 保证调用的安全性 (api签名认证)
  5. 客户端SDK开发
  6. 管理员接口 发布 与调用
  7. 接口文档展示、接口在线调用

注意: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到地了。先不改了,之后还会有延伸,到时再改

第三期

  1. 开发接口发布/下线的功能(管理员)
  2. 前端去浏览接口、查看接口文档、申请签名(注册)
  3. 在线调试(用户)
  4. 统计用户调用接口的次数
  5. 优化系统-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网关作为请求的单一入口点,将请求分配给相应的服务,然后收集结果并将其传递给请求者。而不是让客户单独请求访问每项微服务。

  1. 核心功能:路由、鉴权
  2. 管理上处理:负载均衡、跨域、业务处理、访问控制、发布控制、流量染色、接口保护
  3. 日志上处理:监控日志、报表
路由:起到转发的作用。比如有接口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 签名认证&#xff08;Http 调用&#xff09;Spring Boot Starter&#…...

魔棒无人直播系统有哪些优势?

随着科技的发展&#xff0c;越来越多新鲜事物的出现&#xff0c;它们代替了我们做很多的事情&#xff0c;开始解放着自己的双手&#xff0c;其中&#xff0c;无人直播的出现&#xff0c;就让直播变得更加简单。 因为是无人直播&#xff0c;所以全程不需要真人出镜&#xff0c;…...

[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包)

目录 前言&#xff1a; 一、什么是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命令用于查看磁盘使用情况和磁盘分区&#xff08;GPT分区格式&#xff09; - 命令格式&#xff1a;gdisk [选项...] [设备路径] - 常用选项&…...

SVN管理-备份还原篇

背景&#xff1a; 当你没有svn的时候&#xff0c;写代码战战兢兢&#xff0c;又怕代码丢失白干&#xff0c;搞了svn做版本管理&#xff0c;随着时间的推移&#xff0c;所有的版本信息都在唯一的svn服务器&#xff0c;又开始担心服务器宕机&#xff0c;数据丢失问题&#xff0c…...

程序的重定位

可以理解为编译和链接 过程中产生的地址项都是临时的相对的。编译的时候的地址&#xff0c;在链接时会被修改。最终链接后生成的bin文件的地址项&#xff0c;在加载运行时 也会被修改。 链接器会对所有的输入文件进行扫描&#xff0c;之后就可以确定段的大小&#xff0c;符号定…...

【STM32F103】TIM定时器PWM

定时器分类 STM32F1中除了互联型产品&#xff08;STM32F103C8T6为64KB Flash 中容量产品&#xff09;&#xff0c;其余有8个定时器。 可以8个定时器分为高级&#xff0c;通用&#xff0c;基本三种。 高级定时器有两个&#xff0c;分别是TIM1和TIM8。 通用定时器有四个&…...

图论及其应用的一些论断---选择题

在任意一个网络N=(X,Y,I,A,c)中,最大流的值等于最小割的容量。在任意6个人的集会上,要么有3个人互相认识,要么有3个人互不认识。若G为无向简单图,则图G的边数ε,点数v之间有: ε < = ( v 2 ) ε<=\binom{v}{2} ε<=...

腾讯云轻量应用服务器镜像操作系统如何选择?

腾讯云轻量应用服务器镜像怎么选择&#xff1f;镜像是指轻量服务器的操作系统&#xff0c;可以选择宝塔Linux面板8.0.4腾讯云专享版&#xff0c;如果需要Win系统建议选择Windows Server 2012 R2 中文版&#xff0c;腾讯云服务器网txyfwq.com分享腾讯云轻量应用服务器镜像操作系…...

鸿蒙原生应用/元服务开发-发布基础类型通知类型与接口

基础类型通知主要应用于发送短信息、提示信息、广告推送等&#xff0c;支持普通文本类型、长文本类型、多行文本类型和图片类型。 表 基础类型通知中的内容分类 目前系统仅通知栏订阅了通知&#xff0c;将通知显示在通知栏里。基础类型通知呈现效果示意图如下所示。 图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的调查数据&#xff0c;MySQL 是第二受欢迎的数据库&#xff0c;仅次于 Oracle 数据库。MySQL在过去由于性能高、成本低、可靠性好&#xff0c;已经成…...

Pillow图像处理(PIL.Image类的详细使用)

文章目录 Opencv、Matplotlib(plt)、Pillow(PIL)、Pytorch读取数据的通道顺序Python图像处理库&#xff08;PIL、Pillow、Scikit-image、Opencv&#xff09;Pillow 官方文档&#xff08;超详细&#xff0c;超推荐&#xff09;一、PIL库与Pillow库的区别二、Pillow库&#xff08…...

嵌入式开发——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 被叫侧接收传真&#xff0c;保存为recv.tif 主叫侧: originate [fax_enable_t381][fax_verbose1][fax_disable_v170][fax_ident77777777][fax_enable_t38_request1]sofia/internal/1234192.168.100.121:…...

跑腿配送系统技术探析

概述 跑腿配送系统是一种基于现代科技的服务平台&#xff0c;通过智能化的技术手段&#xff0c;实现用户需求的快速响应和高效配送。本文将探讨该系统的核心技术原理&#xff0c;以及在实际开发中的一些代码示例。 技术原理 1. 用户请求与任务分配 跑腿配送系统的第一步是…...

【数据不完整?用EM算法填补缺失】期望值最大化 EM 算法:睹始知终

期望值最大化算法 EM&#xff1a;睹始知终 算法思想算法推导算法流程E步骤&#xff1a;期望M步骤&#xff1a;最大化陷入局部最优的原因 算法应用高斯混合模型&#xff08;Gaussian Mixture Model, GMM&#xff09;问题描述输入输出Python代码实现 算法思想 期望值最大化方法&a…...

PMP证书可以挂靠吗?

PMP证书不是国内的证书&#xff0c;挂靠不了呀&#xff0c;想挂靠&#xff0c;可以考软考/一建等&#xff0c;里面也有项目管理相关的证书。 PMP证书虽然不能挂靠&#xff0c;但是用处还是很大的&#xff0c;例如提升个人能力、薪资待遇&#xff0c;还有持证可享一些城市的福利…...

HTML语义化的理解

HTML语义化是指在编写HTML代码时&#xff0c;合理地选择适当的标签和属性来描述页面的结构和内容&#xff0c;使得代码更具有可读性、可维护性和可访问性。 可读性&#xff1a;通过使用语义化的标签&#xff0c;可以清晰地表达页面的结构和内容&#xff0c;使得代码更易于阅读和…...

(Java企业 / 公司项目)注册,配置中心Nacos的怎么使用?(含相关面试题)(一)

在企业项目中使用Nacos实现的功能操作&#xff0c;以及如何在自己的环境中搭建Nacos环境&#xff0c;包含demo 一. 官网介绍&#xff1a;home (nacos.io) 文档地址&#xff1a;Nacos 快速开始 二. 准备Nacos环境 在公司里面很多的服务以及环境都是自己搭建的所以我在这里就从…...

计算机网络---知识点

ARPANET----NFSNET—ANSNET—Internet发展及协议 移动互联网 物联网 无线自组网、无线传感器网络、无线个域网 ISO/OSI网络体系结构 TCP/IP网络体系结构 对等通信、PDU 电路交换、报文交换、分组报文交换 虚电路、数据报 信道复用技术 网络性能的主要指标&#xff08…...

力扣42. 接雨水

双指针法 思路&#xff1a; 将数组前后设置为 left、right 指针&#xff0c;相互靠近&#xff1b;在逼近的过程中记录两端最大的值 leftMax、rightMax&#xff0c;作为容器的左右边界&#xff1b;更新指针规则&#xff1a; 如果数组左边的值比右边的小&#xff0c;则更新 left…...

SpringSecurity-2.7中跨域问题

SpringSecurity-2.7中跨域问题 访问测试 起因 写这篇的起因是会了解到 SSM(CrosOrigin)解决跨域,但是会在加入SpringSecurity配置后,这个跨域解决方案就失效了,而/login这个请求上是无法添加这个注解或者通过配置(WebMvcConfig)去解决跨域,所以只能使用SpringSecurity提供的.c…...

Java解决字典序最小回文串

Java解决字典序最小回文串 01 题目 给你一个由 小写英文字母 组成的字符串 s &#xff0c;你可以对其执行一些操作。在一步操作中&#xff0c;你可以用其他小写英文字母 替换 s 中的一个字符。 请你执行 尽可能少的操作 &#xff0c;使 s 变成一个 回文串 。如果执行 最少 操…...

【力扣100】207.课程表

添加链接描述 class Solution:def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:# 思路是计算每一个课的入度&#xff0c;然后使用队列进行入度为0的元素的进出# 数组&#xff1a;下标是课程号&#xff0c;array[下标]是这个课程的入度# 哈希…...

2024年生成式AI支出将翻倍,到2027年将超1500亿美元

据国际数据公司&#xff08;IDC&#xff09;的预测&#xff0c;2023年全球企业在生成式人工智能(GenAI)解决方案上的投资已达194亿美元&#xff0c;预计在2024年将翻番。该预测还指出&#xff0c;包括GenAI软件、相关硬件和服务在内的支出将在2027年达到1511亿美元&#xff0c;…...

【代码随想录】刷题笔记Day42

前言 这两天机器狗终于搞定了&#xff0c;一个控制ROS大佬&#xff0c;一个计院编程大佬&#xff0c;竟然真把创新点这个弄出来了&#xff0c;牛牛牛牛&#xff08;菜鸡我只能负责在旁边喊加油&#xff09;。下午翘了自辩课来刷题&#xff0c;这次应该是元旦前最后一刷了&…...

数据库云平台新数科技完成B轮融资,打造全链路智能化数据库云平台

数据库云平台软件厂商「北京新数科技有限公司」&#xff08;以下简称「新数科技」&#xff09;已于2023年完成B1轮和B2轮融资&#xff0c;分别由渤海创富和彬复资本投资&#xff1b;义柏资本担任本轮融资独家财务顾问。 新数科技成立于2014年&#xff0c;当前产品矩阵包括数据库…...

彩票网站做代理/网络营销的缺点及建议

首先查看配置内mysqlDriver 是否匹配&#xff1a; com.mysql.jdbc.Driver 是 mysql-connector-java 5中的&#xff0c;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功能是实现一个文件的行数单词数和字符数的统计&#xff0c;这个项目的实现平台是window,我所用的IDE是VS2013&#xff0c;我首先从在百度搜了相关的一些代码&#xff0c;然后自己模仿着写了一个&#xff0c;基本实现了行数&#xff0c;单词数和字符数的统计。转载于: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索引到底是干什么的&#xff1f;这个问题自己一直理解的很模糊&#xff0c;只知道它相当于书的目录&#xff0c;能加快数据检索速度。但是要深入一点去说&#xff0c;它为什么能加快数据检索速度&#xff0c;从哪能看出它加快了检索速度&#xff0c;说到这可能我就有点迷茫…...

利用店铺网站做灰色优化/安卓系统优化app

开头 这是一次代码优化过程中发现的问题&#xff0c;在功能优化后发现部分数据查不到出来了&#xff0c;问题就在于一条sql上的#和$。 下图为两条sql&#xff1a; 从图上可以看出 wwlr.LabelId in(${showLabels}) 和 wwlr.LabelId in(#{showLabels})&#xff0c;其中showLabe…...