2024校招美团base上海到店后端一面凉经(附详解):2023-8-29

这里是引用

1 自我介绍

2 实习

2.1 实习的背景

2.2 你觉得你这个部门中业务上比较难的点在哪儿

2.2.1 部门业务上的难点:

我自己答的:接线变化非常复杂,管理网流量和外网流量都到这一个数据中心,管理起来比较复杂,网络架构不断在变化

您在快手的实习背景指向了数据中心网络建设和弹性计算平台这两个非常核心和复杂的领域。这些领域确实存在一些技术和业务上的难点,以下是可能的一些挑战和难点:

  1. 规模与复杂性:在像快手这样的大型互联网公司,数据中心网络的规模非常大,这使得网络管理、维护和故障诊断都变得相当复杂。

  2. 高可用性的需求:快手作为一个流媒体平台,对网络的稳定性和可靠性有很高的要求。任何的网络中断都可能导致用户体验的严重下降。

  3. 安全挑战:大型互联网公司经常是攻击的目标。如何保障数据中心网络的安全,防止DDoS攻击、入侵和其他安全威胁是一个持续的挑战。

  4. 动态资源分配:为了支持弹性计算,数据中心网络必须能够动态地分配和调整资源,同时保持高效和稳定。

  5. 网络流量的预测和优化:快手作为一个内容平台,其流量模式可能因节目、活动或其他因素而发生变化。如何预测流量并进行优化是一个难点。

  6. 技术迭代与升级:随着技术的发展,数据中心网络需要不断地进行迭代和升级。如何在不中断服务的情况下完成这些升级是一个技术挑战。

  7. 成本与性能的权衡:如何在有限的预算内建设和维护一个高性能、高可靠性的数据中心网络是一个持续的挑战。

  8. 人员培训和团队协作:随着技术的发展,团队成员需要不断地学习和培训,以保持其技能的前沿性。此外,跨团队之间的协作也是成功实施数据中心网络策略的关键。

  9. 环境和可持续性考虑:数据中心的能源消耗和冷却是环境和经济的考虑因素。如何构建更加绿色和可持续的数据中心网络是当前和未来的一个主题。

总的来说,您选择的这个实习背景非常有挑战性和价值,也为您的职业发展提供了一个很好的平台。

2.2.2 个人在写需求时碰到的难点(如果2.2.1答不出来,可以往这方面引导)

当然,基于您提供的详细描述,以下是您在快手实习期间面临的主要难点:

  1. 动态同步需求:由于数据中心是根据用户流量动态调整的,您需要确保实时的实例架构可以反向同步到定义架构,保证数据一致性和灾备恢复。

  2. 复杂的表结构处理

    • 您提到了有六个不同的同步表,它们具有不同的结构特点,如树形结构、主子表结构等。
    • 同步不仅仅是内容复制,还包括处理表内的复杂关系,尤其是树形结构中的父子关系。
    • 只需要同步部分字段,而其他字段可能与第三方表有关联,存在依赖关系。
  3. 定制化到通用性的转换:您设计了定制化的程序来处理两种主要的表结构,然后利用类型擦除和反射机制进行泛化,以达到统一的访问和同步接口。

  4. 细粒度同步控制:为了实现更细粒度的同步操作,您增加了一些特殊字段,例如id对儿字段,以跟踪待比较或待同步的记录。

  5. 扩展性设计:考虑到后续可能会有新的同步表,您设计了遵循开闭原则的接口和策略,以确保能够容易地增加新的同步逻辑。

  6. 实例与定义的统一存储决策:需要权衡将实例架构和定义架构存放在同一张表中的利与弊,如简化数据模型、减少数据冗余、优化查询性能等。

综上所述,您在快手的实习期间面临了数据同步、复杂数据结构处理、系统设计泛化与特定化之间的平衡、细粒度同步控制、系统扩展性设计等多个方面的挑战。您的任务涉及到深入的系统设计、数据结构选择、优化策略以及与第三方数据的互操作性,这确实是一个相当复杂且具有挑战性的任务。

2.3 你们是如何解决的?

2.3.1 部门难点的解决方案

(1)自动化建设小组负责应对接线变化,架构变化这些需求

(2)监控小组负责流量报警和处理

确实,接线变化、管理与外网流量的混合以及不断变化的网络架构都给数据中心的管理带来了挑战。为了解决这些挑战,我们可以采取以下策略:

  1. 模块化和标准化:

    • 模块化设计: 将网络架构分解成独立的、可重复的模块,这样在进行扩展或修改时,可以在不影响整体架构的前提下进行调整。
    • 标准接口: 采用统一的标准接口,确保在扩展或变更网络组件时,各部分可以无缝对接。
  2. 分隔管理和外网流量:

    • 物理隔离: 使用单独的物理网络设备来分隔管理和外网流量。
    • 虚拟隔离: 通过VLAN或其他网络技术在同一物理网络上虚拟出多个独立的逻辑网络,确保数据流不会互相干扰。
  3. 统一的网络管理平台:

    • 通过集中的网络管理平台,可以在一个界面上监控、配置和维护整个数据中心的网络,大大简化了管理流程。
    • 该平台还可以与其他IT系统(如服务器、存储等)整合,实现跨域的统一管理。
  4. 自动化和智能化:

    • 网络自动化: 使用自动化工具自动完成网络配置、故障检测和恢复等任务。
    • 智能分析: 利用AI和机器学习技术分析网络流量,预测潜在问题,并提前采取措施。
  5. 持续的文档和培训:

    • 随着网络架构的变化,持续更新网络文档,确保团队成员都能了解当前的网络结构和配置。
    • 定期为团队成员提供培训,使他们掌握新的技术和工具。
  6. 设计弹性网络:

    • 在设计时预留一定的冗余和扩展性,确保网络在未来的增长和变化中可以持续稳定工作。
  7. 安全考虑:

    • 特别是在管理流量和外网流量混合的情况下,需要加强网络安全措施,例如使用防火墙、IDS/IPS等,确保数据的安全。

这些策略可以帮助数据中心应对复杂的接线、流量和网络架构变化的挑战,但需要结合实际情况进行细致的设计和实施。

2.3.2 个人需求难点的解决方案

答:

针对表的复杂性上:(1)使用合适的设计模式和反射原理,结合第三方的配置设计一套通用的同步接口

针对粒度控制上:(2)按照数据中心->机房->机架的粒度依次进行降级同步,比如预测数据中心的数据量很大,则采用按照机房

3 计算机网络

3.1 TCP的keepalive和HTTP的keep-alive的区别

  • TCP keepalive

    • 用途:TCP keepalive是一个用于检测TCP连接是否仍然存活的机制。如果长时间没有在连接上传输数据,TCP keepalive可以用来检查连接是否仍然有效。
    • 协议层次:这是一个在TCP层实现的特性。
  • HTTP keep-alive (注意,这里是"keep-alive",而不是“keepalived”)

    • 用途:HTTP keep-alive(也称为持久连接)是HTTP/1.1引入的一种机制,允许多个HTTP请求和响应在同一个TCP连接上连续地被发送,而不是为每一个请求/响应打开一个新的连接。
    • 协议层次:这是一个在HTTP层实现的特性。

3.2 如何实现

  • TCP keepalive

    • 机制:当连接上没有数据传输超过预定的时间时,系统会发送一个keepalive探测包。如果连续发送了特定数量的探测包还没有得到响应,系统就会判定该连接已死,并关闭它。
    • 配置:大多数操作系统都允许您配置TCP keepalive的参数,例如探测包的发送间隔和重试次数。
  • HTTP keep-alive

    • 机制:在HTTP/1.1中,默认所有连接都是持久的,除非明确指定"Connection: close"头部。客户端和服务器都可以在请求或响应中使用这个头部来关闭连接。
    • 配置:服务器和客户端通常允许您配置持久连接的时间长度或使用的请求数量。

3.3 HTTP的keep-alive与TCP的keepalive关系

虽然HTTP的keep-alive机制通常在TCP连接上实现,但它并不依赖于TCP的keepalive特性。它们是在不同的协议层次上操作的,并且各自独立解决了不同的问题。HTTP的keep-alive关心的是如何在一个已建立的连接上高效地传输多个请求和响应,而TCP的keepalive关心的是如何检测一个空闲的连接是否仍然存活。

3.4 tcp是如何保证可靠性传输的?

TCP(传输控制协议)通过一系列的机制来保证数据在网络中的可靠传输。以下是TCP为确保可靠性所采取的关键机制:

  1. 序列号 (Sequence Numbers):

    • TCP为每一个字节赋予一个唯一的序列号。序列号用于标识数据,以便接收方可以按正确的顺序重组它们,并检测是否有数据丢失。
  2. 确认 (Acknowledgments):

    • 当接收方成功接收到一个或多个数据段,它会返回一个确认消息(ACK)给发送方。确认号告诉发送方接收方期望接收的下一个字节的序列号。
  3. 重传 (Retransmissions):

    • 如果发送方在一段时间内没有接收到特定数据段的确认消息,它会假定该数据段已丢失或被损坏,并会重新发送该数据段。
  4. 滑动窗口 (Sliding Window):

    • TCP使用滑动窗口协议来控制发送方和接收方之间的数据流。窗口的大小定义了在需要确认之前,发送方可以发送多少数据。这有助于确保网络不被过载,并确保接收方能够有效地处理入站数据。
  5. 流量控制 (Flow Control):

    • 接收方使用滑动窗口的大小来告诉发送方它有多少可用的缓冲区。这确保发送方不会发送超出接收方处理能力的数据。
  6. 拥塞控制 (Congestion Control):

    • 当网络中的数据太多,可能导致数据丢失时,TCP会使用拥塞控制算法来降低数据发送速率。当网络条件改善时,TCP将逐渐增加数据的发送速率。
  7. 超时 (Timeouts):

    • TCP使用超时来检测数据丢失。如果在指定的时间内没有收到确认,发送方会假设数据已丢失,并进行重传。
  8. 三次握手 (Three-way Handshake):

    • 当建立一个新的TCP连接时,双方会使用三次握手来确保连接的建立是可靠的。
  9. 四次挥手 (Four-way Handshake):

    • 当终止一个TCP连接时,双方会使用四次挥手来确保连接的终止是可靠的,确保所有的数据都已被成功传输。
  10. TCP校验和 (Checksum):

    • 为了确保数据的完整性和正确性,TCP使用了校验和机制。这是一个端到端的错误检测机制,用于捕获在传输过程中可能发生的任何数据损坏。

    • 当发送方发送一个TCP段时,它会计算这个段的校验和,并将这个值放入TCP头部的校验和字段。接收方在收到这个段后也会计算校验和,并将其与头部的值进行比较。如果这两个值不匹配,这通常意味着数据在传输过程中已被损坏,接收方不会确认该段,导致发送方重新发送它。

    • 需要注意的是,校验和主要用于错误检测,而不是错误修复。如果发现有错误,数据通常会被丢弃,而不是尝试修复。

    这种机制确保了TCP传输中的数据在到达目的地之前是完整和未被篡改的,从而进一步提高了其传输的可靠性。

这些机制共同确保了TCP的可靠性,使其成为了许多应用程序和高层协议(如HTTP,FTP等)的首选传输协议。

3.4.1 由于TCP校验和不包含加密或密钥,所以它不能防御故意的数据篡改,什么意思?

这句话的意思是,虽然TCP校验和可以检测到数据在传输过程中的无意中的错误(例如因为电磁干扰、噪音等原因导致的随机位错误),但它不能防御那些故意篡改数据的行为。

假设攻击者截获了一个TCP段,并对数据进行了篡改。攻击者也可以重新计算这个篡改后的数据的校验和,并将其放入TCP头部。当接收方接收到这个被篡改的数据时,由于校验和是正确的(因为是攻击者故意计算出来的),接收方无法通过校验和来检测出数据已被篡改。

因此,要确保数据的真实性和完整性,仅仅依赖TCP的校验和是不够的。需要更强大的安全机制,例如使用数字签名或使用像TLS/SSL这样的协议,来加密数据并验证数据的完整性和真实性。

3.4 tcp为什么要三次挥手而不是两次?

TCP使用三次握手是为了在双方都确认自己和对方的发送和接收功能正常的基础上,建立稳定的连接。

  • SYN:主机A向主机B发送一个SYN包,表示我想打开一个新的连接。
  • SYN+ACK:主机B收到SYN包后,返回一个SYN+ACK的确认包,表示我已经准备好了,你也准备好了。
  • ACK:主机A再返回一个ACK包,表示我已经准备好了。

如果是两次握手,仅通过第一次和第二次握手,A知道自己和B都可以发送和接收,但B并不知道A的接收能力是否正常。只有三次握手,才能确保双方的发送和接收都没有问题。

三次握手还可以防止已经失效的请求突然传到服务端,因为这种连接请求已经过去很长时间,如果还能够建立连接,可能会造成不必要的错误。

3.4.1 如果是两次握手,仅通过第一次和第二次握手,A知道自己和B都可以发送和接收,但B并不知道A的接收能力是否正常。如果只有两次握手,是不是有可能遭受攻击,导致服务端建立大量的连接

是的,你提到的是一个非常重要的点。

如果TCP仅使用两次握手,那么除了之前提到的“B并不知道A的接收能力是否正常”之外,还有一个重要的安全隐患——SYN洪泛攻击(SYN Flood Attack)。

在SYN洪泛攻击中,攻击者发送大量伪造的SYN请求,导致服务器消耗大量资源处理这些伪造的请求,最终导致资源耗尽或服务不可用。这样的攻击在两次握手中会更容易成功,因为:

  1. 资源占用:在两次握手的情况下,当服务器收到第一个SYN请求后,它会分配资源并立即进入连接已建立的状态。但如果这个SYN请求是伪造的(攻击者并不打算完成连接),服务器就会为一个不真实的客户端浪费资源。

  2. 无法验证客户端的接收能力:由于没有第三次握手,服务器无法确认客户端的接收能力是否正常。这意味着攻击者可以简单地发送伪造的SYN请求,并使得服务器无法验证这些请求的真实性。

使用三次握手,服务器在第二步(SYN+ACK)后仍然处于一个半打开的状态,并等待客户端的确认。只有当客户端返回ACK时,服务器才完全建立连接。这为服务器提供了一个机会,使其不那么容易被伪造的请求所欺骗。

尽管三次握手为服务器提供了一定程度的保护,但SYN洪泛攻击仍然可能对其造成威胁。为了防范这种攻击,现代的网络设备和服务器软件实现了各种策略,如SYN cookies、限制半打开连接的数量等。

3.4.2 服务端可以通过第三次握手的序列号拒绝旧的连接嘛

你是对的。三次握手的确提供了一种机制,使得服务端可以通过检查序列号(sequence number)来识别和拒绝旧的或无效的连接请求。

当TCP连接建立时,客户端和服务器都会选择一个初始的序列号。在三次握手过程中,这些序列号用于标识每个连接请求和响应。

回到前面的场景,当客户端A发送其第一次的SYN请求时,它会选择一个序列号,例如X。如果这个请求被延迟,并且客户端A因为没有收到响应而重新尝试建立连接,它可能会选择一个新的序列号,例如Y。

  • 当旧的、被延迟的SYN请求(带有序列号X)最终到达服务器B,服务器B会发送一个SYN+ACK响应,其中包含客户端的序列号X和服务器选择的自己的序列号。

  • 但是,因为客户端A现在正在等待一个与序列号Y相关的响应,它会忽略这个带有序列号X的SYN+ACK响应。它只会认为与序列号Y相关的响应是有效的。

因此,序列号在三次握手中提供了一个机制,可以用于识别和拒绝失效的连接请求。服务端不会为旧的、失效的请求建立一个完整的连接,因为这些请求不会成功完成握手过程。

3.5 了解哪些攻击手段?

答:CSRF,DDOS,XSS,SYN洪泛攻击,预测tcp序列号攻击

当然可以。这三种都是常见的网页应用安全漏洞。

1. XSS(跨站脚本攻击):

  • 定义: XSS允许攻击者将恶意脚本注入到另一些用户看到的网页中。被攻击的用户可能会将其认证信息、cookie等发送到攻击者。
  • 类型:
    • 存储型XSS: 攻击者的数据被存储在服务器(例如在数据库、日志、消息等),之后用户访问这些数据时触发。
    • 反射型XSS: 攻击者需要诱使用户点击一个恶意链接,用户的浏览器执行恶意脚本,但脚本并不存储在服务器上。
    • DOM型XSS: 攻击载荷在DOM中被执行,而不是来自HTTP响应。

2. SQL注入:

  • 定义: 攻击者可以执行不想要的查询读取、修改、删除数据库中的数据。这通常发生在应用程序没有正确验证用户输入时。
  • 例如: 如果一个不安全的查询是这样构建的: SELECT * FROM users WHERE username='" + userInput + "' AND password='" + passwordInput + "'"; 攻击者可以输入"OR 1=1; -- "来返回所有的用户。

3. CSRF(跨站请求伪造):

  • 定义: 攻击者诱使受害者执行不知情的动作在一个web应用上,通常在受害者已经认证的情况下。

  • 例如: 如果受害者登录了一个银行网站,并且没有登出,攻击者可以诱使受害者访问一个恶意页面,这个页面包含一个到银行网站的请求,例如转账给攻击者。

  • 防护: 通常使用token,确保每个请求都是唯一和特定的。

    4 HTTP重放攻击

HTTPS 主要基于 SSL/TLS 协议,它包括一系列设计来防止重放攻击的机制。下面来解释为什么 HTTPS 可以防止重放攻击,以及为什么 HTTP 不能做到这一点:

  1. HTTPS 和重放攻击的防护:
    • 随机数: 在 TLS 握手过程中,客户端和服务器都会生成随机数。这些随机数用于建立会话密钥。即使攻击者截获了握手数据并尝试重放,由于随机数的存在(客户端第二次生成的随机数被公钥加密),他们无法正确地建立会话密钥。
    • 会话恢复与会话ID: 如果客户端和服务器决定重新使用之前的会话参数,他们会使用一个会话ID进行会话恢复。如果攻击者尝试使用截获的会话ID进行重放,他们会失败,因为服务器上与该ID关联的会话参数已经过期或无效。
    • 序列号: 在TLS中**,每个记录都有一个序列号。如果服务器收到一个已经看过的序列号,它会拒绝该记录,从而阻止了重放攻击**。
  2. HTTP 和重放攻击:
    • 无内置保护: HTTP 是一个明文协议,它没有为数据完整性、机密性或重放攻击提供内置的防护。因此,如果攻击者截获了一个 HTTP 请求,他们可以简单地再次发送它来进行重放攻击。
    • 不使用随机数或序列号: 与 HTTPS 不同,HTTP 没有在请求中包含随机数或序列号,这意味着重放攻击更加容易。

综上所述,HTTPS 提供了多种机制来防止重放攻击,而 HTTP 本身没有这样的保护。这也是许多网站和应用程序选择使用 HTTPS 而不是 HTTP 的原因之一,因为它为数据传输提供了额外的安全性。

黑客直接利用捕获的对称密钥完成重放不行嘛?

你提出了一个很好的问题。确实,如果黑客成功捕获了对称密钥,那么他们可以解密捕获的数据,但仅仅拥有对称密钥并不能直接使他们成功进行重放攻击,原因如下:

  1. 短暂的会话密钥:在TLS/SSL中使用的对称密钥(会话密钥)通常只存在于一个会话期间。每次握手都会生成一个新的会话密钥。所以,即使攻击者获取了密钥,它也只对那一特定会话有效。如果攻击者想在新会话中进行重放攻击,他们需要获得新会话的密钥。

  2. 序列号和时效性:如前所述,TLS中的每个记录都有一个序列号。服务器会跟踪这些序列号以检测重放攻击。即使攻击者有对称密钥并尝试重放某个记录,服务器会因为序列号问题而拒绝这个记录。

  3. 完整性检查:TLS不仅仅是加密,它还提供了数据完整性检查。每个消息都伴随着一个校验值(如HMAC)。攻击者在不被检测的情况下无法修改这些消息。

  4. PFS(Perfect Forward Secrecy):许多现代的TLS配置使用完美的前向保密。这意味着,即使长期的私钥(或其他会话的密钥)被泄露,也不会威胁到其他会话的安全性。每个会话都有一个独特的、不依赖于其他会话的密钥。

当然,如果攻击者在会话期间捕获了密钥并立即尝试重放,理论上这是可能的,但他们只有很短的时间窗口可以这样做,并且需要在网络上有相当高的位置和能力。而且,现代的安全配置和措施(如上述的PFS)使得这种类型的攻击在实践中变得非常困难。

总的来说,仅仅拥有对称密钥并不足以进行成功的重放攻击,但这当然增加了攻击者的能力,这也强调了密钥管理和保护的重要性。

3.6 详细讲解一下SYN洪泛攻击

SYN洪泛攻击是一种拒绝服务攻击,攻击者通过向目标发送大量伪造的TCP SYN请求,导致目标系统耗尽资源。

流程如下:

  1. 攻击者发送大量伪造的SYN请求到目标系统。
  2. 目标系统为每个SYN请求分配资源,然后发送SYN-ACK响应。
  3. 攻击者不发送ACK报文,或者发送的源地址是伪造的,所以目标系统收不到。
  4. 这导致目标系统的资源(如半连接队列)被大量未完成的连接占用,正常的用户无法建立新的连接。

3.7 如何解决SYN的洪泛攻击

  1. SYN Cookies:不为半连接分配资源,而是基于SYN请求计算一个cookie并发送SYN-ACK。只有在收到客户端的ACK报文时,服务器才为连接分配资源。
  2. 限制半连接的数量:设置半连接队列的大小,当达到限制时,新的连接请求可能会被忽略。
  3. 使用防火墙或IDS:检测异常的SYN请求流量并屏蔽相关IP。
  4. 增加系统的可用资源:如增加更多的内存和CPU来处理新的连接请求。

3.8 HTTP的各个版本之间的差别

HTTP 2.0 和 HTTP 1.1 相比有哪些优势呢?

4 java-操作系统

4.1 讲一下jvm有哪些gc算法和收集器

讲了g1和jvm的区别

4.2 讲一下jmm

内存屏障、MESI、volatile,

Java内存模型(JMM,Java Memory Model)是Java虚拟机规范中定义的一个关于计算机内存系统的抽象模型。它描述了如何和何时不同的线程可以看到其他线程修改后的共享变量的值,以及如何同步对共享变量的访问。以下是JMM的核心概念和关键部分:

1. 主内存与工作内存

  • 主内存(Main Memory):保存共享变量的内存区域。
  • 工作内存(Working Memory):保存线程使用的变量的内存区域。每个线程都有自己独立的工作内存。

2. 内存间的交互操作

JMM定义了以下几种操作来控制主内存和工作内存之间的交互:

  • lock(锁定)
  • unlock(解锁)
  • read(读取)
  • load(载入)
  • use(使用)
  • assign(赋值)
  • store(存储)
  • write(写入)

3. 内存屏障(Memory Barrier)

  • 也被称为内存栅栏,是一组指令,用于在指定类型的操作之前或之后插入一种排序约束。
  • 内存屏障可以确保特定的内存读/写操作的顺序,使得这些操作不被重排序。

4. MESI

  • MESI是一个用于描述多核CPU中各核之间如何同步对共享数据的访问的协议。
  • MESI代表四种缓存行状态:Modified(已修改)Exclusive(独占)Shared(共享)和Invalid(无效)。
  • MESI协议确保了在多个CPU核心之间保持内存的一致性。

5. volatile关键字

  • volatile是Java提供的一个轻量级的同步机制。
  • 当一个变量被声明为volatile时,JMM确保所有对这个变量的读写都直接从主内存进行。
  • 使用volatile可以确保变量的可见性和部分的有序性,但不保证原子性。

总结

Java内存模型是为了解决多线程环境下由于各种硬件和编译器优化导致的不可预测行为。JMM通过定义内存和线程之间的交互,为程序员提供了一个更简单、更一致的抽象视图,从而在多线程环境下编写正确、高效的程序。

6 对于i++这种自增操作,如果我们将其分解在Java内存模型(JMM)的上下文中,可以涉及到以下几个步骤:

  1. read(读取): 从主内存读取i的值到工作内存。
  2. load(载入): 将从主内存读取到的值加载到CPU的寄存器或其他高速缓存中。
  3. use(使用): 使用寄存器中的i的值执行加法操作。
  4. assign(赋值): 将加法操作后的新值赋给工作内存中的i
  5. store(存储): 将工作内存中i的新值存储到CPU的寄存器或其他高速缓存中。
  6. write(写入): 将新值从工作内存写回到主内存。

请注意,上述步骤是在没有其他优化或特定实现细节的情况下的通用步骤。实际上,由于编译器优化、CPU指令重排等,这些步骤可能会有所不同或以不同的顺序执行。

4.3 final关键字是如何保证线程安全的呢?

final关键字本身并不直接提供线程安全性。但当用于变量时,它确保了变量的引用不会被修改(也就是说变量引用的对象地址不会改变)。这样,确保了对象的不变性,从而有助于线程安全。

  1. 不变性: 当对象创建后其状态不再改变,该对象就是线程安全的。使用final关键字声明的变量必须在构造函数完成时被初始化,并且在后面不能被修改,这使得final变量能够安全地被多个线程访问而不需要同步。

  2. 发布对象: 当一个对象被不安全地发布时,它的引用可能会被多个线程同时修改,导致不可预测的行为。但如果该对象的所有引用都是final的,这种情况就不会发生。

4.3.1 为什么final修饰的方法不可被重写,修饰的类,不可被继承,为什么这么设计?

  1. 确保行为不变: 通过使方法不可被重写,final确保了类的某些行为永远不会改变。这对于设计某些核心逻辑或特定算法的类特别重要,因为允许子类重写这些方法可能会破坏这些逻辑或算法。

  2. 防止继承: 对于一些类,设计者可能不希望它们被继承,这可能是因为继承会带来额外的复杂性、安全风险或其他问题。final关键字提供了一种机制,确保类不会被其他开发者误用或不当地继承

4.3.2 String 的char数组被final修饰,为什么要这样?

  1. 不变性: String在Java中是不可变的,这意味着一旦创建了一个String对象,它的内容就不能改变。这种不变性是通过在内部使用final关键字来声明字符数组实现的。不可变性为String提供了一些优势,如缓存、线程安全和安全性。

  2. 安全性: 由于String经常用于各种Java安全功能(如类加载器、权限等),所以确保它是不可变的非常重要。如果String是可变的,恶意代码可能会更改其内容,从而导致安全漏洞。

  3. 性能: 由于String是不可变的,JVM可以在运行时缓存String对象。这在某些场景下可以提高性能,例如使用String池。

4.3.3 String 的char数组被final修饰,其引用是不可变的,但是数组中的内容还是可变的啊?

您是对的。String对象内部的char数组被声明为final,确保了数组引用本身不会指向其他数组,但这并不阻止我们更改该数组的内容。但在实际的String类的设计中,Java不提供任何公共方法来修改这个char数组的内容。这确保了String的不变性。

重要的是,这个设计是String类的内部细节。作为外部使用者,我们不应该、也不能试图更改这个数组的内容。尽管通过反射可能能够达到这个目的,但这样做会破坏String的设计意图和不变性,并可能导致许多预期外的问题。

所以,总的来说,String的不变性不仅仅是因为其内部char数组是final的,而是由于它的整体设计决定的,这包括不提供更改内部数组的方法。

4.4 g1的垃圾收集阶段

4.5 g1在最终标记阶段如何识别变动的对象呢?

5 rpc框架

5.1 说一说你的rpc框架的调用流程

基础:消费端和服务端必须共享同一个版本的sdk,否则可能会出错

调用链路:

5.2 netty是怎么实现channel的复用的

5.2.1 Netty的Channel复用与HTTP的Keep-Alive:

当我们说HTTP基于TCP的复用,通常我们指的是HTTP的Keep-Alive机制。在传统的HTTP/1.0中,默认的行为是每次完成一个请求/响应对后关闭TCP连接。但随后为了优化性能和减少连接建立/断开的开销,引入了Keep-Alive机制,在HTTP/1.1中,默认启用了Keep-Alive,允许在同一个TCP连接上完成多个HTTP请求/响应对。Netty的Channel复用指的是在整个应用的生命周期中,复用建立的TCP连接。Netty通过维护连接池来避免频繁地建立和断开连接,从而实现复用。所以,虽然这两者在核心都是复用TCP连接来减少开销,但实现细节和上下文有所不同。HTTP的Keep-Alive是在协议层面的优化,而Netty的Channel复用更多地涉及到框架和应用层的优化。

5.2.2 Netty如何实现Channel的复用:

  • 连接池: Netty可以使用连接池来复用连接。一旦连接被建立并且当前没有被使用,它可以被放入连接池中。当新的请求到达并需要一个连接时,可以直接从连接池中取出一个已存在的连接,从而避免重新建立连接的开销。

  • EventLoop: Netty中有一个核心组件叫做EventLoop,它负责处理I/O事件,如接受新连接、读/写数据等。每个EventLoop可以关联多个Channel,并且所有这些Channel共享同一个线程。这种设计保证了同一Channel上的所有I/O操作都是由同一个线程顺序执行的,从而避免了多线程同步的开销。这也是一种Channel复用的方式,因为多个Channel共享一个EventLoop

  • ChannelPipeline: 当数据在Netty中流动时,它会经过一个叫做ChannelPipeline的处理链。这个处理链由多个ChannelHandler组成。当一个Channel被复用时,其关联的ChannelPipeline也可以被复用,从而减少了重新构建处理链的开销。

总之,Netty通过多种方式来实现Channel的复用,从而优化性能和减少资源使用。

5.2.3 连接池: Netty可以使用连接池来复用连接。一旦连接被建立并且当前没有被使用,它可以被放入连接池中。为什么连接没有被长时间使用,需要放入连接池中?

在讨论为什么需要连接池以及为什么将未被使用的连接放入连接池之前,我们首先要明确连接池的核心目标:提高资源使用效率,并降低创建和销毁连接的开销。

  1. 创建与销毁连接的开销:创建新的连接,特别是TCP连接,需要时间和系统资源。这涉及到三次握手、TCP参数的协商等步骤。同样地,关闭连接也需要时间,并可能导致TIME_WAIT状态,暂时占用系统资源。频繁的创建和断开连接会导致系统资源的浪费和性能下降。

  2. 连接复用的优势:与其每次都创建一个新的连接,不如复用一个已经存在的连接。这样,可以直接使用这个连接,避免了新建连接的时间延迟。

  3. 为什么将未被长时间使用的连接放入连接池

    • 即时可用性:将未使用的连接放入连接池意味着这些连接仍然是活跃的并且可以立即被再次使用,无需经历连接建立的延迟。
    • 资源管理:维护连接的存活会消耗资源,但与频繁创建和销毁连接相比,这种开销是较小的。连接池通常有大小限制,超出该限制的空闲连接会被关闭,以确保不会浪费太多资源。
    • 预防频繁的连接建立/断开:有些应用场景可能存在突发的请求增加。如果在低流量时期关闭了所有空闲连接,然后在高流量时期突然需要大量新的连接,这将导致性能瓶颈。连接池可以缓解这种情况,因为它允许快速响应这种流量变化。

总的来说,连接池是为了提高性能和资源使用效率而设计的。将未被长时间使用的连接放入连接池可以确保在需要时能够快速响应,而不是每次都经历创建新连接的开销。

5.3 讲一讲你的方案中是怎么解决粘包和拆包问题的,自定义协议长什么样子?

6 编程

6.1 25. K 个一组翻转链表

6.2 92. 反转链表 II

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值