com.alibaba.csp.sentinel.cluster.server.handler.TokenServerHandler Maven / Gradle / Ivy
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.csp.sentinel.cluster.server.handler;
import java.net.InetSocketAddress;
import com.alibaba.csp.sentinel.cluster.ClusterConstants;
import com.alibaba.csp.sentinel.cluster.request.ClusterRequest;
import com.alibaba.csp.sentinel.cluster.response.ClusterResponse;
import com.alibaba.csp.sentinel.cluster.server.connection.ConnectionManager;
import com.alibaba.csp.sentinel.cluster.server.connection.ConnectionPool;
import com.alibaba.csp.sentinel.cluster.server.processor.RequestProcessor;
import com.alibaba.csp.sentinel.cluster.server.processor.RequestProcessorProvider;
import com.alibaba.csp.sentinel.log.RecordLog;
import com.alibaba.csp.sentinel.util.StringUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
/**
* Netty server handler for Sentinel token server.
*
* @author Eric Zhao
* @since 1.4.0
*/
public class TokenServerHandler extends ChannelInboundHandlerAdapter {
private final ConnectionPool globalConnectionPool;
public TokenServerHandler(ConnectionPool globalConnectionPool) {
this.globalConnectionPool = globalConnectionPool;
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
globalConnectionPool.createConnection(ctx.channel());
String remoteAddress = getRemoteAddress(ctx);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
String remoteAddress = getRemoteAddress(ctx);
globalConnectionPool.remove(ctx.channel());
ConnectionManager.removeConnection(remoteAddress);
}
@Override
@SuppressWarnings("unchecked")
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
globalConnectionPool.refreshLastReadTime(ctx.channel());
if (msg instanceof ClusterRequest) {
ClusterRequest request = (ClusterRequest)msg;
// Client ping with its namespace, add to connection manager.
if (request.getType() == ClusterConstants.MSG_TYPE_PING) {
handlePingRequest(ctx, request);
return;
}
// Pick request processor for request type.
RequestProcessor, ?> processor = RequestProcessorProvider.getProcessor(request.getType());
if (processor == null) {
RecordLog.warn("[TokenServerHandler] No processor for request type: " + request.getType());
writeBadResponse(ctx, request);
} else {
ClusterResponse> response = processor.processRequest(request);
writeResponse(ctx, response);
}
}
}
private void writeBadResponse(ChannelHandlerContext ctx, ClusterRequest request) {
ClusterResponse> response = new ClusterResponse<>(request.getId(), request.getType(),
ClusterConstants.RESPONSE_STATUS_BAD, null);
writeResponse(ctx, response);
}
private void writeResponse(ChannelHandlerContext ctx, ClusterResponse response) {
ctx.writeAndFlush(response);
}
private void handlePingRequest(ChannelHandlerContext ctx, ClusterRequest request) {
if (request.getData() == null || StringUtil.isBlank((String)request.getData())) {
writeBadResponse(ctx, request);
return;
}
String namespace = (String)request.getData();
String clientAddress = getRemoteAddress(ctx);
// Add the remote namespace to connection manager.
int curCount = ConnectionManager.addConnection(namespace, clientAddress).getConnectedCount();
int status = ClusterConstants.RESPONSE_STATUS_OK;
ClusterResponse response = new ClusterResponse<>(request.getId(), request.getType(), status, curCount);
writeResponse(ctx, response);
}
private String getRemoteAddress(ChannelHandlerContext ctx) {
if (ctx.channel().remoteAddress() == null) {
return null;
}
InetSocketAddress inetAddress = (InetSocketAddress) ctx.channel().remoteAddress();
return inetAddress.getAddress().getHostAddress() + ":" + inetAddress.getPort();
}
}