软件架构师的面试通常会被问到哪些问题

最近,我参加了一家领先的服务型公司的软件架构师(Java)职位的面试。我在这里分享了一些面试官问我的问题。我只列出了与 Java 相关的问题,因为本文主要关注 Java。面试官问我有关 AWS、Docker、Kubernetes、Kafka、Elastic Search、SQL/NoSQL 和设计模式的问题。

1.ClassNotFoundException 和 NoClassDefFoundError 有什么区别?

当您尝试在运行时使用 Class.forName() 或 loadClass() 方法加载类,但请求的类在类路径中未找到时,会发生 ClassNotFoundException。当您在类路径上没有相应的 Jar 时,会发生此错误。这是一个已检查异常。

NoClassDefFoundError 发生在编译时类存在且程序编译成功但运行时类不存在时。这是一个错误。可能编译了你的项目然后删除了其中一个 .class 文件。它将给出 NoClassDefFoundError。

2. Java 中创建线程有哪些不同的方法?

创建线程有多种方式——使用 Runnable 或 Callable 接口、扩展 Thread 类、使用 Executor 框架/线程池。面试官进一步询问是否有其他方式创建线程?答案是使用 Reactive 编程。我们可以使用 Spring Web Flux 库并实现响应式代码。如果您知道任何其他创建线程的方法,请在评论中分享。

3. 解释不同类型的加密?

加密基本上有两种类型。对称加密——单密钥用于加密和解密。当您可以在发送者和接收者之间安全地共享密钥时使用。当您想要加密大量数据、加密静态数据时,使用对称加密。常见的对称加密方法——AES、DES

非对称加密:使用两个不同的密钥——私钥和公钥。使用公钥加密的数据只能用相应的私钥解密。网站公开提供的 SSL/TLS 证书包含公钥。常见的非对称加密方法——RCA

4.ConcurrentHashMap与HashMap有何不同?

ConcurrentHashMap 将映射划分为多个段,并且仅在写入时锁定特定段。因此,通过允许多个线程同时写入不同的段,可以实现更好的并发性。

ConcurrentHashMap 中的读取是非阻塞的,不需要锁定。这意味着多个线程可以安全地同时从映射中读取,而无需等待锁定,这显著提高了读取密集型场景的性能。易失性机制确保内存可见性,这意味着当一个线程写入一个值时,该值会立即对所有其他线程可见。这允许读取操作始终看到最新的值。

5. 当你在浏览器中打开一个 URL/网站时,请求经历了哪些步骤?请逐步解释。

这里给出非常简短的细节:

URL 解析
DNS 解析 — 从域名查找服务器地址
TLS 握手(如果是 HTTPS)→加密流量
发送 HTTP 请求
服务器处理请求→可能涉及应用程序负载均衡器、网关
接收 HTTP 响应
解析和呈现 HTML、CSS 和 JavaScript
获取其他资源(CSS、JS、图像)
向用户显示最终网页。

6.2PC 和 SAGA 设计模式有什么区别?

2PC 用于即时事务。您可以无缝地提交或回滚整个事务。如果所有各方都同意,则提交事务。如果任何一方不同意,则回滚事务。当给定场景中涉及的服务数量有限时,可以使用此方法。由于单点故障,它的容错能力较差。

相反,SAGA 模式可用于跨越许多不同服务的长期运行事务。这里每个动作都有一个补偿动作。例如 — 创建订单,补偿动作是 — 恢复订单。与 2PC 相比,它更具可扩展性和容错性,因为它不需要全局锁定。例如,有三个服务 — 订单 > 库存 > 付款。假设付款请求失败,那么它将恢复库存并恢复订单。它将交易分为多个步骤。

7 什么是CQRS设计模式。

CQRS(命令查询职责分离)是一种用于分离系统中的读写操作的设计模式。它将处理命令(更改应用程序状态的操作)的职责查询(检索数据而不修改数据的操作)的职责分开。

如何实现它取决于需求,这是一个非常主观的问题。例如 — 在命令服务端,将有创建产品、更新产品数量、更新产品价格、删除产品等事件。它将此事件发布到 Kafka。查询服务将使用这些事件,并拥有自己的存储(可能是 Elastic Search),并以所需的形式存储数据,这些形式是基于业务需求的查询。由于它是基于事件的,因此可以进行时间旅行并查看随时间发生了哪些变化。它还有助于轻松恢复更改。请参阅本文了解更多详细信息。

8. 分布式系统中使用了哪些不同的设计模式?

服务发现和注册、负载平衡、客户端负载平衡、断路器、API 网关、同步通信 (REST)、异步通信 (消息传递 — 例如 Kafka、ActiveMQ)、速率限制。您还应该了解每种设计模式,以便能够回答相关问题。

9. 我有一个 Employee 类,里面有 200 多个不同的字段。序列化此对象时,我只想序列化这 200 个字段中的 10 个字段。实现此目的的最佳方法是什么?

使用 Externalizable 接口。它提供了更多控制,我们可以在其中编写序列化逻辑。这里我们只需要序列化所需的 10 个字段。

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

public class Employee implements Externalizable {
    // 50 fields (for simplicity, we show only 6)
    private String name;
    private int age;
    private String department;
    private String address;
    private double salary;
    private String nonSerializedField; // Field not to be serialized

    // Constructors
    public Employee() {
        // No-arg constructor required by Externalizable
    }

    public Employee(String name, int age, String department, String address, double salary, String nonSerializedField) {
        this.name = name;
        this.age = age;
        this.department = department;
        this.address = address;
        this.salary = salary;
        this.nonSerializedField = nonSerializedField;
    }

    // Getter and Setter Methods
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getDepartment() {
        return department;
    }

    public String getAddress() {
        return address;
    }

    public double getSalary() {
        return salary;
    }

    public String getNonSerializedField() {
        return nonSerializedField;
    }

    // Externalizable methods
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        // Manually write only the 5 selected fields
        out.writeObject(name);
        out.writeInt(age);
        out.writeObject(department);
        out.writeObject(address);
        out.writeDouble(salary);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        // Manually read only the 5 selected fields
        name = (String) in.readObject();
        age = in.readInt();
        department = (String) in.readObject();
        address = (String) in.readObject();
        salary = in.readDouble();
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", department='" + department + '\'' +
                ", address='" + address + '\'' +
                ", salary=" + salary +
                ", nonSerializedField='" + nonSerializedField + '\'' +
                '}';
    }
}

10. 实施灾难恢复时应考虑哪些要点?

这是一个非常主观的问题。请浏览互联网上的不同文章。这里简要介绍一下。

确定关键指标:

  • 恢复点目标 (RPO):定义您可以承受丢失的数据量。它指的是上次数据备份与故障点之间的最大时间间隔(例如,如果 RPO 为 4 小时,则您愿意丢失 4 小时的数据)。
  • 恢复时间目标 (RTO):定义发生故障后需要多快恢复运营。例如,如果 RTO 为 2 小时,则系统必须在 2 小时内恢复正常运行。

定期备份/快照数据库。多个副本。不同的云提供商提供此类管理数据库服务。

将您的系统和数据分散到不同的地理区域,以确保即使自然灾害影响一个地区,另一个地区的服务仍然可用。

识别可能出现的重大故障并测试系统是否存在此类故障。

故障转移机制:

故障转移可确保如果一个系统或数据中心发生故障,另一个系统或数据中心可以接管并最大程度地减少停机时间。

  • 冷故障转移:备份系统保持离线状态,仅在发生故障时才上线。恢复过程需要时间,因为需要手动启动服务和系统。
  • 温故障转移:备份系统在启用最少服务的情况下运行,并准备通过一些人工干预快速接管。
  • 热故障转移:备份系统与主系统同时运行。故障转移自动且几乎即时发生。
  • 用例:主动-主动或主动-被动数据库复制、负载均衡器。

自动化和编排:

灾难恢复必须实现自动化,以最大限度地减少人工干预并缩短恢复时间。基础设施即代码 (IaC) 和编排平台等工具可确保您的灾难恢复流程自动触发。

  • 基础设施即代码 (IaC):使用 Terraform、CloudFormation 或 Ansible 等 IaC 工具来定义您的基础设施,以便在发生灾难时可以快速重新创建。
  • 自动故障转移测试:通过使用 AWS 故障注入模拟器等工具模拟故障,定期测试您的灾难恢复过程,以确保故障转移按预期工作。
  • 自动恢复手册:使用 Runbooks(AWS Systems Manager)等自动化平台或自定义脚本来自动执行故障转移、恢复和回滚操作。

11. 您将如何为您的项目构建现代 CICD 管道?

构建镜像:当新代码合并到目标分支时,我们可以使用 GitHub 操作来运行构建,此 GitHub 操作将自动启动一个作业,我们可以利用它构建 docker 镜像。

推送镜像:从 Github Action runner Job 将镜像推送到您的私有 Docker 存储库(例如 - AWS ECR)。

环境智能配置:Helm 模板用于根据参数化输入值动态生成 Kubernetes 清单文件。这样可以轻松为不同的环境(如开发、暂存和生产)自定义部署,而无需每次手动编辑配置文件。Helm 允许您对图表进行版本控制,从而更轻松地管理更改和回滚。

Argo CD:Argo CD 是一款使用 GitOps 方法管理 Kubernetes 应用程序的强大工具。它简化了部署流程,增强了可见性并提高了应用程序更新的可靠性。它还提供了漂亮的 UI,以便您可以查看各种组件的部署状态,甚至可以查看日志。

12.TCP 和 UDP 有什么区别?

TCP(传输控制协议)是一种面向连接的协议,它通过确保数据包按顺序传送、进行错误检查并在必要时重新传输来提供可靠的数据传输。这使得 TCP 速度较慢,但​​适用于对准确性至关重要的应用程序,例如文件传输(FTP)、电子邮件(SMTP)和网页浏览(HTTP)。

另一方面,UDP(用户数据报协议)是一种无连接协议,无需建立连接即可发送数据包,因此速度更快,但可靠性较低,因为它无法保证交付或顺序。UDP 非常适合那些对速度至关重要且可以接受少量数据丢失的应用程序,例如视频流、VoIP 和在线游戏。

我已经分享了面试中问我的主要技术问题。希望这能帮助你更好地准备下一次面试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肉三

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值