All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.logicbus.backend.server.MessageRouter Maven / Gradle / Ivy

There is a newer version: 1.6.17
Show newest version
package com.logicbus.backend.server;


import com.logicbus.backend.*;
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.bizlog.BizLogItem;
import com.logicbus.backend.bizlog.BizLogger;
import com.logicbus.models.catalog.Path;
import com.logicbus.models.servant.ServiceDescription;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 消息路由器
 * 
 * @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的取值
* * @version 1.6.11.29 [20180510 duanyy]
* - 优化错误处理
* * @version 1.6.12.29 [20190409]
* - 优化底层的错误代码的处理;
*/ public class MessageRouter { /** * a logger of log4j */ protected static Logger logger = LoggerFactory.getLogger(MessageRouter.class); static public int action(Normalizer normalizer, HttpServletRequest request, Context ctx, AccessController ac){ Normalizer finalNormalizer = servantFactory.getNormalizer(normalizer); Path id = finalNormalizer.normalize(ctx,request); AccessController finalAc = servantFactory.getAccessController(ac); return action(id,ctx,finalAc); } /** * 服务调用 * @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 == null){ doException(id,sessionId,factory.getExceptionHandler(),ctx,"core.e1003","Service does not exist."); return 0; } //通过访问控制器获取访问优先级 int priority = 0; if (acmEnable && null != ac){ try { sessionId = ac.createSessionId(id, pool.getDescription(), ctx); priority = ac.accessStart(sessionId,id, pool.getDescription(), ctx); if (priority < 0){ doException(id,sessionId,pool.getExceptionHandler(),ctx,"core.e1010","Permission denied"); return 0; } }catch (BaseException ex){ doException(id,sessionId,pool.getExceptionHandler(),ctx,ex.getCode(),ex.getMessage()); return 0; } } //从服务实例池中拿服务实例,并执行 servant = pool.borrowObject(priority); if (servant == null){ doException(id,sessionId,pool.getExceptionHandler(),ctx,"core.e1013","Can not get a servant from pool in the limited time"); return 0; } try { doExecute(id,sessionId,servant, ctx); }catch (BaseException ex){ doException(id,sessionId,servant,ctx,ex.getCode(),ex.getMessage()); } }catch (Throwable t){ ctx.setReturn(HttpServletResponse.SC_OK,"core.e1012",t.getMessage()); logger.error("Service=" + id.getPath()); logger.error(ExceptionUtils.getStackTrace(t)); } finally { ctx.setEndTime(System.nanoTime()); 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 (ctx != null) { ctx.finish(); } 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)?PropertiesConstants.getString(ctx,"$api",id.toString(),true):"/core/Null"; item.clientIP = ctx.getClientIp(); //当无法取到sessionId时,直接取ip(当服务找不到时) item.client = sessionId != null && sessionId.length() > 0 ? sessionId : item.clientIP; 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 doExecute(Path id,String sessionId,Servant servant,Context ctx) { servant.actionBefore(ctx); servant.actionProcess(ctx); servant.actionAfter(ctx); return 0; } protected static int doException(Path id,String sessionId,Servant servant,Context ctx,String code,String message) { logger.error(String.format("[%s-%s]-%s-%s:%s,query=%s",ctx.getClientIp(),id.toString(),sessionId,code,message,ctx.getQueryString())); ctx.setReturn(HttpServletResponse.SC_OK,code, message); if (servant != null){ servant.actionException(ctx,code,message); } return 0; } 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(); 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"); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy