接着在任务真正执行时进行判断:
private final class ReaderIdleTimeoutTask extends AbstractIdleTask { ReaderIdleTimeoutTask(ChannelHandlerContext ctx) { super(ctx); } @Override protected void run(ChannelHandlerContext ctx) { long nextDelay = readerIdleTimeNanos; if (!reading) { nextDelay -= ticksInNanos() - lastReadTime; } if (nextDelay <= 0) { // Reader is idle - set a new timeout and notify the callback. readerIdleTimeout = schedule(ctx, this, readerIdleTimeNanos, TimeUnit.NANOSECONDS); boolean first = firstReaderIdleEvent; firstReaderIdleEvent = false; try { IdleStateEvent event = newIdleStateEvent(IdleState.READER_IDLE, first); channelIdle(ctx, event); } catch (Throwable t) { ctx.fireExceptionCaught(t); } } else { // Read occurred before the timeout - set a new timeout with shorter delay. readerIdleTimeout = schedule(ctx, this, nextDelay, TimeUnit.NANOSECONDS); } } }如果满足条件则会生成一个 IdleStateEvent 事件。
SpringBoot 监控由于整合了 SpringBoot 之后不但可以利用 Spring 帮我们管理对象,也可以利用它来做应用监控。
actuator 监控当我们为引入了:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>就开启了 SpringBoot 的 actuator 监控功能,他可以暴露出很多监控端点供我们使用。
如一些应用中的一些统计数据:
存在的 Beans:
更多信息请查看:https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html
但是如果我想监控现在我的服务端有多少客户端连上来了,分别的 ID 是多少?
其实就是实时查看我内部定义的那个关联关系的 Map。
这就需要暴露自定义端点了。
自定义端点暴露的方式也很简单:
继承 AbstractEndpoint 并复写其中的 invoke 函数:
public class CustomEndpoint extends AbstractEndpoint<Map<Long,NioSocketChannel>> { /** * 监控端点的 访问地址 * @param id */ public CustomEndpoint(String id) { //false 表示不是敏感端点 super(id, false); } @Override public Map<Long, NioSocketChannel> invoke() { return NettySocketHolder.getMAP(); } }其实就是返回了 Map 中的数据。
再配置一个该类型的 Bean 即可:
@Configuration public class EndPointConfig { @Value("${monitor.channel.map.key}") private String channelMap; @Bean public CustomEndpoint buildEndPoint(){ CustomEndpoint customEndpoint = new CustomEndpoint(channelMap) ; return customEndpoint ; } }这样我们就可以通过配置文件中的 monitor.channel.map.key 来访问了:
一个客户端连接时:
两个客户端连接时:
这样其实监控功能已经可以满足了,但能不能展示的更美观、并且多个应用也可以方便查看呢?
有这样的开源工具帮我们做到了:
https://github.com/codecentric/spring-boot-admin
简单来说我们可以利用该工具将 actuator 暴露出来的接口可视化并聚合的展示在页面中:
接入也很简单,首先需要引入依赖:
<dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-starter-client</artifactId> </dependency>并在配置文件中加入:
# 关闭健康检查权限 management.security.enabled=false # SpringAdmin 地址 spring.boot.admin.url=http://127.0.0.1:8888在启动应用之前先讲 SpringBootAdmin 部署好: