/*
* Copyright 2008-2009 the original author or authors.
*
* 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 net.hasor.rsf.rpc.caller;
import io.netty.util.Timeout;
import io.netty.util.TimerTask;
import net.hasor.core.Hasor;
import net.hasor.core.Provider;
import net.hasor.core.future.FutureCallback;
import net.hasor.core.provider.InstanceProvider;
import net.hasor.rsf.*;
import net.hasor.rsf.container.RsfBeanContainer;
import net.hasor.rsf.domain.*;
import net.hasor.rsf.domain.provider.AddressProvider;
import net.hasor.rsf.utils.ProtocolUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 负责管理所有 RSF 发起的请求,Manager还提供了最大并发上限的配置.
* @version : 2014年9月12日
* @author 赵永春(zyc@hasor.net)
*/
public abstract class RsfRequestManager {
protected static Logger logger = LoggerFactory.getLogger(RsfRequestManager.class);
protected static Logger invLogger = LoggerFactory.getLogger(RsfConstants.LoggerName_Invoker);
private final ConcurrentMap<Long, RsfFuture> rsfResponse;
private final RsfContext rsfContext;
private final AtomicInteger requestCount;
private final SenderListener senderListener;
//
public RsfRequestManager(RsfContext rsfContext, SenderListener senderListener) {
senderListener = Hasor.assertIsNotNull(senderListener, "not found SendData.");
this.rsfContext = rsfContext;
this.rsfResponse = new ConcurrentHashMap<Long, RsfFuture>();
this.requestCount = new AtomicInteger(0);
this.senderListener = senderListener;
}
/**获取RSF容器对象。*/
public RsfContext getContext() {
return this.rsfContext;
}
/**获取{@link RsfBeanContainer}。*/
public abstract RsfBeanContainer getContainer();
/**发送数据包*/
private void sendData(Provider<InterAddress> target, RequestInfo info) {
this.senderListener.sendRequest(target, info);
}
//
/**
* 获取正在进行中的调用请求。
* @param requestID 请求ID
* @return 返回RsfFuture。
*/
public RsfFuture getRequest(long requestID) {
return this.rsfResponse.get(requestID);
}
/**
* 响应挂起的Request请求。
* @param info 响应结果
*/
public boolean putResponse(ResponseInfo info) {
long requestID = info.getRequestID();
RsfFuture rsfFuture = this.rsfResponse.get(requestID);
if (rsfFuture == null) {
invLogger.warn("response({}) -> timeoutFailed, RsfFuture is not exist. -> maybe is timeout!", requestID);
return false;
}
//
// 1.处理ACK应答 -> (Invoke类型调用,不处理ACK应答)
if (info.getStatus() == ProtocolStatus.Accept) {
if (!rsfFuture.getRequest().isMessage()) {
invLogger.info("response({}) -> ignore, rpcType = Invoke, status = Accept", requestID);
return true;/* Invoker类型request不处理 ack 应答,只有Message类型请求才会把ACK应答作为response进行处理。 */
}
}
//
// 2.处理response
rsfFuture = this.removeRsfFuture(requestID);
if (rsfFuture == null) {
invLogger.warn("response({}) -> timeoutFailed, RsfFuture is not exist. -> maybe is timeout!", requestID);
return false;
}
//
// 3.反序列化
RsfRequest rsfRequest = rsfFuture.getRequest();
RsfResponseObject local = new RsfResponseObject(rsfRequest);
local.addOptionMap(info);
local.sendStatus(info.getStatus());
String serializeType = info.getSerializeType();
String bindID = local.getBindInfo().getBindID();
Method callMethod = rsfRequest.getMethod();
int length = info.getReturnData() == null ? 0 : info.getReturnData().length;
invLogger.info("response({}) -> receiveTime ={}, serializeType ={}, status ={}, dataLength ={}, isMessage ={}, bindID ={}, callMethod ={}.",//
requestID, info.getReceiveTime(), serializeType, info.getStatus(), length, rsfRequest.isMessage(), bindID, callMethod);
//
// - Message 调用
if (rsfRequest.isMessage()) {
Class<?> returnType = rsfRequest.getMethod().getReturnType();
RsfResultDO returnObject = null;
if (info.getStatus() == ProtocolStatus.Accept) {
returnObject = new RsfResultDO(requestID, true);
} else {
returnObject = new RsfResultDO(requestID, false);
returnObject.setErrorCode(info.getStatus());
returnObject.setErrorMessage(info.getOption("message"));
}
//
if (returnObject.isSuccess()) {
invLogger.info("response({}) -> successful.", requestID);
if (returnType.isAssignableFrom(RsfResult.class)) {
local.sendData(returnObject);
return rsfFuture.completed(local);
}
if (returnObject.isSuccess()) {
local.sendData(null);
return rsfFuture.completed(local);
}
}
//
String errorInfo = "errorCode = " + returnObject.getErrorCode() + ", errorMessage=" + returnObject.getErrorMessage();
invLogger.error("response({}) -> invokeFailed, {}", requestID, errorInfo);
return rsfFuture.failed(new RsfException(local.getStatus(), errorInfo));
}
// - Invoker 调用
if (info.getStatus() == ProtocolStatus.OK) {
SerializeCoder coder = this.getContext().getEnvironment().getSerializeCoder(serializeType);
Class<?> returnType = rsfRequest.getMethod().getReturnType();
try {
byte[] returnDataData = info.getReturnData();
Object returnObject = coder.decode(returnDataData, returnType);
local.sendData(returnObject);
} catch (Throwable e) {
invLogger.error("response({}) -> serializeFailed, bindID ={}, serializeType ={}, callMethod ={}, dataType ={}, message ={}.",//
requestID, bindID, serializeType, callMethod, returnType, e.getMessage(), e);
return rsfFuture.failed(e);
}
return rsfFuture.completed(local);
} else {
invLogger.error("response({}) -> statusFailed, bindID ={}, status ={}.",//
requestID, bindID, local.getStatus());
return rsfFuture.failed(new RsfException(local.getStatus(), "status."));
}
}
/**
* 响应挂起的Request请求。
* @param requestID 请求ID
* @param e 异常响应
*/
public void putResponse(long requestID, Throwable e) {
RsfFuture rsfFuture = this.removeRsfFuture(requestID);
if (rsfFuture != null) {
invLogger.error("response({}) -> errorFailed, {}", requestID, e.getMessage(), e);
rsfFuture.failed(e);
} else {
invLogger.error("response({}) -> errorFailed, RsfFuture is not exist. -> maybe is timeout! ,error= {}.", requestID, e.getMessage(), e);
}
}
private RsfFuture removeRsfFuture(long requestID) {
RsfFuture rsfFuture = this.rsfResponse.remove(requestID);
if (rsfFuture != null) {
this.requestCount.decrementAndGet();// i--;
}
return rsfFuture;
}
/**
* 发送RSF调用请求。
* @param rsfRequest rsf请求
* @param listener FutureCallback回调监听器。
* @return 返回RsfFuture。
*/
protected RsfFuture doSendRequest(RsfRequestFormLocal rsfRequest, FutureCallback<RsfResponse> listener) {
RsfBindInfo<?> bindInfo = rsfRequest.getBindInfo();
String serviceID = bindInfo.getBindID();
final RsfFuture rsfFuture = new RsfFuture(rsfRequest, listener);
invLogger.info("request({}) -> doSendRequest, bindID ={}, callMethod ={}, isMessage ={}.", //
rsfRequest.getRequestID(), serviceID, rsfRequest.getMethod(), bindInfo.isMessage());
//
if (bindInfo.isMessage()) {
rsfRequest.addOption("RPC_TYPE", "MESSAGE");
} else {
rsfRequest.addOption("RPC_TYPE", "INVOKER");
}
rsfRequest.addOptionMap(this.getContext().getSettings().getClientOption());//写入客户端选项,并将选项发送到Server。
Provider<RsfFilter>[] rsfFilterList = this.getContainer().getFilterProviders(serviceID);
RsfResponseObject res = new RsfResponseObject(rsfRequest);
//
try {
/*下面这段代码要负责 -> 执行rsfFilter过滤器链,并最终调用sendRequest发送请求。*/
new RsfFilterHandler(rsfFilterList, new RsfFilterChain() {
public void doFilter(RsfRequest request, RsfResponse response) throws Throwable {
if (response.isResponse()) {
invLogger.info("request({}) -> sendRequest, response form local.", request.getRequestID());
rsfFuture.completed(response);//如果本地调用链已经做出了响应,那么不在需要发送到远端。
} else {
invLogger.info("request({}) -> sendRequest, response wait for remote.", request.getRequestID());
sendRequest(rsfFuture);//发送请求到远方
}
}
}).doFilter(rsfRequest, res);
} catch (Throwable e) {
invLogger.error("request({}) -> errorFailed, sendRequest, doRsfFilterChain. error ={}.", rsfRequest.getRequestID(), e.getMessage(), e);
try {
rsfFuture.failed(e);
} catch (Throwable e2) {
logger.error("request({}) -> {}.", rsfRequest.getRequestID(), e2.getMessage(), e2);
}
}
return rsfFuture;
}
/**将请求发送到远端服务器。*/
private void sendRequest(final RsfFuture rsfFuture) throws Throwable {
/*1.远程目标机*/
final RsfRequestFormLocal rsfRequest = (RsfRequestFormLocal) rsfFuture.getRequest();
final AddressProvider target = rsfRequest.getTarget();
String serviceID = rsfRequest.getBindInfo().getBindID();
invLogger.info("request({}) -> bindID ={}, callMethod ={}, serializeType ={}, isMessage ={}, isP2PCalls ={}.",//
rsfRequest.getRequestID(), serviceID, rsfRequest.getMethod(), rsfRequest.getSerializeType(), rsfRequest.isMessage(), rsfRequest.isP2PCalls());
//
/*2.发送之前的检查(允许的最大并发请求数)*/
RsfSettings rsfSettings = this.getContainer().getEnvironment().getSettings();
if (this.requestCount.get() >= rsfSettings.getMaximumRequest()) {
SendLimitPolicy sendPolicy = rsfSettings.getSendLimitPolicy();
String errorMessage = "request(" + rsfRequest.getRequestID() + ") -> sendDataFailed, maximum number of requests, apply SendPolicy = " + sendPolicy.name();
invLogger.error(errorMessage);
if (sendPolicy == SendLimitPolicy.Reject) {
// - A.直接抛异常
throw new RsfException(ProtocolStatus.SendLimitPolicy, errorMessage);
} else {
// - B.等待1秒之后重新尝试,如果依然资源不足,那么抛异常
try {
Thread.sleep(1000);/*SendLimitPolicy.WaitSecond*/
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
if (this.requestCount.get() >= rsfSettings.getMaximumRequest()) {
invLogger.error(errorMessage);
throw new RsfException(ProtocolStatus.SendLimitPolicy, errorMessage);
}
}
}
/*3.准备发送数据*/
String methodName = rsfRequest.getMethod().getName();
Object[] args = rsfRequest.getParameterObject();
InterAddress address = target.get(serviceID, methodName, args);
if (address == null) {
invLogger.warn("request({}) -> targetAddress Unavailable, bindID ={}.", rsfRequest.getRequestID(), serviceID);
rsfFuture.failed(new RsfException(ProtocolStatus.Forbidden, "Service [" + serviceID + "] Address Unavailable."));
return;
}
if (rsfRequest.isP2PCalls()) {
rsfRequest.addOption(OptionKeys.TargetAddress, address.toHostSchema());
}
/*4.发送请求*/
try {
Provider<InterAddress> targetProvider = new InstanceProvider<InterAddress>(address);
invLogger.warn("request({}) -> pre sendData, bindID ={}, targetAddress ={}.", rsfRequest.getRequestID(), serviceID, address);
RsfEnvironment environment = this.getContext().getEnvironment();
startRequest(rsfFuture); // <- 1.计时request。
RequestInfo info = ProtocolUtils.buildRequestInfo(environment, rsfRequest); // <- 2.生成RequestInfo
sendData(targetProvider, info); // <- 3.发送数据
} catch (Throwable e) {
invLogger.error("request(" + rsfRequest.getRequestID() + ") send error, " + e.getMessage(), e);
putResponse(rsfRequest.getRequestID(), e);
}
}
/**
* 负责客户端引发的超时逻辑。
* @param rsfFuture 开始计时的请求。
*/
private void startRequest(RsfFuture rsfFuture) {
this.requestCount.incrementAndGet();// i++;
this.rsfResponse.put(rsfFuture.getRequest().getRequestID(), rsfFuture);
final RsfRequestFormLocal request = (RsfRequestFormLocal) rsfFuture.getRequest();
TimerTask timeTask = new TimerTask() {
public void run(Timeout timeoutObject) throws Exception {
RsfFuture rsfCallBack = getRequest(request.getRequestID());
/*检测不到说明请求已经被正确响应。*/
if (rsfCallBack == null)
return;
/*异常信息*/
String errorInfo = "request(" + request.getRequestID() + ") -> timeout for client.";
invLogger.error(errorInfo);
/*回应Response*/
putResponse(request.getRequestID(), new RsfTimeoutException(errorInfo));
}
};
invLogger.info("request({}) -> startRequest, timeout at {} ,bindID ={}, callMethod ={}.", //
request.getRequestID(), request.getTimeout(), request.getBindInfo().getBindID(), request.getMethod());
this.getContext().getEnvironment().atTime(timeTask, request.getTimeout());
}
}