面试题整理

1.通过滑动窗口协议动态调整发送速率

滑动窗口协议是一种流量控制机制,用于管理数据发送方和接收方之间的数据传输速率,以避免因发送速率过快而导致的数据包丢失或拥塞。在TCP中,通过动态调整发送端的发送窗口大小来实现这一目标。

基本原理:

  1. 发送窗口:发送端维护一个发送窗口,窗口内的序列号表示已发送但未收到确认(ACK)的数据段。窗口大小是可变的,根据网络状况和接收端的反馈进行动态调整。

  2. 接收窗口:接收端也有一个接收窗口,并通过ACK信息告知发送端其当前接收窗口的大小。这个大小反映了接收端剩余的缓冲区容量以及处理能力。

  3. 通告窗口(Advertised Window Size):接收端会在每个ACK中携带自己的接收窗口大小,发送端据此调整自己的发送窗口。

  4. 流量控制过程

    • 当接收端接收到数据并有足够的缓冲区空间时,会增大通告窗口,发送端可以发送更多的数据。
    • 如果接收端处理速度较慢或者缓冲区接近满载,则减小通告窗口,发送端相应地减少待发送的数据量。
    • 发送端始终只能发送窗口内序号的数据段,并且只有当接收到对某个数据段的ACK后,才能将对应序号从窗口移除,并向窗口前端推进(即滑动),同时可能发送新的数据段填充窗口。

示例

  • 假设初始状态下,发送端发送窗口为4个序号单位,已发送序号0、1、2、3的数据段,接收端接收窗口也为4个序号单位。
  • 接收端收到序号0的数据段并返回ACK(0),此时发送端窗口向前滑动,发送序号4的数据段。
  • 若此时接收端处理速度变慢,只接收了序号0和1的数据段,于是它发回ACK(1),同时更新通告窗口为2个序号单位。
  • 发送端接收到ACK(1)后,知道序号0和1的数据段已被接收,窗口向前滑动至序号2和3,但由于接收端通告窗口变小,因此暂时不能发送序号5和6,直到接收端处理更多数据并增大其通告窗口。

这样,通过发送端和接收端之间不断地交互窗口信息,实现了对数据传输速率的动态控制,确保网络资源的有效利用和数据传输的可靠性。

2 http2.0了解吗?和http1.1的差距?

HTTP/2是超文本传输协议(HTTP)的第二个主要版本,相比于HTTP/1.1在性能、安全性和网络效率上有显著提升。以下是HTTP/2与HTTP/1.1的主要区别:

  1. 多路复用

    • HTTP/1.1中存在队头阻塞问题,即在一个TCP连接上一次只能发送一个请求,收到响应后才能发送下一个请求。
    • HTTP/2引入了多路复用技术,允许在一个TCP连接上同时处理多个请求和响应,避免了队头阻塞现象,提高了带宽利用率和页面加载速度。
  2. 二进制分帧

    • HTTP/1.x使用基于文本的格式进行数据传输。
    • HTTP/2将所有传输的信息分割为更小的独立帧,包括header帧、数据帧等,这些帧可以交错、并行地在同一个TCP连接上传输。
  3. 头部压缩

    • HTTP/1.1中的头部信息通常会占用大量字节,尤其是在多次请求时,重复的头部字段造成不必要的带宽消耗。
    • HTTP/2引入了HPACK压缩算法对头部进行压缩,减少了冗余信息的传输,大大提升了效率。
  4. 服务器推送(Server Push)

    • 服务器在客户端请求资源后,能够主动推送预测到客户端可能需要的其他资源,无需等待客户端发起请求,提前加载资源。
  5. 优先级和依赖性

    • HTTP/2允许设置帧的优先级,客户端可以根据页面渲染顺序指定资源的优先级,让服务器能合理安排资源的发送顺序。

综上所述,HTTP/2的核心改进在于通过减少延迟、提高带宽利用效率以及更好地支持现代Web应用的特性来优化用户体验和网络资源利用。

3 服务依赖redis服务崩溃后 如何保障服务稳定性

当服务依赖的Redis服务崩溃后,保障服务稳定性的方法可以包括以下策略:

  1. 高可用架构设计

    • 部署Redis集群:采用主从复制(Replication)和哨兵模式(Sentinel)或Cluster模式构建高可用Redis集群。这样即使一个节点失效,其他节点能够自动接管服务。
    • 数据持久化:确保Redis数据定期保存到磁盘上,通过AOF(Append-only File)或RDB(Redis Database)方式,在服务恢复时可以从磁盘快速重建数据。
  2. 客户端容错处理

    • 重试机制:在客户端库中实现合理的重试逻辑,当Redis连接失败或响应超时时,可以设置一定次数的重试。
    • 失效转移:客户端应能识别并自动切换到集群中的其他在线节点。
  3. 本地缓存策略

    • 对于非关键性或者读多写少的数据,可以考虑在服务端本地使用内存或其他存储介质作为临时缓存,当Redis不可用时,服务可以从本地缓存获取数据以减少对Redis的依赖。
    • 如果有可能,设计一种机制使得在Redis宕机期间,服务可以继续运行但可能暂时失去部分功能或性能下降。
  4. 降级处理

    • 在Redis无法访问时,服务可以进入降级模式,仅提供核心功能,或者将请求暂存入队列,待Redis服务恢复后再进行处理。
  5. 监控告警与自动化恢复

    • 设置完善的监控系统检测Redis服务状态,并在服务异常时立即发送告警通知运维人员。
    • 使用自动化工具或脚本进行故障检测和自愈,如自动重启Redis服务、重新配置客户端指向新的可用节点等。
  6. 服务隔离与熔断

    • 在分布式服务框架中,可以通过服务网格或API网关实现熔断机制,当Redis服务不可用时,服务调用Redis的部分可以迅速熔断,避免整个服务因等待Redis响应而阻塞。
  7. 冗余部署和备份计划

    • 在不同的数据中心或云区域部署多个Redis实例,提高整体系统的地理冗余性。
    • 定期备份Redis数据,并确保在灾难发生时有可靠的恢复方案。

综合运用上述策略,可以在一定程度上降低Redis服务中断对整体服务稳定性的影响,确保业务持续运行。同时,还需要根据具体业务场景和技术栈选择最合适的解决方案。

4 MySQL主库挂了,处理步骤通常包括以下几个关键环节:

  1. 识别问题

    • 确认主库是否真的宕机:检查服务器状态、网络连接、系统日志以及MySQL错误日志,确定数据库服务是否运行正常。
    • 如果是硬件故障,立即联系数据中心运维团队进行硬件修复或更换。
    • 如果是软件错误导致的宕机,查看错误日志来定位问题。
  2. 快速响应与止损

    • 通知相关业务团队,并根据业务重要性决定是否执行紧急降级操作,例如关闭写入操作以防止数据不一致。
    • 对于实时性要求不高的接口,可以暂时切换到静态数据或者返回默认信息,减轻对从库的压力和用户的等待时间。
  3. 恢复主库服务

    • 尝试重启MySQL服务。如果是因为内存溢出或其他非致命错误导致的宕机,重启可能能够解决问题。
    • 若重启无效,则需要进一步分析原因,如备份恢复、日志回滚等。
  4. 使用备用资源

    • 如果有可用的热备节点,可以启动该热备节点并将其提升为主库角色(在确保数据同步的情况下)。
    • 没有热备时,可以从最近的完整备份恢复数据,并利用binlog日志将数据追赶到崩溃前的时间点,然后转换为新的主库。
  5. 从库切换

    • 根据实际情况选择一个已同步最新的从库作为新的主库,执行必要的变更,如停止复制、更改复制模式(设置为可读写),更新应用配置指向新的主库地址。
    • 同时,其他从库也需要更新其主库地址,重新开始从新的主库上同步数据。
  6. 数据一致性验证

    • 在切换完成后,对新主库的数据进行完整性及一致性校验,确保业务不受影响。
  7. 监控与优化

    • 主库恢复正常后,持续监控系统的性能和稳定性,查找宕机的根本原因并优化避免类似问题再次发生。
    • 更新高可用和容灾策略,比如改进备份策略、增强监控报警机制、增加从库数量等。
  8. 记录与复盘

    • 记录下整个处理过程,包括故障发生的原因、处理步骤、影响范围和恢复结果,用于后期的经验总结和知识传承。

在整个过程中,必须保证数据的一致性和安全性,尽量减少停机时间并尽快恢复正常服务。同时,在设计之初就应该考虑高可用架构,如采用MySQL集群(如MySQL Group Replication)、Proxy层(如MaxScale)或者其他分布式数据库方案来提高整体系统的抗风险能力。

5 反爬了解吗?反爬的几项技术在项目里面怎么实现的?

反爬技术在项目中的实现通常包括但不限于以下几个方面:

  1. User-Agent限制

    • 实现方式:服务器端检查请求头中的User-Agent字段,验证其是否来自常见的浏览器。如果发现是爬虫的标识(如自定义的或常见爬虫库默认的UA),可以拒绝响应或者返回错误信息。
    • 项目实现:在后端代码中添加对请求头进行检查的逻辑,例如在Web框架(如Django、Express等)的中间件中过滤非正常UA。
  2. IP限制与封禁

    • 实现方式:记录并统计每个IP地址的访问频率和速率,当某个IP在短时间内发送大量请求时,将其加入黑名单或暂时封禁。
    • 项目实现:使用缓存(如Redis)、数据库或其他存储服务来记录IP访问次数,并设置相应的阈值判断及处理逻辑。
  3. 验证码

    • 实现方式:为重要接口或频繁抓取的页面增加图形验证码、滑动验证码、点选验证码等形式,阻止自动化脚本的直接访问。
    • 项目实现:集成验证码生成和校验组件,通常前端负责展示验证码,后端负责接收并校验用户提交的答案。
  4. Session管理

    • 实现方式:通过Session机制控制用户的访问行为,比如登录状态验证、防止重复操作等,这有助于识别并阻止非法爬虫。
    • 项目实现:在后端配置Session管理和验证流程,确保重要操作必须经过合法身份验证才能执行。
  5. 动态加载和JavaScript渲染

    • 实现方式:网页数据部分通过AJAX动态加载或采用SPA(Single Page Application)模式,使得简单的HTTP请求无法获取完整内容。
    • 项目实现:将重要数据通过异步API提供,同时在前端用JavaScript动态填充页面,对于爬虫而言需要解析JS或模拟浏览器执行环境(如使用Selenium)。
  6. robots.txt文件

    • 实现方式:通过网站根目录下的robots.txt文件声明哪些路径不允许爬虫抓取。
    • 项目实现:无需额外编程实现,只需正确编写并上传到服务器相应位置即可。但并不是所有爬虫都会遵守robots.txt规则。
  7. 加密链接和参数混淆

    • 实现方式:对请求链接进行加密处理,或者对请求参数进行混淆,使爬虫难以构造有效请求。
    • 项目实现:在生成链接或构建请求时进行加密处理,在服务器端解密后再进行业务逻辑处理。
  8. 请求频率限制

    • 实现方式:通过限速器模块限制同一客户端(根据IP、User-Agent等特征识别)在一定时间内的请求数量。
    • 项目实现:使用令牌桶算法、漏桶算法或其他流量控制策略,在网关层或应用层实施请求频率限制。
  9. 定制反爬策略

    • 根据实际场景设计特定的反爬策略,如要求用户授权、设备指纹检测等。

总之,具体的实现方式会因不同的开发语言、框架和应用场景而有所差异,关键是结合项目的实际情况制定合适的反爬措施,并在代码层面加以实现和优化。同时,也要注意遵循法律法规,避免过度反爬导致的法律风险。

6 项目部署的服务器是单机的,请问如果是大流量高并发请求服务器怎么处理?

当您的项目部署在单机服务器上且面临大流量高并发请求时,可采取以下策略来优化性能和提高处理能力:

  1. 负载均衡与代理层

    • 即使是单机环境,也可以考虑在前端配置一个负载均衡器(如Nginx)来分发请求。虽然单机无法实现真正的分布式负载均衡,但可以利用Nginx的高性能和反向代理功能,将部分静态资源直接返回,减少后端压力。
    • Nginx可以通过配置缓存机制,对静态资源进行缓存,并能有效处理HTTP请求的并发连接。
  2. 服务器性能提升

    • 硬件升级:增加内存以支持更多的并发连接数,提升CPU性能以快速处理请求,增大硬盘I/O速度或使用SSD存储提高数据读写效率,以及增加带宽确保网络传输不成为瓶颈。
    • 软件优化:选择合适的Web服务器软件并对其进行深度调优,例如针对Nginx或Apache的配置参数调整。
  3. 应用层面优化

    • 缓存技术:使用本地缓存(如Memcached、Redis等)缓存常用数据和计算结果,降低数据库访问频率,减轻数据库压力。
    • 异步处理:对于耗时的操作采用异步处理模型,避免阻塞主线程,例如通过消息队列系统处理非实时任务。
    • 数据库优化:优化SQL查询语句,建立索引,合理设计表结构,根据业务场景考虑是否引入读写分离、主从复制等技术提高读取性能。
  4. 代码层面优化

    • 减少不必要的计算和IO操作,精简HTTP响应头大小,压缩输出内容(如Gzip),使用CDN加速静态文件加载。
    • 对于动态内容,尽可能地将其转化为静态化页面或者半静态化页面,减少动态生成次数。
  5. 限制并发连接和请求速率

    • 可以设置合理的限速规则,控制客户端在同一时间段内的请求数量,防止短时间内大量请求冲击服务器。
  6. 动静分离

    • 将静态资源托管到独立的服务或存储中,比如使用CDN服务加速静态内容的分发,减轻服务器压力。
  7. 服务降级

    • 在高并发情况下实施服务降级策略,保证核心业务不受影响,暂时舍弃非关键功能。
  8. 监控与自动扩展

    • 建立完善的监控系统,实时监控服务器的各项指标,以便在压力过大时及时预警,并根据实际情况提前准备扩容方案。

然而,单机服务器在面对极高并发请求时存在物理极限,长期应对大流量高并发的最佳解决方案通常是转向集群架构,通过水平扩展多台服务器共同分担负载,实现弹性伸缩。如果条件允许,应当考虑迁移到云服务器,并利用云服务商提供的弹性伸缩功能进行动态扩缩容。

你可能感兴趣的:(java,后端)