Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.logicbus.backend.server.MessageRouter Maven / Gradle / Ivy
package com.logicbus.backend.server;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alogic.tracer.Tool;
import com.alogic.tracer.TraceContext;
import com.anysoft.util.BaseException;
import com.anysoft.util.PropertiesConstants;
import com.anysoft.util.Settings;
import com.logicbus.backend.AccessController;
import com.logicbus.backend.Context;
import com.logicbus.backend.Servant;
import com.logicbus.backend.ServantException;
import com.logicbus.backend.ServantFactory;
import com.logicbus.backend.ServantPool;
import com.logicbus.backend.ServantWorkerThread;
import com.logicbus.backend.bizlog.BizLogItem;
import com.logicbus.backend.bizlog.BizLogger;
import com.logicbus.models.catalog.Path;
import com.logicbus.models.servant.ServiceDescription;
/**
* 消息路由器
*
* @author duanyy
*
* @version 1.0.1 [20140402 duanyy]
* - {@link com.logicbus.backend.AccessController AccessController}有更新
*
* @version 1.0.2 [20140407 duanyy]
* - 采用{@link java.util.concurrent.CountDownLatch CountDownLatch}来和工作进程通讯.
*
* @version 1.0.5 [20140412 duanyy]
* - 改进消息传递模型
*
* @version 1.2.2 [20140417 duanyy]
* - 增加非线程调度模式
*
* @version 1.2.3 [20140617 duanyy]
* - 增加业务日志的采集功能
*
* @version 1.2.6 [20140807 duanyy]
* - ServantPool和ServantFactory插件化
*
* @version 1.2.6.4 [20140820 duanyy]
* - 修正servant实例无法获取到,抛出NullPointException问题
*
* @version 1.2.7 [20140828 duanyy]
* - 重写BizLogger
*
* @version 1.2.7.1 [20140902 duanyy]
* - BizLogItem去掉host属性
*
* @version 1.2.7.2 [20140910 duanyy]
* - 修正bizlog日志中client的取值
*
* @version 1.2.8 [20140917 duanyy]
* - Handler:handle和flush方法增加timestamp参数,以便时间同步
*
* @version 1.3.0.1 [20141029 duanyy]
* - 当所访问的服务不存在时,以一个统一的服务名(/core/Null)来进行日志记录
*
* @version 1.4.0 [20141117 duanyy]
* - Servant体系抛弃MessageDoc
*
* @version 1.6.4.11 [20151116 duanyy]
* - 日志类型为none的服务日志也将输出到bizlog
*
* @version 1.6.5.6 [20160523 duanyy]
* - bizlog增加报文长度
* - 在action中提前写出报文
* - 增加trace日志
*
* @version 1.6.7.3 [20170118 duanyy]
* - 对tlog的开启开关进行了统一
*
* @version 1.6.7.4 [20170118 duanyy]
* - 服务耗时单位改为ns
*
* @version 1.6.7.9 [20170201 duanyy]
* - 采用SLF4j日志框架输出日志
*
* @version 1.6.7.15 [20170221 duanyy]
* - 增加bizlog.enable环境变量,以便关闭bizlog
* - 增加acm.enable环境变量,以便关闭ac控制器
*
* @version 1.6.7.20
* - 改造ServantManager模型,增加服务配置监控机制
*
* @version 1.6.8.3 [20170328 duanyy]
* - 修正tlog输出,将参数和错误原因分离开来
*
* @version 1.6.9.8 [20170821 duanyy]
* - 优化代码
*
* @version 1.6.9.9 [20170829 duanyy]
* - Pool的returnObject接口增加是否出错的参数
*
* @version 1.6.10.9 [20171124 duanyy]
* - 规范化URL和URI的取值
*/
public class MessageRouter {
/**
* a logger of log4j
*/
protected static Logger logger = LoggerFactory.getLogger(MessageRouter.class);
/**
* 服务调用
* @param id 服务id
* @param ctx 上下文
* @param ac 访问控制器
* @return 调用结果
*/
static public int action(Path id,Context ctx,AccessController ac){
ServantPool pool = null;
Servant servant = null;
String sessionId = "";
TraceContext tc = null;
if (tracerEnable){
tc = Tool.start(ctx.getGlobalSerial(), ctx.getGlobalSerialOrder());
}
try{
//访问开始
ctx.setStartTime(System.nanoTime());
//获取服务实例池
ServantFactory factory = servantFactory;
pool = factory.getPool(id);
if (!pool.isRunning()){
throw new ServantException("core.e1009",
"The Service is paused:service id:" + id);
}
//通过访问控制器获取访问优先级
int priority = 0;
if (acmEnable && null != ac){
sessionId = ac.createSessionId(id, pool.getDescription(), ctx);
priority = ac.accessStart(sessionId,id, pool.getDescription(), ctx);
if (priority < 0){
logger.info("Unauthorized Access:" + ctx.getClientIp() + ",url:" + ctx.getRequestURL());
ctx.setReturn("core.e1010","Permission denied!service id: "+ id);
return 0;
}
}
//从服务实例池中拿服务实例,并执行
servant = pool.borrowObject(priority);
if (servant == null){
logger.warn("Can not get a servant from pool in the limited time,check servant.queueTimeout variable.");
ctx.setReturn("core.e1011", "Can not get a servant from pool in the limited time,check servant.queueTimeout variable.");
}else{
if (!threadMode){
//在非线程模式下,不支持服务超时
execute(servant,ctx);
}else{
CountDownLatch latch = new CountDownLatch(1);
ServantWorkerThread thread = new ServantWorkerThread(servant,ctx,latch,tc != null ? tc.newChild() : null);
thread.start();
if (!latch.await(servant.getTimeOutValue(), TimeUnit.MILLISECONDS)){
ctx.setReturn("core.e1011","Time out or interrupted.");
}
thread = null;
}
}
}catch (ServantException ex){
ctx.setReturn(ex.getCode(), ex.getMessage());
logger.error(ExceptionUtils.getStackTrace(ex));
}catch (BaseException ex){
ctx.setReturn(ex.getCode(), ex.getMessage());
logger.error(ExceptionUtils.getStackTrace(ex));
}catch (Exception ex){
ctx.setReturn("core.e1012",ex.getMessage());
logger.error(ExceptionUtils.getStackTrace(ex));
}catch (Throwable t){
ctx.setReturn("core.e1012",t.getMessage());
logger.error(ExceptionUtils.getStackTrace(t));
}
finally {
ctx.setEndTime(System.nanoTime());
if (ctx != null){
ctx.finish();
}
if (pool != null){
if (servant != null){
pool.returnObject(servant,false);
}
pool.visited(ctx.getDuration(),ctx.getReturnCode());
if (acmEnable && ac != null){
ac.accessEnd(sessionId,id, pool.getDescription(), ctx);
}
}
if (bizlogEnable && bizLogger != null){
//需要记录日志
log(id,sessionId,pool == null ? null : pool.getDescription(),ctx);
}
if (tracerEnable){
boolean ok = ctx.getReturnCode().equals("core.ok");
Tool.end(tc, "ALOGIC", id.getPath(), ok ?"OK":"FAILED",
String.format("[%s]%s", ctx.getClientIp(),ctx.getReason()),ctx.getQueryString(),ctx.getKeyword(), ctx.getContentLength());
}
}
return 0;
}
protected static int log(Path id,String sessionId,ServiceDescription sd,Context ctx){
ServiceDescription.LogType logType =
(sd != null) ? sd.getLogType():ServiceDescription.LogType.brief;
BizLogItem item = new BizLogItem();
item.logType = logType;
item.sn = ctx.getGlobalSerial();
item.id = (sd != null)?id.toString():"/core/Null";
item.clientIP = ctx.getClientIp();
//当无法取到sessionId时,直接取ip(当服务找不到时)
item.client = sessionId != null && sessionId.length() > 0 ? sessionId : item.clientIP;
//item.host = ctx.getHost();
item.result = ctx.getReturnCode();
item.reason = ctx.getReason();
item.startTime = ctx.getTimestamp();
item.duration = ctx.getDuration();
item.url = ctx.getRequestURL();
item.content = logType == ServiceDescription.LogType.detail ? ctx.toString() : null;
item.contentLength = ctx.getContentLength();
bizLogger.handle(item,System.currentTimeMillis());
return 0;
}
protected static int execute(Servant servant,Context ctx) {
servant.actionBefore( ctx);
servant.actionProcess( ctx);
servant.actionAfter( ctx);
return 0;
}
protected static boolean threadMode = true;
protected static boolean tracerEnable = false;
protected static BizLogger bizLogger = null;
protected static ServantFactory servantFactory = null;
protected static boolean bizlogEnable = true;
protected static boolean acmEnable = true;
static {
Settings settings = Settings.get();
//初始化threadMode
threadMode = PropertiesConstants.getBoolean(settings, "servant.threadMode", true);
tracerEnable = PropertiesConstants.getBoolean(settings, "tracer.servant.enable", false);
bizlogEnable = PropertiesConstants.getBoolean(settings, "bizlog.enable", true);
acmEnable = PropertiesConstants.getBoolean(settings, "acm.enable", true);
bizLogger = (BizLogger) settings.get("bizLogger");
servantFactory = (ServantFactory) settings.get("servantFactory");
}
}