面试题答案
一键面试级联故障
- 设计场景:假设微服务A调用微服务B,微服务B调用微服务C。当微服务C出现故障(如拒绝所有请求)时,微服务B由于无法从C获取响应,进而导致微服务A也出现故障。
- Ruby代码实现:
- 在微服务C的Ruby代码中,可以在处理请求的方法前添加逻辑来模拟故障,例如:
class MicroserviceC def handle_request # 模拟故障,直接抛出异常 raise 'Simulated failure' end end
- 微服务B中调用C的部分,捕获C抛出的异常,例如:
class MicroserviceB def call_microservice_c begin microservice_c = MicroserviceC.new microservice_c.handle_request rescue => e # 这里可以选择继续抛出异常,导致级联故障 raise e end end end
- 验证影响:
- 监控微服务A、B、C的请求响应时间、错误率等指标。可以使用工具如Prometheus和Grafana来实时展示这些指标。如果级联故障发生,A和B的错误率会显著上升,响应时间会大幅增加。
- 保障生产环境最小影响:
- 在生产环境中,使用流量镜像技术,将一小部分流量(如1%)导向实验环境,在实验环境中触发级联故障,观察对这部分流量的影响,而不影响大部分正常流量。
依赖故障
- 设计场景:微服务依赖某个外部服务(如第三方API),模拟该外部服务不可用或响应异常缓慢的情况。
- Ruby代码实现:
- 使用Ruby的HTTP客户端库(如Faraday)时,可以添加中间件来模拟故障。例如:
require 'faraday' connection = Faraday.new(url: 'https://third - party - api.com') do |faraday| faraday.response :raise_error faraday.use(Faraday::Response::SimulateFailure, { error_rate: 0.5, # 50%的请求失败 delay: 5 # 5秒延迟 }) faraday.adapter Faraday.default_adapter end class Faraday::Response::SimulateFailure < Faraday::Response::Middleware def initialize(options = {}) @error_rate = options[:error_rate] @delay = options[:delay] end def on_complete(env) if rand < @error_rate raise 'Simulated external service failure' end sleep @delay if @delay end end
- 验证影响:
- 观察微服务的业务功能是否正常,如数据获取是否失败,业务流程是否中断。同样通过监控指标来查看微服务自身的错误率、响应时间等变化。
- 保障生产环境最小影响:
- 利用熔断器模式,当检测到外部服务故障达到一定阈值时,熔断器打开,微服务直接返回默认值或错误信息,避免大量无效请求。同时,在实验前进行充分的灰度发布,逐步扩大实验范围。
数据一致性故障
- 设计场景:在微服务通过消息队列向PostgreSQL存储数据时,模拟消息丢失或重复消费,导致数据不一致。
- Ruby代码实现:
- 消息丢失模拟:在向RabbitMQ发送消息时,故意不处理确认机制,例如:
require 'bunny' connection = Bunny.new connection.start channel = connection.create_channel queue = channel.queue('data - queue') message = 'Some data' # 不等待确认,模拟消息丢失 queue.publish(message, persistent: true)
- 消息重复消费模拟:在消费消息的代码中,不做幂等处理,例如:
consumer = queue.subscribe(block: true) do |delivery_info, properties, body| # 假设这里是向PostgreSQL插入数据的操作 ActiveRecord::Base.connection.execute("INSERT INTO some_table (data) VALUES ('#{body}')") end
- 验证影响:
- 通过数据库层面的一致性检查,例如使用数据库的约束条件(如唯一约束)来发现重复数据。对比数据库中的数据和通过消息队列发送的数据总量,判断是否有消息丢失。
- 保障生产环境最小影响:
- 在生产环境启用RabbitMQ的事务机制或publisher confirms来确保消息可靠发送。在消费端实现幂等性,例如在插入数据前先查询是否已存在,或者使用数据库的ON CONFLICT DO NOTHING语句。同时,在实验前对生产数据进行备份,以便在实验出现问题时快速恢复。