Java学习指南
  • Java 编程的逻辑
  • Java进阶
  • Java FrameWorks
  • 了解 USB Type-A,B,C 三大标准接口
  • 深入浅出DDD
  • 重构:改善既有代码的设计
  • 面试大纲
  • 云原生
    • 什么是无服务器(what is serverless)?
  • 博客
    • 深入分析Log4j 漏洞
  • 博客
    • Serverless之快速搭建Spring Boot应用
  • 博客
    • 使用 Prometheus + Grafana + Spring Boot Actuator 监控应用
  • 博客
    • 使用 Prometheus + Grafana 监控 MySQL
  • 博客
    • 使用Github Actions + Docker 部署Spring Boot应用
  • 博客
    • Redis分布式锁之Redisson的原理和实践
  • 博客
    • 数据库中的树结构应该怎样去设计
  • 学习&成长
    • 如何成为技术大牛
  • 开发工具
    • Git Commit Message Guidelines
  • 开发工具
    • git命名大全
  • 开发工具
    • Gradle vs Maven Comparison
  • 开发工具
    • Swagger2常用注解及其说明
  • 开发工具
    • 简明 VIM 练级攻略
  • 微服务
    • 十大微服务设计模式和原则
  • 微服务
    • 微服务下的身份认证和令牌管理
  • 微服务
    • 微服务坏味道之循环依赖
  • 设计模式
    • 设计模式 - JDK中的设计模式
  • 设计模式
    • 设计模式 - Java三种代理模式
  • 设计模式
    • 设计模式 - 六大设计原则
  • 设计模式
    • 设计模式 - 单例模式
  • 设计模式
    • 设计模式 - 命名模式
  • 设计模式
    • 设计模式 - 备忘录模式
  • 设计模式
    • 设计模式 - 概览
  • 设计模式
    • 设计模式 - 没用的设计模式
  • 质量&效率
    • Homebrew 替换国内镜像源
  • 质量&效率
    • 工作中如何做好技术积累
  • Java FrameWorks
    • Logback
      • 自定义 logback 日志过滤器
  • Java FrameWorks
    • Mybatis
      • MyBatis(十三) - 整合Spring
  • Java FrameWorks
    • Mybatis
      • MyBatis(十二) - 一些API
  • Java FrameWorks
    • Mybatis
      • Mybatis(一) - 概述
  • Java FrameWorks
    • Mybatis
      • Mybatis(七) - 结果集的封装与映射
  • Java FrameWorks
    • Mybatis
      • Mybatis(三) - mapper.xml及其加载机制
  • Java FrameWorks
    • Mybatis
      • Mybatis(九) - 事务
  • Java FrameWorks
    • Mybatis
      • Mybatis(二) - 全局配置文件及其加载机制
  • Java FrameWorks
    • Mybatis
      • Mybatis(五) - SqlSession执行流程
  • Java FrameWorks
    • Mybatis
      • Mybatis(八) - 缓存
  • Java FrameWorks
    • Mybatis
      • Mybatis(六) - 动态SQL的参数绑定与执行
  • Java FrameWorks
    • Mybatis
      • Mybatis(十) - 插件
  • Java FrameWorks
    • Mybatis
      • Mybatis(十一) - 日志
  • Java FrameWorks
    • Mybatis
      • Mybatis(四) - Mapper接口解析
  • Java FrameWorks
    • Netty
      • Netty 可靠性分析
  • Java FrameWorks
    • Netty
      • Netty - Netty 线程模型
  • Java FrameWorks
    • Netty
      • Netty堆外内存泄露排查盛宴
  • Java FrameWorks
    • Netty
      • Netty高级 - 高性能之道
  • Java FrameWorks
    • Shiro
      • Shiro + JWT + Spring Boot Restful 简易教程
  • Java FrameWorks
    • Shiro
      • 非常详尽的 Shiro 架构解析!
  • Java FrameWorks
    • Spring
      • Spring AOP 使用介绍,从前世到今生
  • Java FrameWorks
    • Spring
      • Spring AOP 源码解析
  • Java FrameWorks
    • Spring
      • Spring Event 实现原理
  • Java FrameWorks
    • Spring
      • Spring Events
  • Java FrameWorks
    • Spring
      • Spring IOC容器源码分析
  • Java FrameWorks
    • Spring
      • Spring Integration简介
  • Java FrameWorks
    • Spring
      • Spring MVC 框架中拦截器 Interceptor 的使用方法
  • Java FrameWorks
    • Spring
      • Spring bean 解析、注册、实例化流程源码剖析
  • Java FrameWorks
    • Spring
      • Spring validation中@NotNull、@NotEmpty、@NotBlank的区别
  • Java FrameWorks
    • Spring
      • Spring 如何解决循环依赖?
  • Java FrameWorks
    • Spring
      • Spring 异步实现原理与实战分享
  • Java FrameWorks
    • Spring
      • Spring中的“for update”问题
  • Java FrameWorks
    • Spring
      • Spring中的设计模式
  • Java FrameWorks
    • Spring
      • Spring事务失效的 8 大原因
  • Java FrameWorks
    • Spring
      • Spring事务管理详解
  • Java FrameWorks
    • Spring
      • Spring计时器StopWatch使用
  • Java FrameWorks
    • Spring
      • 详述 Spring MVC 框架中拦截器 Interceptor 的使用方法
  • Java FrameWorks
    • Spring
      • 透彻的掌握 Spring 中@transactional 的使用
  • Java
    • Java IO&NIO&AIO
      • Java IO - BIO 详解
  • Java
    • Java IO&NIO&AIO
      • Java NIO - IO多路复用详解
  • Java
    • Java IO&NIO&AIO
      • Java N(A)IO - Netty
  • Java
    • Java IO&NIO&AIO
      • Java IO - Unix IO模型
  • Java
    • Java IO&NIO&AIO
      • Java IO - 分类
  • Java
    • Java IO&NIO&AIO
      • Java NIO - 基础详解
  • Java
    • Java IO&NIO&AIO
      • Java IO - 常见类使用
  • Java
    • Java IO&NIO&AIO
      • Java AIO - 异步IO详解
  • Java
    • Java IO&NIO&AIO
      • Java IO概述
  • Java
    • Java IO&NIO&AIO
      • Java IO - 设计模式
  • Java
    • Java IO&NIO&AIO
      • Java NIO - 零拷贝实现
  • Java
    • Java JVM
      • JVM 优化经验总结
  • Java
    • Java JVM
      • JVM 内存结构
  • Java
    • Java JVM
      • JVM参数设置
  • Java
    • Java JVM
      • Java 内存模型
  • Java
    • Java JVM
      • 从实际案例聊聊Java应用的GC优化
  • Java
    • Java JVM
      • Java 垃圾回收器G1详解
  • Java
    • Java JVM
      • 垃圾回收器Shenandoah GC详解
  • Java
    • Java JVM
      • 垃圾回收器ZGC详解
  • Java
    • Java JVM
      • 垃圾回收基础
  • Java
    • Java JVM
      • 如何优化Java GC
  • Java
    • Java JVM
      • 类加载机制
  • Java
    • Java JVM
      • 类字节码详解
  • Java
    • Java 基础
      • Java hashCode() 和 equals()
  • Java
    • Java 基础
      • Java 基础 - Java native方法以及JNI实践
  • Java
    • Java 基础
      • Java serialVersionUID 有什么作用?
  • Java
    • Java 基础
      • Java 泛型的类型擦除
  • Java
    • Java 基础
      • Java 基础 - Unsafe类解析
  • Java
    • Java 基础
      • Difference Between Statement and PreparedStatement
  • Java
    • Java 基础
      • Java 基础 - SPI机制详解
  • Java
    • Java 基础
      • Java 基础 - final
  • Java
    • Java 基础
      • Java中static关键字详解
  • Java
    • Java 基础
      • 为什么说Java中只有值传递?
  • Java
    • Java 基础
      • Java 基础 - 即时编译器原理解析及实践
  • Java
    • Java 基础
      • Java 基础 - 反射
  • Java
    • Java 基础
      • Java多态的面试题
  • Java
    • Java 基础
      • Java 基础 - 异常机制详解
  • Java
    • Java 基础
      • 为什么要有抽象类?
  • Java
    • Java 基础
      • 接口的本质
  • Java
    • Java 基础
      • Java 基础 - 枚举
  • Java
    • Java 基础
      • Java 基础 - 泛型机制详解
  • Java
    • Java 基础
      • Java 基础 - 注解机制详解
  • Java
    • Java 基础
      • 为什么 String hashCode 方法选择数字31作为乘子
  • Java
    • Java 并发
      • Java 并发 - 14个Java并发容器
  • Java
    • Java 并发
      • Java 并发 - AQS
  • Java
    • Java 并发
      • Java 并发 - BlockingQueue
  • Java
    • Java 并发
      • Java 并发 - CAS
  • Java
    • Java 并发
      • Java 并发 - Condition接口
  • Java
    • Java 并发
      • Java 并发 - CopyOnWriteArrayList
  • Java
    • Java 并发
      • Java 并发 - CountDownLatch、CyclicBarrier和Phaser对比
  • Java
    • Java 并发
      • Java 并发 - Fork&Join框架
  • Java
    • Java 并发
      • Java 并发 - Java CompletableFuture 详解
  • Java
    • Java 并发
      • Java 并发 - Java 线程池
  • Java
    • Java 并发
      • Java 并发 - Lock接口
  • Java
    • Java 并发
      • Java 并发 - ReentrantLock
  • Java
    • Java 并发
      • Java 并发 - ReentrantReadWriteLock
  • Java
    • Java 并发
      • Java 并发 - Synchronized
  • Java
    • Java 并发
      • Java 并发 - ThreadLocal 内存泄漏问题
  • Java
    • Java 并发
      • Java 并发 - ThreadLocal
  • Java
    • Java 并发
      • Java 并发 - Volatile
  • Java
    • Java 并发
      • Java 并发 - 从ReentrantLock的实现看AQS的原理及应用
  • Java
    • Java 并发
      • Java 并发 - 公平锁和非公平锁
  • Java
    • Java 并发
      • Java 并发 - 内存模型
  • Java
    • Java 并发
      • Java 并发 - 原子类
  • Java
    • Java 并发
      • Java 并发 - 如何确保三个线程顺序执行?
  • Java
    • Java 并发
      • Java 并发 - 锁
  • Java
    • Java 的新特性
      • Java 10 新特性概述
  • Java
    • Java 的新特性
      • Java 11 新特性概述
  • Java
    • Java 的新特性
      • Java 12 新特性概述
  • Java
    • Java 的新特性
      • Java 13 新特性概述
  • Java
    • Java 的新特性
      • Java 14 新特性概述
  • Java
    • Java 的新特性
      • Java 15 新特性概述
  • Java
    • Java 的新特性
      • Java 8的新特性
  • Java
    • Java 的新特性
      • Java 9 新特性概述
  • Java
    • Java 调试排错
      • 调试排错 - Java Debug Interface(JDI)详解
  • Java
    • Java 调试排错
      • 调试排错 - CPU 100% 排查优化实践
  • Java
    • Java 调试排错
      • 调试排错 - Java Heap Dump分析
  • Java
    • Java 调试排错
      • 调试排错 - Java Thread Dump分析
  • Java
    • Java 调试排错
      • 调试排错 - Java动态调试技术原理
  • Java
    • Java 调试排错
      • 调试排错 - Java应用在线调试Arthas
  • Java
    • Java 调试排错
      • 调试排错 - Java问题排查:工具单
  • Java
    • Java 调试排错
      • 调试排错 - 内存溢出与内存泄漏
  • Java
    • Java 调试排错
      • 调试排错 - 在线分析GC日志的网站GCeasy
  • Java
    • Java 调试排错
      • 调试排错 - 常见的GC问题分析与解决
  • Java
    • Java 集合
      • Java 集合 - ArrayList
  • Java
    • Java 集合
      • Java 集合 - HashMap 和 ConcurrentHashMap
  • Java
    • Java 集合
      • Java 集合 - HashMap的死循环问题
  • Java
    • Java 集合
      • Java 集合 - LinkedHashSet&Map
  • Java
    • Java 集合
      • Java 集合 - LinkedList
  • Java
    • Java 集合
      • Java 集合 - PriorityQueue
  • Java
    • Java 集合
      • Java 集合 - Stack & Queue
  • Java
    • Java 集合
      • Java 集合 - TreeSet & TreeMap
  • Java
    • Java 集合
      • Java 集合 - WeakHashMap
  • Java
    • Java 集合
      • Java 集合 - 为什么HashMap的容量是2的幂次方
  • Java
    • Java 集合
      • Java 集合 - 概览
  • Java
    • Java 集合
      • Java 集合 - 高性能队列Disruptor详解
  • 分布式
    • RPC
      • ⭐️RPC - Dubbo&hsf&Spring cloud的区别
  • 分布式
    • RPC
      • ⭐️RPC - Dubbo的架构原理
  • 分布式
    • RPC
      • ⭐️RPC - HSF的原理分析
  • 分布式
    • RPC
      • ⭐️RPC - 你应该知道的RPC原理
  • 分布式
    • RPC
      • ⭐️RPC - 动态代理
  • 分布式
    • RPC
      • 深入理解 RPC 之协议篇
  • 分布式
    • RPC
      • RPC - 序列化和反序列化
  • 分布式
    • RPC
      • ⭐️RPC - 服务注册与发现
  • 分布式
    • RPC
      • RPC - 核心原理
  • 分布式
    • RPC
      • ⭐️RPC - 框架对比
  • 分布式
    • RPC
      • ⭐️RPC - 网络通信
  • 分布式
    • 分布式事务
      • 分布式事务 Seata TCC 模式深度解析
  • 分布式
    • 分布式事务
      • 分布式事务的实现原理
  • 分布式
    • 分布式事务
      • 常用的分布式事务解决方案
  • 分布式
    • 分布式事务
      • 手写实现基于消息队列的分布式事务框架
  • 分布式
    • 分布式算法
      • CAP 定理的含义
  • 分布式
    • 分布式算法
      • Paxos和Raft比较
  • 分布式
    • 分布式算法
      • 分布式一致性与共识算法
  • 分布式
    • 分布式锁
      • ⭐️分布式锁的原理及实现方式
  • 分布式
    • 搜索引擎
      • ElasticSearch与SpringBoot的集成与JPA方法的使用
  • 分布式
    • 搜索引擎
      • 全文搜索引擎 Elasticsearch 入门教程
  • 分布式
    • 搜索引擎
      • 十分钟学会使用 Elasticsearch 优雅搭建自己的搜索系统
  • 分布式
    • 搜索引擎
      • 腾讯万亿级 Elasticsearch 技术解密
  • 分布式
    • 日志系统
      • Grafana Loki 简明教程
  • 分布式
    • 日志系统
      • 分布式系统中如何优雅地追踪日志
  • 分布式
    • 日志系统
      • 如何优雅地记录操作日志?
  • 分布式
    • 日志系统
      • 日志收集组件—Flume、Logstash、Filebeat对比
  • 分布式
    • 日志系统
      • 集中式日志系统 ELK 协议栈详解
  • 分布式
    • 消息队列
      • 消息队列 - Kafka
  • 分布式
    • 消息队列
      • 消息队列 - Kafka、RabbitMQ、RocketMQ等消息中间件的对比
  • 分布式
    • 消息队列
      • 消息队列之 RabbitMQ
  • 分布式
    • 消息队列
      • 消息队列 - 使用docker-compose构建kafka集群
  • 分布式
    • 消息队列
      • 消息队列 - 分布式系统与消息的投递
  • 分布式
    • 消息队列
      • 消息队列 - 如何保证消息的可靠性传输
  • 分布式
    • 消息队列
      • 消息队列 - 如何保证消息的顺序性
  • 分布式
    • 消息队列
      • 消息队列 - 如何保证消息队列的高可用
  • 分布式
    • 消息队列
      • 消息队列 - 消息队列设计精要
  • 分布式
    • 监控系统
      • 深度剖析开源分布式监控CAT
  • 大数据
    • Flink
      • Flink架构与核心组件
  • 微服务
    • Dubbo
      • 基于dubbo的分布式应用中的统一异常处理
  • 微服务
    • Dubbo
      • Vim快捷键
  • 微服务
    • Service Mesh
      • Istio 是什么?
  • 微服务
    • Service Mesh
      • OCTO 2.0:美团基于Service Mesh的服务治理系统详解
  • 微服务
    • Service Mesh
      • Service Mesh是什么?
  • 微服务
    • Service Mesh
      • Spring Cloud向Service Mesh迁移
  • 微服务
    • Service Mesh
      • 数据挖掘算法
  • 微服务
    • Service Mesh
      • Seata Saga 模式
  • 微服务
    • Spring Cloud
      • Seata TCC 模式
  • 微服务
    • Spring Cloud
      • Spring Cloud Config
  • 微服务
    • Spring Cloud
      • Seata AT 模式
  • 微服务
    • Spring Cloud
      • Spring Cloud Gateway
  • 微服务
    • Spring Cloud
      • Spring Cloud OpenFeign 的核心原理
  • 微服务
    • Spring Cloud
      • Seata XA 模式
  • 数据库
    • Database Version Control
      • Liquibase vs. Flyway
  • 数据库
    • Database Version Control
      • Six reasons to version control your database
  • 数据库
    • MySQL
      • How Sharding Works
  • 数据库
    • MySQL
      • MySQL InnoDB中各种SQL语句加锁分析
  • 数据库
    • MySQL
      • MySQL 事务隔离级别和锁
  • 数据库
    • MySQL
      • MySQL 索引性能分析概要
  • 数据库
    • MySQL
      • MySQL 索引设计概要
  • 数据库
    • MySQL
      • MySQL出现Waiting for table metadata lock的原因以及解决方法
  • 数据库
    • MySQL
      • MySQL的Limit性能问题
  • 数据库
    • MySQL
      • MySQL索引优化explain
  • 数据库
    • MySQL
      • MySQL索引背后的数据结构及算法原理
  • 数据库
    • MySQL
      • MySQL行转列、列转行问题
  • 数据库
    • MySQL
      • 一条SQL更新语句是如何执行的?
  • 数据库
    • MySQL
      • 一条SQL查询语句是如何执行的?
  • 数据库
    • MySQL
      • 为什么 MySQL 使用 B+ 树
  • 数据库
    • MySQL
      • 为什么 MySQL 的自增主键不单调也不连续
  • 数据库
    • MySQL
      • 为什么我的MySQL会“抖”一下?
  • 数据库
    • MySQL
      • 为什么数据库不应该使用外键
  • 数据库
    • MySQL
      • 为什么数据库会丢失数据
  • 数据库
    • MySQL
      • 事务的可重复读的能力是怎么实现的?
  • 数据库
    • MySQL
      • 大众点评订单系统分库分表实践
  • 数据库
    • MySQL
      • 如何保证缓存与数据库双写时的数据一致性?
  • 数据库
    • MySQL
      • 浅谈数据库并发控制 - 锁和 MVCC
  • 数据库
    • MySQL
      • 深入浅出MySQL 中事务的实现
  • 数据库
    • MySQL
      • 浅入浅出MySQL 和 InnoDB
  • 数据库
    • PostgreSQL
      • PostgreSQL upsert功能(insert on conflict do)的用法
  • 数据库
    • Redis
      • Redis GEO & 实现原理深度分析
  • 数据库
    • Redis
      • Redis 和 I/O 多路复用
  • 数据库
    • Redis
      • Redis分布式锁
  • 数据库
    • Redis
      • Redis实现分布式锁中的“坑”
  • 数据库
    • Redis
      • Redis总结
  • 数据库
    • Redis
      • 史上最全Redis高可用技术解决方案大全
  • 数据库
    • Redis
      • Redlock:Redis分布式锁最牛逼的实现
  • 数据库
    • Redis
      • 为什么 Redis 选择单线程模型
  • 数据库
    • TiDB
      • 新一代数据库TiDB在美团的实践
  • 数据库
    • 数据仓库
      • 实时数仓在有赞的实践
  • 数据库
    • 数据库原理
      • OLTP与OLAP的关系是什么?
  • 数据库
    • 数据库原理
      • 为什么 OLAP 需要列式存储
  • 系统设计
    • DDD
      • Domain Primitive
  • 系统设计
    • DDD
      • Repository模式
  • 系统设计
    • DDD
      • 应用架构
  • 系统设计
    • DDD
      • 聊聊如何避免写流水账代码
  • 系统设计
    • DDD
      • 领域层设计规范
  • 系统设计
    • DDD
      • 从三明治到六边形
  • 系统设计
    • DDD
      • 阿里盒马领域驱动设计实践
  • 系统设计
    • DDD
      • 领域驱动设计(DDD)编码实践
  • 系统设计
    • DDD
      • 领域驱动设计在互联网业务开发中的实践
  • 系统设计
    • 基础架构
      • 容错,高可用和灾备
  • 系统设计
    • 数据聚合
      • GraphQL及元数据驱动架构在后端BFF中的实践
  • 系统设计
    • 数据聚合
      • 高效研发-闲鱼在数据聚合上的探索与实践
  • 系统设计
    • 服务安全
      • JSON Web Token 入门教程
  • 系统设计
    • 服务安全
      • 你还在用JWT做身份认证嘛?
  • 系统设计
    • 服务安全
      • 凭证(Credentials)
  • 系统设计
    • 服务安全
      • 授权(Authorization)
  • 系统设计
    • 服务安全
      • 理解OAuth2.0
  • 系统设计
    • 服务安全
      • 认证(Authentication)
  • 系统设计
    • 架构案例
      • 微信 Android 客户端架构演进之路
  • 系统设计
    • 高可用架构
      • 业务高可用的保障:异地多活架构
  • 计算机基础
    • 字符编码
      • Base64原理解析
  • 计算机基础
    • 字符编码
      • 字符编码笔记:ASCII,Unicode 和 UTF-8
  • 计算机基础
    • 操作系统
      • 为什么 CPU 访问硬盘很慢
  • 计算机基础
    • 操作系统
      • 为什么 HTTPS 需要 7 次握手以及 9 倍时延
  • 计算机基础
    • 操作系统
      • 为什么 Linux 默认页大小是 4KB
  • 计算机基础
    • 操作系统
      • 磁盘IO那些事
  • 计算机基础
    • 操作系统
      • 虚拟机的3种网络模式
  • 计算机基础
    • 服务器
      • mac终端bash、zsh、oh-my-zsh最实用教程
  • 计算机基础
    • 服务器
      • Nginx强制跳转Https
  • 计算机基础
    • 服务器
      • curl 的用法指南
  • 计算机基础
    • 网络安全
      • 如何设计一个安全的对外接口?
  • 计算机基础
    • 网络安全
      • 浅谈常见的七种加密算法及实现
  • 计算机基础
    • 网络编程
      • MQTT - The Standard for IoT Messaging
  • 计算机基础
    • 网络编程
      • 两万字长文 50+ 张趣图带你领悟网络编程的内功心法
  • 计算机基础
    • 网络编程
      • 为什么 TCP 协议有 TIME_WAIT 状态
  • 计算机基础
    • 网络编程
      • 为什么 TCP 协议有性能问题
  • 计算机基础
    • 网络编程
      • 为什么 TCP 协议有粘包问题
  • 计算机基础
    • 网络编程
      • 为什么 TCP 建立连接需要三次握手
  • 计算机基础
    • 网络编程
      • 为什么 TCP/IP 协议会拆分数据
  • 计算机基础
    • 网络编程
      • 使用 OAuth 2 和 JWT 为微服务提供安全保障
  • 计算机基础
    • 网络编程
      • 四种常见的 POST 提交数据方式
  • 计算机基础
    • 网络编程
      • 有赞TCP网络编程最佳实践
  • 计算机基础
    • 网络编程
      • 看完这篇HTTP,跟面试官扯皮就没问题了
  • 计算机基础
    • 网络编程
      • 详细解析 HTTP 与 HTTPS 的区别
  • 质量&效率
    • 快捷键
      • Idea快捷键(Mac版)
  • 质量&效率
    • 快捷键
      • Shell快捷键
  • 质量&效率
    • 快捷键
      • conduit
  • 质量&效率
    • 敏捷开发
      • Scrum的3种角色
  • 质量&效率
    • 敏捷开发
      • Scrum的4种会议
  • 质量&效率
    • 敏捷开发
      • ThoughtWorks的敏捷开发
  • 质量&效率
    • 敏捷开发
      • 敏捷开发入门教程
  • 运维&测试
    • Docker
      • Docker (容器) 的原理
  • 运维&测试
    • Docker
      • Docker Compose:链接外部容器的几种方式
  • 运维&测试
    • Docker
      • Docker 入门教程
  • 运维&测试
    • Docker
      • Docker 核心技术与实现原理
  • 运维&测试
    • Docker
      • Dockerfile 最佳实践
  • 运维&测试
    • Docker
      • Docker开启Remote API 访问 2375端口
  • 运维&测试
    • Docker
      • Watchtower - 自动更新 Docker 镜像与容器
  • 运维&测试
    • Kubernetes
      • Kubernetes 介绍
  • 运维&测试
    • Kubernetes
      • Kubernetes 在有赞的实践
  • 运维&测试
    • Kubernetes
      • Kubernetes 学习路径
  • 运维&测试
    • Kubernetes
      • Kubernetes如何改变美团的云基础设施?
  • 运维&测试
    • Kubernetes
      • Kubernetes的三种外部访问方式:NodePort、LoadBalancer 和 Ingress
  • 运维&测试
    • Kubernetes
      • 谈 Kubernetes 的架构设计与实现原理
  • 运维&测试
    • 压测
      • 全链路压测平台(Quake)在美团中的实践
  • 运维&测试
    • 测试
      • Cpress - JavaScript End to End Testing Framework
  • 运维&测试
    • 测试
      • 代码覆盖率-JaCoCo
  • 运维&测试
    • 测试
      • 浅谈代码覆盖率
  • 运维&测试
    • 测试
      • 测试中 Fakes、Mocks 以及 Stubs 概念明晰
  • Java FrameWorks
    • Spring
      • Spring AOP
        • Spring AOP中的Bean是如何被AOP代理的
  • Java FrameWorks
    • Spring
      • Spring AOP
        • Spring AOP原生动态代理和Cglib动态代理
  • Java FrameWorks
    • Spring
      • Spring AOP
        • Spring AOP实现方式(xml&注解)
  • Java FrameWorks
    • Spring
      • Spring AOP
        • Spring AOP是如何收集切面类并封装的
  • Java FrameWorks
    • Spring
      • Spring AOP
        • Spring AOP概述
  • Java FrameWorks
    • Spring
      • Spring AOP
        • Spring AOP的底层核心后置处理器
  • Java FrameWorks
    • Spring
      • Spring AOP
        • Spring AOP的延伸知识
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot - IOC(一)
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot - IOC(三)
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot - IOC(二)
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot - IOC(五)
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot - IOC(四) - 循环依赖与解决方案
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot - 启动引导
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot JarLauncher
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot Web Mvc 自动装配
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot 使用ApplicationListener监听器
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot 声明式事务
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot 嵌入式容器
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot引起的“堆外内存泄漏”排查及经验总结
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot的启动流程
  • Java FrameWorks
    • Spring
      • Spring Boot
        • Spring Boot自动化配置源码分析
  • Java FrameWorks
    • Spring
      • Spring Boot
        • 如何自定义Spring Boot Starter?
  • Java FrameWorks
    • Spring
      • Spring IOC
        • IOC - 模块装配和条件装配
  • Java FrameWorks
    • Spring
      • Spring IOC
        • IOC - 配置源(xml,注解)
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring Environment
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring ApplicationContext
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring BeanDefinition
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring BeanFactory
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring BeanFactoryPostProcessor
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring BeanPostProcessor
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring Bean的生命周期(一) - 概述
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring Bean的生命周期(三) - 实例化阶段
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring Bean的生命周期(二) - BeanDefinition
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring Bean的生命周期(五) - 销毁阶段
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring Bean的生命周期(四) - 初始化阶段
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring ComponentScan
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring Events
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring IOC 基础篇
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring IOC 总结
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring IOC 进阶篇
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring IOC容器的生命周期
  • Java FrameWorks
    • Spring
      • Spring IOC
        • Spring Resource
  • Java FrameWorks
    • Spring
      • Spring MVC
        • DispatcherServlet的初始化原理
  • Java FrameWorks
    • Spring
      • Spring MVC
        • DispatcherServlet的核心工作原理
  • Java FrameWorks
    • Spring
      • Spring MVC
        • WebMvc的架构设计与组件功能解析
  • Java FrameWorks
    • Spring
      • Spring Security
        • Spring Boot 2 + Spring Security 5 + JWT 的单页应用 Restful 解决方案
  • Java FrameWorks
    • Spring
      • Spring Security
        • Spring Security Oauth
  • Java FrameWorks
    • Spring
      • Spring Security
        • Spring Security
  • Java FrameWorks
    • Spring
      • Spring WebFlux
        • DispatcherHandler的工作原理(传统方式)
  • Java FrameWorks
    • Spring
      • Spring WebFlux
        • DispatcherHandler的工作原理(函数式端点)
  • Java FrameWorks
    • Spring
      • Spring WebFlux
        • WebFlux的自动装配
  • Java FrameWorks
    • Spring
      • Spring WebFlux
        • 快速了解响应式编程与Reactive
  • Java FrameWorks
    • Spring
      • Spring WebFlux
        • 快速使用WebFlux
  • 分布式
    • 协调服务
      • Zookeeper
        • Zookeeper - 客户端之 Curator
  • 分布式
    • 协调服务
      • Zookeeper
        • 详解分布式协调服务 ZooKeeper
  • 分布式
    • 协调服务
      • etcd
        • 高可用分布式存储 etcd 的实现原理
  • 数据库
    • Database Version Control
      • Flyway
        • Database Migrations with Flyway
  • 数据库
    • Database Version Control
      • Flyway
        • How Flyway works
  • 数据库
    • Database Version Control
      • Flyway
        • Rolling Back Migrations with Flyway
  • 数据库
    • Database Version Control
      • Flyway
        • The meaning of the concept of checksums
  • 数据库
    • Database Version Control
      • Liquibase
        • Introduction to Liquibase Rollback
  • 数据库
    • Database Version Control
      • Liquibase
        • LiquiBase中文学习指南
  • 数据库
    • Database Version Control
      • Liquibase
        • Use Liquibase to Safely Evolve Your Database Schema
  • 系统设计
    • 流量控制
      • RateLimiter
        • Guava Rate Limiter实现分析
  • 系统设计
    • 流量控制
      • Sentinel
        • Sentinel 与 Hystrix 的对比
  • 系统设计
    • 流量控制
      • Sentinel
        • Sentinel工作主流程
  • 系统设计
    • 流量控制
      • 算法
        • 分布式服务限流实战
  • 系统设计
    • 解决方案
      • 秒杀系统
        • 如何设计一个秒杀系统
  • 系统设计
    • 解决方案
      • 红包系统
        • 微信高并发资金交易系统设计方案--百亿红包背后的技术支撑
  • 计算机基础
    • 数据结构与算法
      • 其他相关
        • 什么是预排序遍历树算法(MPTT,Modified Preorder Tree Traversal)
  • 计算机基础
    • 数据结构与算法
      • 其他相关
        • 加密算法
  • 计算机基础
    • 数据结构与算法
      • 其他相关
        • 推荐系统算法
  • 计算机基础
    • 数据结构与算法
      • 其他相关
        • linkerd
  • 计算机基础
    • 数据结构与算法
      • 其他相关
        • 查找算法
  • 计算机基础
    • 数据结构与算法
      • 其他相关
        • 缓存淘汰算法中的LRU和LFU
  • 计算机基础
    • 数据结构与算法
      • 其他相关
        • 负载均衡算法
  • 计算机基础
    • 数据结构与算法
      • 分布式算法
        • 分布式算法 - Paxos算法
  • 计算机基础
    • 数据结构与算法
      • 分布式算法
        • 分布式算法 - Raft算法
  • 计算机基础
    • 数据结构与算法
      • 分布式算法
        • 分布式算法 - Snowflake算法
  • 计算机基础
    • 数据结构与算法
      • 分布式算法
        • 分布式算法 - ZAB算法
  • 计算机基础
    • 数据结构与算法
      • 分布式算法
        • 分布式算法 - 一致性Hash算法
  • 计算机基础
    • 数据结构与算法
      • 大数据处理
        • 大数据处理 - Bitmap & Bloom Filter
  • 计算机基础
    • 数据结构与算法
      • 大数据处理
        • 大数据处理 - Map & Reduce
  • 计算机基础
    • 数据结构与算法
      • 大数据处理
        • 大数据处理 - Trie树/数据库/倒排索引
  • 计算机基础
    • 数据结构与算法
      • 大数据处理
        • 大数据处理 - 分治/hash/排序
  • 计算机基础
    • 数据结构与算法
      • 大数据处理
        • 大数据处理 - 双层桶划分
  • 计算机基础
    • 数据结构与算法
      • 大数据处理
        • 大数据处理 - 外(磁盘文件)排序
  • 计算机基础
    • 数据结构与算法
      • 大数据处理
        • 大数据处理 - 布隆过滤器
  • 计算机基础
    • 数据结构与算法
      • 大数据处理
        • 大数据处理算法
  • 计算机基础
    • 数据结构与算法
      • 字符串匹配算法
        • 字符串匹配 - 文本预处理:后缀树(Suffix Tree)
  • 计算机基础
    • 数据结构与算法
      • 字符串匹配算法
        • 字符串匹配 - 模式预处理:BM 算法 (Boyer-Moore)
  • 计算机基础
    • 数据结构与算法
      • 字符串匹配算法
        • 字符串匹配 - 模式预处理:KMP 算法(Knuth-Morris-Pratt)
  • 计算机基础
    • 数据结构与算法
      • 字符串匹配算法
        • 字符串匹配 - 模式预处理:朴素算法(Naive)(暴力破解)
  • 计算机基础
    • 数据结构与算法
      • 字符串匹配算法
        • 字符串匹配
  • 计算机基础
    • 数据结构与算法
      • 常用算法
        • 分支限界算法
  • 计算机基础
    • 数据结构与算法
      • 常用算法
        • 分治算法
  • 计算机基础
    • 数据结构与算法
      • 常用算法
        • 动态规划算法
  • 计算机基础
    • 数据结构与算法
      • 常用算法
        • 回溯算法
  • 计算机基础
    • 数据结构与算法
      • 常用算法
        • 贪心算法
  • 计算机基础
    • 数据结构与算法
      • 排序算法
        • 十大排序算法
  • 计算机基础
    • 数据结构与算法
      • 排序算法
        • 图解排序算法(一)之3种简单排序(选择,冒泡,直接插入)
  • 计算机基础
    • 数据结构与算法
      • 排序算法
        • 图解排序算法(三)之堆排序
  • 计算机基础
    • 数据结构与算法
      • 排序算法
        • 图解排序算法(二)之希尔排序
  • 计算机基础
    • 数据结构与算法
      • 排序算法
        • 图解排序算法(四)之归并排序
  • 计算机基础
    • 数据结构与算法
      • 数据结构
        • 树的高度和深度
  • 计算机基础
    • 数据结构与算法
      • 数据结构
        • 红黑树深入剖析及Java实现
  • 计算机基础
    • 数据结构与算法
      • 数据结构
        • 线性结构 - Hash
  • 计算机基础
    • 数据结构与算法
      • 数据结构
        • 线性结构 - 数组、链表、栈、队列
  • 计算机基础
    • 数据结构与算法
      • 数据结构
        • 逻辑结构 - 树
  • 运维&测试
    • 测试
      • Spock
        • Groovy 简明教程
  • 运维&测试
    • 测试
      • Spock
        • Spock 官方文档
  • 运维&测试
    • 测试
      • Spock
        • Spock单元测试框架介绍以及在美团优选的实践
  • 运维&测试
    • 测试
      • TDD
        • TDD 实践 - FizzFuzzWhizz(一)
  • 运维&测试
    • 测试
      • TDD
        • TDD 实践 - FizzFuzzWhizz(三)
  • 运维&测试
    • 测试
      • TDD
        • TDD 实践 - FizzFuzzWhizz(二)
  • 运维&测试
    • 测试
      • TDD
        • 测试驱动开发(TDD)- 原理篇
  • 微服务
    • Spring Cloud
      • Spring Cloud Alibaba
        • Nacos
          • Nacos 服务注册的原理
  • 微服务
    • Spring Cloud
      • Spring Cloud Alibaba
        • Nacos
          • Nacos 配置中心原理分析
  • 微服务
    • Spring Cloud
      • Spring Cloud Alibaba
        • Seata
          • 服务调用过程
  • 微服务
    • Spring Cloud
      • Spring Cloud Alibaba
        • Seata
          • Spring Cloud Bus
  • 微服务
    • Spring Cloud
      • Spring Cloud Alibaba
        • Seata
          • Spring Cloud Consul
  • 微服务
    • Spring Cloud
      • Spring Cloud Alibaba
        • Seata
          • Spring Cloud Stream
  • 微服务
    • Spring Cloud
      • Spring Cloud Alibaba
        • Sentinel
          • Sentinel 与 Hystrix 的对比
  • 微服务
    • Spring Cloud
      • Spring Cloud Alibaba
        • Sentinel
          • Sentinel
  • 微服务
    • Spring Cloud
      • Spring Cloud Netflix
        • Hystrix
          • How Hystrix Works
  • 微服务
    • Spring Cloud
      • Spring Cloud Netflix
        • Hystrix
          • Hystrix
  • 微服务
    • Spring Cloud
      • Spring Cloud Netflix
        • Hystrix
          • Hystrix原理与实战
  • 微服务
    • Spring Cloud
      • Spring Cloud Netflix
        • Hystrix
          • Spring Cloud Hystrix基本原理
由 GitBook 提供支持
在本页
  • 1. 前言
  • 2. 代码样例
  • 3. 核心概念
  • 4. 组件实例与API
  • 4.1 Message
  • 4.2 Message Channel
  • 4.3 Message Endpoint
  • 4.4 辅助类与工具
  • 5. DSL简述
  • 6. 监控与异常处理
  • 6.1 监控
  • 6.2 异常处理
  • 7. 扩展
  • 8. 经典样例
  • 9. 应用体会

这有帮助吗?

  1. Java FrameWorks
  2. Spring

Spring Integration简介

转载:Spring Integration简介

1. 前言

此番介绍一个不是特别热门的Spring子项目:Spring Integration,总的来说它是一种消息控制框架,核心思想源自Enterprise Integration Pattern一书。构建此框架的核心目标是为企业复杂系统集成提供一种便捷的解决方案,可以说它与ESB(Enterprise Service Bus)有很多相似之处,意在通过消息将各个子系统解耦分离。

由于核心概念就是从Enterprise Integration Pattern一书中的理论出发,那么了解这本书必然会对熟悉使用此框架有很大的帮助,推荐阅读这篇文章来帮助理解,本文也会直接引用一些该文章的内容。由于Spring Integration相关的第三方资料、文章比较少,因此在学习和使用过程中很有必要参考官方文档,本文的结构其实也与官方文档比较类似。

2. 代码样例

在我对此框架进行初探和了解之时发现零星的相关文章总是描述相关的概念而没有任何示例表明这个框架到底做了什么、可以干什么,与此同时很多相关案例均是以XML配置的形式来表达,而时至今日XML配置正逐步被淘汰,因此学习的过程极其不顺。没有什么比一段简洁的可执行代码更能说明问题,因此首先贴上一段示例代码,以SpringBoot为基础、纯java配置:

@Configuration
@EnableIntegration
@MessageEndpoint
public class flow {

    @Bean
    public MessageChannel beep(){
        return new QueueChannel();
    }
    
    @InboundChannelAdapter(value = "beep", poller = @Poller(fixedRate = "2000"))
    public int input(){
        Random random = new Random();
        System.out.println("Generate !!!");
        return random.nextInt();
    }
    
    @ServiceActivator(inputChannel = "beep", poller = @Poller(fixedRate = "500") )
    public void output(Message<?> message){
        System.out.println("Msg:"+ message);
    }

}

依赖项:

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-integration</artifactId>
	</dependency>
		
	<!-- something more ... -->
</dependencies>

直接将上述内容置入一个SpringBoot项目,启动后即可观察到打印输出的内容。相信即使未有了解过任何Spring Integration概念也能明白上述代码做了什么,基本上就是个典型的生产者消费者模型,而其中传输的就是消息。可以看出Spring Integration做的最重要的一件事就是配置管道、传递消息。

3. 核心概念

从源头Enterprise Integration Pattern来说,它认为企业内部各个子服务基于消息集成,在这种方式下各个组件之间的交互将不再使用远程调用等同步方式,而是通过向目标子系统发送一个消息来令该子系统执行某个功能,在消息成功发送之后,调用方即可以开始对其它任务进行处理,而不再是同步调用过程中的等待。在使用这种处理方式时,一个系统的吞吐量可以大大增加。这种应用场景被抽象为Pipes-and-Filters模型:

该模型主要由两部分组成:用来传递消息的通道(Pipe)以及用来对消息进行处理的过滤器(Filter)。这些消息通道将过滤器串联起来,而消息自身则会沿着这些通道流动。

在Spring Integration中,pipe和filter加上消息本身构成了三大基本组件:

  1. Message:即消息本身,它由Payload和Header两部分组成,Payload是对任意Java对象的包装而Header则包含了消息的元数据信息,同时header也常用于Http、Mail等其他消息头部的转换。其基接口为Message<T>,需要注意的是通用的消息实现是不可变的。

  2. Message Channel:即Pipes-and-Filters模型中的pipe,它是消息传输的载体,通常可以分为point-to-point(点对点)和publish-subscribe(发布订阅)两种行为模式。此外从通道是否保存消息的角度来说,通道还分为Pollable Channel和Subscribable Channel两种。

    • Pollable Channel:保存消息,消费者需要主动拉取消息,核心接口为PollableChannel。

    • Subscribable Channel:可订阅型通道,不存储消息,消费者被动通知消息,核心接口为SubscribableChannel。

    这种划分方式也是API接口的划分方式,不同的通道类型对消息流程的处理会有不同的表现形式。

  3. Message Endpoint:即Pipes-and-Filters模型中的Filter,它是消息的消费端,通常与外部系统对接。Spring Integration提供了多种不同的EndPoint满足不同的需求。

4. 组件实例与API

在Spring Integration中几个基本概念都有其基本接口,下面介绍一些具体实现类以及辅助工具类。

4.1 Message

Message的通用实现类为org.springframework.messaging.support.GenericMessage,在框架执行过程中Message的头部默认会包括timestamp(时间戳)和id(UUID类型),特别注意它是不可变的。在接收消息时,参数可以直接使用Message接口,也可以直接使用载荷的具体类型辅以@Payload,在获取头部信息时,可以使用@Header("head name")来接受头部的具体某项值。

4.2 Message Channel

  • Pollable Channel

    • QueueChannel:基本的拉取型通道,底层封装了一个队列。它是一个point-to-point型的通道,这也意味着即使该通道有多个消费者,每个消息只会被一个消费者获取。队列可以指定容量大小,消息生产者和消费者在发送消息、接收消息时的行为与操作阻塞队列类似。

    • PriorityChannel:与QueueChannel类似,但是底层是一个优先队列,与QueueChannel先入先出的形式不同,它可以为通道内的消息进行优先级操作。

  • Subscribable Channel

    • PublishSubscribeChannel:基本的通知型通道,从名称上就可以看出他是一个publish-subscribe型通道,该通道所有的消费者都会接收到通道的每一个消息,常用于事件消息的处理。此通道继承了AbstractExecutorChannel,如果构造时传入Executor则在执行消费者时会使用到线程池,消费者与生产者不在同一个线程中执行,否则将在同一个线程中依次调用各个消费者。

    • DirectChannel:point-to-point型的通道但是本身不存储消息,只能有一个消费者,此通道的消费者和生产者将在同一个线程中执行任务,相当于函数调用。注意这是框架默认的通道类型。

    • ExecutorChannel:同样是一个point-to-point型的通道,与DirectChannel不同的是它继承自AbstractExecutorChannel,消费者与生产者不在同一个线程中执行。

4.3 Message Endpoint

以java config配置Endpoint时,通常会创建一个标有@MessageEndpoint注解的配置类,然后编写相关方法并配以相关的注解。注意配置类上可以辅以@Configuration以便同时配置通道Bean,但是Endpoint方法通常不会与@Bean注解同时出现,配以@Bean后Endpoint表现出的行为可能会不符合预期,例如上面的那一段示例代码,如果在消费者上增加@Bean那么每次产生的消息都将是同一个int值。

相关的注解均在org.springframework.integration.annotation包下,这些注解通常都配有inputChannel和outChannel属性,用于指定输入输出通道,如果在容器中没有找到该名称的通道Bean则会自动创建(DirectChannel类型,必须有@EnableIntegration)。以下是常用的几种Endpoint实现:

  • Message Transformer:消息转换器,用于转换消息内容和格式。

  • Message Filter:消息过滤器,没什么可多说的,返回类型为boolean即可。

  • Message Router:消息路由器,用于判断将消息发往哪个通道,相关注解可以配置映射通道的名称列表,函数返回判断后决定发送的通道名称。

  • Splitter:消息分割器,用于将单个消息分割为多个消息,通常在分割组合内容的载荷时使用。

  • Aggregator:基本上是Splitter的反面,Aggregator将多个消息聚合为一个消息。为了聚合消息,这种Endpoint需要消息存储器、判断是否属于同一个聚合的方法等额外的配置,而且通常会接收多个通道的输出,因此在实际使用过程中通常无法直接用单个注解来完成定义,往往采用Bean的方式详细定制。

  • Service Activator:通常用于连接具体的服务,作为消息最终的消费方,因此称为服务激活器。

  • Channel Adapter:用于连接外部系统,可以是输入也可以是输出,也可以作为两个通道的连接适配器(例如协调Pollable Channel和Subscribable Channel)。框架提供了@InboundChannelAdapter这一注解来快速配置一个消息发生器,可以以指定的时间间隔产生、发送消息。

4.4 辅助类与工具

  • @EnableIntegration:工程配置辅助注解,该注解会在Spring容器中注入一些消息系统的基本组件,主要如有如下:

    • 内建的Bean,例如errorChannel、taskScheduler等

    • 一些BeanFactoryPostProcessor,增强集成环境

    • 一些BeanPostProcessor,对一些集成的Bean进行转化、包装

    • 解析相关注解的Annotaion Processor,根据这些注解注册相关的Bean

  • MessagingTemplate:通常情况下发送和接受消息需要直接调用channel的方法,为了实现非侵入性接入消息系统,提供的消息发送、接受工具,同时也能更加符合收发消息的语义。

  • ChannelInterceptor:通道拦截器接口,AOP相关的概念,包含了6个接口方法,结合通道的send和receive方法,执行顺序如下:

    • channel.send 调用

    • interceptor.preSend

    • channel.doSend (存入通道)

    • interceptor.postSend

    • interceptor.afterSendCompletion

    • channel.send 返回

    • channel.receive 调用

    • interceptor.preReceive (若此方法返回false则调用receive将收到null,但仍会执行afterReceiveCompletion,此方法仅应用于PollableChannel)

    • channel.doReceive (取出消息)

    • interceptor.postReceive(此方法仅应用于PollableChannel且收到消息后才会执行)

    • interceptor.afterReceiveCompletion

    • channel.receive 返回

  • Advice:Endpoint的切面工具类,提供对单个Endpoint执行切入(直接使用AOP可能切得过宽,有些通道是直接方法调用),以期对Endpoint方法进行重试、过滤等等。框架默认提供了一些Advice类,我们也可以进行自定义,通常自定义Advice可以继承AbstractRequestHandlerAdvice来减少额外的编码。

5. DSL简述

DSL即Domain Specific Language,是为了解决某一类任务而专门设计的语言,Spring Integration目前提供了一套由Java流式API和Java Config实现的配置Spring Integration的DSL。通过java dsl可以快速定义出整个消息流程,看一下官方示例代码就可以快速理解其精髓。

@Configuration
@EnableIntegration
public class MyConfiguration {

    @Bean
    public AtomicInteger integerSource() {
        return new AtomicInteger();
    }

    @Bean
    public IntegrationFlow myFlow() {
        return IntegrationFlows.from(integerSource::getAndIncrement,
                                         c -> c.poller(Pollers.fixedRate(100)))
                    .channel("inputChannel")
                    .filter((Integer p) -> p > 0)
                    .transform(Object::toString)
                    .channel(MessageChannels.queue())
                    .get();
    }
}

如果流程没有分支、聚合且没有特殊的定制要求,那么DSL的优势非常明显。目前Spring Integration所有的组件均可以在DSL中找到对应的调用方法。所有流程都从IntegrationFlows开始,具体如何使用参见官方文档,有一整个章节来描述使用的方法。

6. 监控与异常处理

在系统管理方面Spring Integration也提供了相关的工具来监控消息组件的使用状况以及对于Endpoint执行过程中出现异常的处理。

6.1 监控

开启监控后可以掌握Message Channel和Message Endpoint以及Message Source的使用状态信息。启用监控非常方便,在Java Config应用情景下,使用@EnableIntegrationManagement注解即可:

@Configuration
@EnableIntegration
@EnableIntegrationManagement(
    defaultLoggingEnabled = "true", 
    defaultCountsEnabled = "false", 
    defaultStatsEnabled = "false", 
    countsEnabled = { "foo", "${count.patterns}" }, 
    statsEnabled = { "qux", "!*" }, 
    MetricsFactory = "myMetricsFactory") 
public static class ContextConfiguration {
...
}

可以看到它支持配置只对特定的组件进行监控,监控的各项指标包括总计、错误总计、执行时间等,具体可以查阅官方文档。

开启监控后容器中会注入IntegrationManagementConfigurer类型的Bean,在应用内可以通过它来获取到各个组件的监控对象,此外启用JMX时也可以通过MBean来获取相关信息。

此外SI还提供了一个注解@EnableIntegrationGraphController来将所有SI的组件的运行时监控信息通过一个Controller返回Json格式的数据,基本上包含了所有的监控内容,非常方便。

6.2 异常处理

Spring Integration对于错误处理的解决主要通过errorChannel来实现,它将组件中发生的错误包装为一个错误消息发送至error channel,这个通道默认类型为subscribable channel,没有指定时将提供默认的实现。这样即使发送者与接收者即使不在同一个线程(同一个线程的情况下,错误会直接抛给发送者)的情况下依然能够对错误进行处理。

框架默认会注册一个errorChannel,也可以进行自定义配置。如果需要对不同的错误分类处理,Spring Integration提供了几种方法:

  1. Message头部可以指定错误通道的名称(头部名为常量MessageHeaders.ERROR_CHANNEL)

  2. 配置一个ErrorMessageExceptionTypeRouter 来订阅error channel以实现对不同错误类型的分发

7. 扩展

为了适配不同的输入、出处,第三方系统集成以及对消息的持久化等,Spring Integration提供了多种适配包,如Http、Ftp、Mail、JDBC等等,基本涵盖了大部分常用的工具、系统。具体详见官方文档。

8. 经典样例

Spring Integration提供了一些样例代码以供学些参考,地址为https://github.com/spring-projects/spring-integration-samples。这里将最经典的一个样例拿出来解释一下,此样例非常能说明问题,同样对理解大有裨益。该样例名称为咖啡店,对咖啡店的下单流程使用Spring Integration进行了模拟,整个流程描述如图:

简单描述一下:一个订单包含多个商品,商品分为冷饮和热饮,两种商品需要分开制作准备,全部制作完成后由服务员统一传递。以Java Config版本为示例,这其中包含了

  • 信息拆分(Splitter):将订单消息拆分为多个饮品消息

    @MessageEndpoint
    public class OrderSplitter {
    
    	@Splitter(inputChannel="orders", outputChannel="drinks")
    	public List<OrderItem> split(Order order) {
    		return order.getItems();
    	}
    
    }
  • 信息路由(Router):将冷饮项和热饮项传递到不同的通道

    @MessageEndpoint
    public class DrinkRouter {
    
    	@Router(inputChannel="drinks")
    	public String resolveOrderItemChannel(OrderItem orderItem) {
    		return (orderItem.isIced()) ? "coldDrinks" : "hotDrinks";
    	}
    
    }
  • 信息消费(Service Activator):制作饮品

    @Component
    public class Barista {
    
    	private static Log logger = LogFactory.getLog(Barista.class);
    
    	private long hotDrinkDelay = 5000;
    
    	private long coldDrinkDelay = 1000;
    
    	private final AtomicInteger hotDrinkCounter = new AtomicInteger();
    
    	private final AtomicInteger coldDrinkCounter = new AtomicInteger();
    
    
    	public void setHotDrinkDelay(long hotDrinkDelay) {
    		this.hotDrinkDelay = hotDrinkDelay;
    	}
    
    	public void setColdDrinkDelay(long coldDrinkDelay) {
    		this.coldDrinkDelay = coldDrinkDelay;
    	}
    
    	@ServiceActivator(inputChannel="hotDrinkBarista", outputChannel="preparedDrinks")
    	public Drink prepareHotDrink(OrderItem orderItem) {
    		try {
    			Thread.sleep(this.hotDrinkDelay);
    			logger.info(Thread.currentThread().getName()
    					+ " prepared hot drink #" + hotDrinkCounter.incrementAndGet() + " for order #"
    					+ orderItem.getOrderNumber() + ": " + orderItem);
    			return new Drink(orderItem.getOrderNumber(), orderItem.getDrinkType(), orderItem.isIced(),
    					orderItem.getShots());
    		} catch (InterruptedException e) {
    			Thread.currentThread().interrupt();
    			return null;
    		}
    	}
    
    	@ServiceActivator(inputChannel="coldDrinkBarista", outputChannel="preparedDrinks")
    	public Drink prepareColdDrink(OrderItem orderItem) {
    		try {
    			Thread.sleep(this.coldDrinkDelay);
    			logger.info(Thread.currentThread().getName()
    					+ " prepared cold drink #" + coldDrinkCounter.incrementAndGet() + " for order #"
    					+ orderItem.getOrderNumber() + ": " + orderItem);
    			return new Drink(orderItem.getOrderNumber(), orderItem.getDrinkType(), orderItem.isIced(),
    					orderItem.getShots());
    		} catch (InterruptedException e) {
    			Thread.currentThread().interrupt();
    			return null;
    		}
    	}
    
    }
  • 信息聚合(Aggregator):将多个饮品项根据订单号聚合为一个完整的消息

    @MessageEndpoint
    public class Waiter {
    
    	@Aggregator(inputChannel = "preparedDrinks", outputChannel = "deliveries")
    	public Delivery prepareDelivery(List<Drink> drinks) {
    		return new Delivery(drinks);
    	}
    
    	@CorrelationStrategy
    	public int correlateByOrderNumber(Drink drink) {
    		return drink.getOrderNumber();
    	}
    
    }

这个样例给出了XML配置、Java Config、Java DSL三种配置方式的示例代码,比较好地展示出了Spring Integration的特性。

9. 应用体会

最后分享几点应用过程中的心得体会以及一些总结。

  1. 必须了解不同通道处理消息的方式以及特性,对消息执行时所处的线程有清晰的认识,否则运行时表现的行为往往会和预想的有所不同。不同于消息队列中间件可以推送消息至消费者,作为一个框架在内部分发消息时,消费者消费消息执行的方式为线程内的方法调用、提交线程池运行、主动从队列中拉取。

  2. 通道一般都需要直接进行定义,对于一个消息系统来说通常不会采用默认的DirectChannel,这样就导致需要定义大量的通道Bean,适当采用MessageTemplate通过Bean名称来发送消息(需要配置DestinationResolver)而不是通过通道对象,这样会使代码更加简洁明了。

  3. 如果要使用Aggregator则需注意聚合时Message通常以ID作为key来存储,注意同一消息是否被发往多个通道然后被Aggregator接收多次。

  4. 对于现在的应用情景来说,尽管Spring Integration的目的是整合各种各样的外部系统,但是现有成熟的消息队列中间件往往是更好的选择,完备的持久化、分布式解决方案以及开箱即用的监控UI界面都是SI不具备的。此外在微服务大行其道的情况下,这种集中式策略就更显有些格格不入,但是话又说回来,微服务也是有点吹的过头,在没有达到规模以及性能瓶颈的情况下微服务只会徒增复杂度,对于逐步发展的集成项目来说,其实不妨先采用集中式架构。对于一些需要在内部分发、路由消息的单体应用倒是很适合使用SI。

  5. 可以发现有很多类的包是org.springframework.messaging,并不在SI自己的包下,有些类甚至有重复。简单查阅来看,Spring Messaging这个包创建的时间是晚于Spring Integration的,也就是说Spring已经将消息编程模型的概念抽离了出来,以更好地适配消息中间件以及其他消息应用,SI成为了其上层的应用。而Spring Cloud Stream则是对SI的再一次封装,增加了许多Binding(绑定)的功能,可以看到SI在这之中也是控制应用内部的消息流转。

  6. 本人也是在特定场景下寻找一款工具来集成内部的不同系统而发现的Spring Integration,资料确实少。编写过程中出于组件重用的考虑感觉并不如想象中的方便,流程写完了也就写死了,并没有灵活变更的感觉,不过SI还是有其用武之地的。

上一页Spring下一页Java FrameWorks

最后更新于2年前

这有帮助吗?

2021-04-15-1zwDLG
2021-04-15-viBXbG