// 企业中间件选型矩阵(基于知识库[1][3][7])
public enum MiddlewareType {
TRANSACTIONAL("事务中间件", "TongESB", "处理分布式事务"),
MESSAGING("消息中间件", "RabbitMQ", "异步解耦"),
CACHE("缓存中间件", "Redis", "数据加速"),
LOAD_BALANCER("负载均衡", "Nginx", "流量分发"),
APPLICATION_SERVER("应用服务器", "东方通应用服务器", "容器化部署");
private final String description;
private final String example;
private final String useCase;
MiddlewareType(String desc, String ex, String use) {
this.description = desc;
this.example = ex;
this.useCase = use;
}
}
注释:
- 选型需结合功能性需求(如TPS)、非功能性需求(如高可用)
- 国产化替代:优先选择东方通、金蝶等信创认证产品
// 缓存击穿防护(知识库[10])
public class SafeRedisCache {
private final JedisPool jedisPool;
public SafeRedisCache(JedisPool pool) {
this.jedisPool = pool;
}
@Transactional
public String getWithMutex(String key) {
try (Jedis jedis = jedisPool.getResource()) {
// 1. 尝试获取互斥锁
String lockKey = "lock:" + key;
if (!jedis.setnx(lockKey, "1").equals(1L)) {
Thread.sleep(100); // 等待锁释放
return getWithMutex(key); // 递归重试
}
// 2. 设置锁过期时间(防死锁)
jedis.expire(lockKey, 10);
// 3. 尝试从Redis获取数据
String value = jedis.get(key);
if (value != null) {
return value;
}
// 4. 缓存未命中,从数据库加载
value = loadFromDB(key);
jedis.setex(key, 3600, value); // 设置逻辑过期时间
// 5. 释放锁
jedis.del(lockKey);
return value;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return null;
}
}
private String loadFromDB(String key) {
// 模拟数据库查询
return "DB_DATA_" + key;
}
}
注释:
- 击穿防护:通过互斥锁(Redis的
SETNX
)防止缓存重建期间的雪崩- 逻辑过期时间:结合数据库TTL实现数据一致性
// 生产者-消费者模式(知识库[9])
@Configuration
public class RabbitMQConfig {
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory factory = new CachingConnectionFactory("localhost");
factory.setUsername("guest");
factory.setPassword("guest");
return factory;
}
@Bean
public AmqpTemplate amqpTemplate(ConnectionFactory factory) {
return new RabbitTemplate(factory);
}
}
// 生产者
@Service
public class OrderProducer {
@Autowired
private AmqpTemplate rabbitTemplate;
public void sendOrder(String orderNo) {
rabbitTemplate.convertAndSend(
"order_exchange", // 交换机
"order.routing.key", // 路由键
orderNo,
message -> {
// 设置消息TTL(防积压)
message.getMessageProperties().setExpiration("10000"); // 10秒
return message;
});
}
}
// 消费者
@Component
public class OrderConsumer {
@RabbitListener(queues = "order_queue")
public void processOrder(@Payload String orderNo,
@Header(AmqpHeaders.CONSUMER_QUEUE) String queue) {
// 消息幂等性校验
if (isProcessed(orderNo)) {
return;
}
// 处理订单逻辑
System.out.println("Processing order: " + orderNo);
markAsProcessed(orderNo);
}
private boolean isProcessed(String orderNo) {
// 检查数据库或缓存
return false;
}
private void markAsProcessed(String orderNo) {
// 标记为已处理
}
}
注释:
- 消息幂等性:通过数据库唯一索引或分布式锁实现
- 消息重试:结合
x-death
头部实现死信队列
// Seata AT模式实现(知识库[6])
@Service
public class AccountService {
@Autowired
private AccountMapper accountMapper;
@Autowired
private OrderService orderService;
@GlobalTransactional(name = "transfer-tx", rollbackFor = Exception.class)
public void transfer(String fromUser, String toUser, BigDecimal amount) {
// 1. 扣减用户余额
accountMapper.debit(fromUser, amount);
// 2. 异步通知订单服务
try {
orderService.createOrder(fromUser, toUser, amount);
} catch (Exception e) {
throw new RuntimeException("订单创建失败,事务回滚");
}
// 3. 提交事务
System.out.println("分布式事务提交成功!");
}
}
// 配置文件:transactional-msg.yml
server:
port: 8091
spring:
application:
name: seata-account
datasource:
url: jdbc:mysql://localhost:3306/seata_account?useUnicode=true&characterEncoding=utf8
seata:
enabled: true
tx-service-group: my_test_tx_group
service:
vgroup-mapping:
my_test_tx_group: default
grouplist:
default: 127.0.0.1:8091
注释:
- AT模式:通过Undo Log实现自动回滚
- TC/TM/RM:需部署Seata控制台
// TongLINK/Q生产者(知识库[8])
public class TongLinkProducer {
private static final String TOPIC = "TOPIC_TEST";
private static final String GROUP = "GROUP_TEST";
public void sendMessage(String message) {
try {
// 1. 创建连接
Connection connection = new Connection();
connection.connect("localhost", 8001);
// 2. 发送消息
connection.send(
new Message(message.getBytes()),
TOPIC,
GROUP,
0, // 优先级
0 // 消息ID
);
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 消费者
public class TongLinkConsumer implements MessageListener {
public void onMessage(Message msg) {
System.out.println("Received message: " + new String(msg.getBody()));
}
public static void main(String[] args) {
try {
Connection connection = new Connection();
connection.connect("localhost", 8001);
connection.subscribe(TOPIC, GROUP, new TongLinkConsumer());
} catch (Exception e) {
e.printStackTrace();
}
}
}
注释:
- 国产化替代:需配置TLS加密和国密算法
- 性能优势:支持百万级TPS
<route id="orderRoute">
<from uri="direct:start"/>
<to uri="log:incoming?level=INFO"/>
<choice>
<when>
<simple>${header.type} == 'CREATE'simple>
<to uri="bean:orderService?method=createOrder"/>
when>
<otherwise>
<to uri="bean:orderService?method=updateOrder"/>
otherwise>
choice>
route>
注释:
- SOA架构:支持REST、SOAP、MQTT多种协议
- 监控集成:与Prometheus/Grafana无缝对接
// Spring Security集成(知识库[2])
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/public/**").permitAll()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.httpBasic()
.and()
.csrf().disable() // 生产环境需启用
.sessionManagement()
.maximumSessions(1) // 会话限制
.expiredUrl("/login?expired");
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(); // 密码哈希
}
}
注释:
- RBAC模型:基于角色的访问控制
- 防XXE:在XML解析时禁用实体扩展
// MyBatis分页优化(知识库[11])
public class PageHelperExample {
@Autowired
private UserMapper userMapper;
public List<User> getUsers(int pageNum, int pageSize) {
PageHelper.startPage(pageNum, pageSize);
List<User> users = userMapper.selectAll();
PageInfo<User> pageInfo = new PageInfo<>(users);
System.out.println("Total: " + pageInfo.getTotal());
return users;
}
}
// Redis集群配置
@Configuration
public class RedisClusterConfig {
@Bean
public JedisConnectionFactory jedisConnectionFactory() {
RedisClusterConfiguration config = new RedisClusterConfiguration();
config.addClusterNode(new RedisNode("192.168.1.1", 7000));
config.addClusterNode(new RedisNode("192.168.1.2", 7001));
return new JedisConnectionFactory(config);
}
}
注释:
- 分页查询:避免全表扫描
- 集群分片:通过Redis Cluster实现横向扩展
注释:
- 限流降级:Sentinel实现QPS限流
- 熔断机制:Hystrix保护下游服务
场景 | 并发数 | TPS | 响应时间(p99) | 错误率 |
---|---|---|---|---|
基础架构 | 500 | 800 | 500ms | 0.2% |
+Redis缓存 | 1000 | 1500 | 200ms | 0.1% |
+消息队列异步化 | 2000 | 2800 | 150ms | 0.05% |
全链路压测(国产化) | 5000 | 4200 | 120ms | 0.01% |
// 集群健康检查脚本
public class RedisHealthChecker {
public static void main(String[] args) {
JedisCluster cluster = new JedisCluster(getClusterNodes());
try {
cluster.ping();
System.out.println("Cluster is healthy!");
} catch (JedisConnectionException e) {
System.err.println("Cluster is unreachable!");
// 触发自动修复流程
} finally {
cluster.close();
}
}
private static List<HostAndPort> getClusterNodes() {
return Arrays.asList(
new HostAndPort("192.168.1.1", 7000),
new HostAndPort("192.168.1.2", 7001)
);
}
}
注释:
- 哨兵模式:推荐使用Redis Sentinel自动切换
// 消息幂等性实现
public class IdempotentConsumer {
private final RedisTemplate<String, String> redisTemplate;
public void processMessage(String messageId, String payload) {
if (redisTemplate.opsForValue().setIfAbsent(messageId, "processed", 24, TimeUnit.HOURS)) {
// 处理业务逻辑
System.out.println("Processing: " + payload);
} else {
System.out.println("Duplicate message ignored: " + messageId);
}
}
}
注释:
- 唯一ID:消息需携带全局唯一ID
// Prometheus+Grafana集成
@Configuration
public class MetricsConfig {
@Bean
public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
return registry -> registry.config().commonTags("application", "middleware-demo");
}
@Bean
public Exporter prometheusExporter() {
return PrometheusMeterRegistry.builder()
.publishPercentiles(0.5, 0.95)
.build();
}
}
// Grafana面板示例(JSON片段)
{
"title": "Redis Cluster Metrics",
"type": "graph",
"targets": [
{
"expr": "redis_connected_clients",
"legendFormat": "Connected Clients"
}
],
"yaxes": [
{ "label": "Clients" },
{ "label": "Throughput" }
]
}
注释:
- APM工具:推荐SkyWalking+Zipkin全链路追踪
通过本文,你已掌握:
终极彩蛋代码:
// 中间件熔断器(全栈防护) @Component public class MiddlewareCircuitBreaker { @Autowired private CircuitBreakerRegistry registry;
public
T executeWithCircuitBreaker( String serviceId, Callable command, T fallbackValue) { CircuitBreaker circuitBreaker = registry.circuitBreaker(serviceId); return circuitBreaker.run( command, throwable -> { System.err.println("Service " + serviceId + " failed: " + throwable.getMessage()); return fallbackValue; }); } }