最近帮团队整理了一套面向中高级开发的面试题库,主要覆盖多线程、高并发、物联网和Spring架构四大技术板块。这些题目不是网上随手搜来的八股文,而是结合我们实际业务场景中遇到的真实问题提炼而成。比如物联网设备高频上报数据时的并发处理、Spring Cloud微服务在流量激增时的稳定性保障等,都是血泪教训换来的经验。
这套题特别适合考察3-5年经验的候选人,能快速验证其是否具备复杂场景下的实战能力。举个例子,单纯问"synchronized原理"只能算基础题,但如果让候选人设计一个物联网设备指令下发的线程安全方案,就能看出他是否真正理解锁的应用场景。
在实际业务中,我总结出线程安全防护的三个层级:
踩坑记录:曾经在设备心跳检测服务里错误使用了synchronized,导致万级设备同时上线时出现线程饥饿。后来改用ReentrantReadWriteLock才解决。
面试必问的ThreadPoolExecutor构造参数,我习惯用餐厅来类比解释:
java复制// 物联网设备数据处理的最佳实践配置
ThreadPoolExecutor deviceThreadPool = new ThreadPoolExecutor(
4, // 常驻线程数=CPU核心数
16, // 突发流量时最大扩展
60, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1000), // 缓冲队列
new NamedThreadFactory("IoT-Worker"),
new ThreadPoolExecutor.CallerRunsPolicy() // 饱和时由调用线程处理
);
在智慧园区项目中经历过严重的缓存雪崩,总结出这些实战经验:
java复制// Caffeine本地缓存配置示例
LoadingCache<String, DeviceInfo> localCache = Caffeine.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.maximumSize(1000)
.refreshAfterWrite(1, TimeUnit.MINUTES)
.build(key -> queryFromRedis(key));
针对物联网场景的特殊需求,不同分布式锁方案的对比:
| 方案 | 实现原理 | 适用场景 | 注意事项 |
|---|---|---|---|
| Redis SETNX | 键值过期机制 | 短时锁(<10s) | 注意时钟漂移问题 |
| ZooKeeper | 临时顺序节点 | 长时锁(>30s) | 要处理连接断开 |
| RedLock | 多Redis实例投票 | 高可靠性要求 | 性能损耗较大 |
| 数据库乐观锁 | version字段 | 低频修改场景 | 重试机制要完善 |
真实案例:智能门锁的远程开锁指令必须使用RedLock,普通Redis锁在Master切换时可能导致重复开锁。
物联网项目中最容易出错的消息可靠性配置:
python复制# Paho-MQTT客户端示例
client.publish("device/001/cmd", payload="reboot", qos=1, retain=False)
处理过10万+设备在线的系统,总结出这些经验值:
在Spring Boot自动配置中遇到的典型问题:
@PostConstruct方法里调用其他Bean可能遇到NPE@Async方法不能在初始化阶段调用@Transactional在同类方法调用时不生效java复制// 正确的Bean初始化方式
@Configuration
public class DeviceConfig {
@Autowired
private RedisTemplate redisTemplate;
@PostConstruct
public void init() {
// 改为监听事件方式避免时序问题
ApplicationEventPublisher.publishEvent(new CacheInitEvent(this));
}
}
基于Sleuth+Zipkin的实际配置要点:
yaml复制# application.yml关键配置
spring:
sleuth:
sampler:
probability: 0.1
propagation-keys: deviceId,userId
zipkin:
base-url: http://zipkin:9411
通过Jstack分析发现的典型问题:
newFixedThreadPool导致队列积压@Async默认不配置线程池大小java复制// 正确的异步任务配置
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(8);
executor.setMaxPoolSize(32);
executor.setQueueCapacity(1000);
executor.setThreadNamePrefix("Async-");
executor.initialize();
return executor;
}
}
经过压测验证的连接池计算公式:
properties复制# 推荐的生产环境配置
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.connection-timeout=3000
spring.datasource.hikari.idle-timeout=600000
通过调试Spring源码总结的三级缓存机制:
java复制// 模拟Spring解决循环依赖的关键代码
public class DefaultSingletonBeanRegistry {
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); // 一级缓存
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); // 二级缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); // 三级缓存
protected Object getSingleton(String beanName) {
// 实际查找顺序:1→2→3
}
}
在物联网网关开发中遇到的真实案例:
java复制// Netty管道配置示例
pipeline.addLast(new LengthFieldBasedFrameDecoder(
1024 * 1024, // maxFrameLength
0, // lengthFieldOffset
4, // lengthFieldLength
0, // lengthAdjustment
4 // initialBytesToStrip
));
pipeline.addLast(new DeviceProtocolDecoder());
结合物联网设备抢购场景的特别设计:
lua复制-- 库存扣减Lua脚本
local stock = tonumber(redis.call('GET', KEYS[1]))
if stock > 0 then
redis.call('DECR', KEYS[1])
return 1 -- 成功
end
return 0 -- 失败
针对物联网跨服务操作的方案对比:
| 方案 | 一致性级别 | 性能影响 | 适用场景 |
|---|---|---|---|
| 本地消息表 | 最终一致 | 低 | 异步通知类业务 |
| TCC | 强一致 | 高 | 资金交易类业务 |
| SAGA | 最终一致 | 中 | 长流程业务 |
| Seata AT模式 | 弱一致 | 中 | 简单CRUD操作 |
真实踩坑:设备激活流程最初用本地消息表,后来因为状态同步延迟改为TCC模式,虽然开发成本高但保证了实时性。
某次线上OOM的排查记录:
jmap -histo:live pid 发现DeviceSession对象异常增长java复制// 修复后的缓存实现
Cache<String, DeviceSession> cache = CacheBuilder.newBuilder()
.maximumSize(10000)
.weakValues()
.expireAfterAccess(30, TimeUnit.MINUTES)
.build();
使用JStack检测死锁的标准流程:
jstack pid > thread_dump.logsynchronized和ReentrantLock混合使用的情况text复制// 典型死锁线程栈示例
"Thread-1" #12 prio=5 os_prio=0 tid=0x00007f48740f7000 nid=0x5e1f waiting for monitor entry [0x00007f486b7f6000]
java.lang.Thread.State: BLOCKED (on object monitor at com.example.DeviceManager.lock(DeviceManager.java:42))
- waiting to lock <0x000000076e9b8d00> (a java.lang.Object)
- locked <0x000000076e9b8d10> (a java.lang.Object)
"Thread-2" #13 prio=5 os_prio=0 tid=0x00007f48740f8800 nid=0x5e20 waiting for monitor entry [0x00007f486b6f5000]
java.lang.Thread.State: BLOCKED (on object monitor at com.example.DeviceManager.unlock(DeviceManager.java:58))
- waiting to lock <0x000000076e9b8d10> (a java.lang.Object)
- locked <0x000000076e9b8d00> (a java.lang.Object)
设备管理模块的领域划分经验:
java复制// 领域模型示例
public class Device extends AggregateRoot {
private DeviceId id;
private DeviceStatus status;
private GeoLocation location;
public void updateLocation(GeoLocation newLocation) {
this.location = newLocation;
addDomainEvent(new DeviceLocationChangedEvent(this));
}
}
针对设备状态流转的优雅实现:
java复制// 状态接口
public interface DeviceState {
void activate(DeviceContext context);
void deactivate(DeviceContext context);
}
// 具体状态实现
public class ActiveState implements DeviceState {
@Override
public void deactivate(DeviceContext context) {
context.setState(new InactiveState());
// 触发下线逻辑...
}
}
// 上下文类
public class DeviceContext {
private DeviceState currentState;
public void transitionTo(DeviceState newState) {
this.currentState = newState;
}
}
对比传统HTTP的特性差异:
java复制// RSocket服务端示例
RSocketServer.create()
.acceptor((setup, sendingSocket) -> Mono.just(
new AbstractRSocket() {
@Override
public Mono<Payload> requestResponse(Payload payload) {
// 处理设备请求...
}
}))
.bind(TcpServerTransport.create(7878))
.block();
Istio在物联网边缘计算中的应用要点:
yaml复制# Istio VirtualService示例
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: device-service
spec:
hosts:
- devices.example.com
http:
- route:
- destination:
host: device-service
subset: v1
timeout: 10s
retries:
attempts: 3
retryOn: gateway-error,connect-failure
设计白板题时的评分要点:
模拟线上事故的考察流程:
面试技巧:我会故意提供不完整的错误信息,观察候选人如何追问和排查,这比直接问"CPU100%怎么办"更能考察实战能力。
在Code Review时必查的雷区:
java复制// 典型问题代码示例
public class DeviceCounter {
private volatile int count; // volatile不能保证++原子性
public void add() {
synchronized(this) {
externalService.call(); // 可能发生死锁
count++;
}
}
}
通过数百次Code Review总结的经验:
@Transactional注解在private方法上无效@Async不配置自定义线程池的风险@Cacheable在同类调用时不生效@Scheduled单线程执行可能阻塞@RestControllerAdvice未处理特定异常java复制// 正确的缓存配置示例
@Cacheable(value = "devices", key = "#deviceId", unless = "#result == null")
public DeviceInfo getDevice(String deviceId) {
// 查询实现...
}
针对物联网网关的推荐配置:
bash复制# 启动参数示例
java -Xms4g -Xmx4g -Xmn1g \
-XX:+UseG1GC -XX:MaxGCPauseMillis=200 \
-Xloggc:/logs/gc.log -XX:+UseGCLogFileRotation \
-XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=10M \
-jar iot-gateway.jar
在千万级设备管理系统中的实践经验:
where id > ? limit ?替代limit ?,?sql复制-- 优化前后的分页对比
/* 低效写法 */
SELECT * FROM device_history ORDER BY id LIMIT 1000000, 10;
/* 高效写法 */
SELECT * FROM device_history WHERE id > 1000000 ORDER BY id LIMIT 10;
物联网系统必须监控的核心指标:
在线设备数/注册设备数消息数/s按Topic分类下发到响应时间百分位统计失败请求数/总请求数prometheus复制# Prometheus告警规则示例
- alert: HighDeviceOfflineRate
expr: sum(device_online_status{status="offline"}) by (region) / sum(device_online_status) by (region) > 0.1
for: 5m
labels:
severity: critical
annotations:
summary: "高设备离线率 ({{ $value }}%)"
ELK架构下的关键配置:
yaml复制# Filebeat多行配置示例
multiline.pattern: '^\[[0-9]{4}-[0-9]{2}-[0-9]{2}'
multiline.negate: true
multiline.match: after
物联网安全架构设计原则:
java复制// 消息签名验证示例
public boolean verifySignature(DeviceMessage message) {
String computed = HmacUtils.hmacSha256Hex(deviceSecret, message.getBody());
return computed.equals(message.getSignature());
}
针对物联网的特定安全措施:
| 攻击类型 | 防御方案 | 实施要点 |
|---|---|---|
| 重放攻击 | 时间戳+Nonce校验 | 时间窗口控制在±5分钟 |
| DDoS | 设备行为分析+速率限制 | 基于设备ID的令牌桶算法 |
| 固件篡改 | 安全启动+签名校验 | 使用HSM保护私钥 |
| 中间人攻击 | 证书绑定(Pinning) | 预置CA证书到设备安全区域 |
物联网系统的测试金字塔实践:
yaml复制# Jenkins流水线片段
stages {
stage('Test') {
steps {
sh 'mvn test'
sh 'k6 run --vus 100 --duration 30m smoke-test.js'
}
}
}
设备固件的分批次更新策略:
json复制// 设备分组策略配置示例
{
"rolloutPhases": [
{
"percentage": 1,
"selector": {"labels": {"env":"test"}}
},
{
"percentage": 10,
"selector": {"region": ["east","west"]}
}
]
}
某智能家居平台的重构经验:
plantuml复制@startuml
component "设备服务" as Device
component "用户服务" as User
component "消息网关" as Gateway
Device --> Gateway : 上报状态
Gateway --> User : 鉴权请求
User --> Device : 控制指令
@enduml
Istio在边缘计算场景的调优经验:
yaml复制# EnvoyFilter配置示例
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: device-metrics
spec:
configPatches:
- applyTo: HTTP_FILTER
match:
context: SIDECAR_OUTBOUND
patch:
operation: ADD
value:
name: envoy.lua
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
inlineCode: |
function envoy_on_response(response_handle)
local device_id = response_handle:headers():get("x-device-id")
if device_id then
stats:counter("device_requests_total"):inc(1)
end
end
经过多个物联网项目验证的Git工作流:
bash复制# 典型开发流程示例
git checkout -b feature/device-control
git commit -m "添加设备控制接口"
git fetch origin
git rebase origin/master
git push -f origin feature/device-control
架构设计文档的必备要素:
markdown复制# 设备注册流程设计
## 1. 上下文图
```plantuml
@startuml
actor 设备
participant "接入网关" as Gateway
participant "设备服务" as Service
participant "数据库" as DB
设备 -> Gateway: 注册请求
Gateway -> Service: 鉴权
Service -> DB: 持久化设备信息
@enduml
我培养团队架构师的两个核心方法:
源码调试法:带着问题读Spring/Netty源码
故障复现法:在测试环境模拟线上问题
如何在不做管理岗的情况下推动技术改进:
个人经验:我从写技术周报开始,逐渐建立起跨团队的影响力。关键是要提供可落地的具体建议,而不是空谈理念。