pre探针tomcat连接池内同一级别线程池传递问题

编程

//拦截tomcat类:

/*

* Licensed to the Apache Software Foundation (ASF) under one or more

* contributor license agreements. See the NOTICE file distributed with

* this work for additional information regarding copyright ownership.

* The ASF licenses this file to You 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 org.apache.catalina.core;

import java.io.IOException;

import java.util.concurrent.atomic.AtomicInteger;

import javax.servlet.DispatcherType;

import javax.servlet.RequestDispatcher;

import javax.servlet.Servlet;

import javax.servlet.ServletException;

import javax.servlet.UnavailableException;

import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.Context;

import org.apache.catalina.Globals;

import org.apache.catalina.LifecycleException;

import org.apache.catalina.connector.ClientAbortException;

import org.apache.catalina.connector.Request;

import org.apache.catalina.connector.Response;

import org.apache.catalina.valves.ValveBase;

import org.apache.tomcat.util.ExceptionUtils;

import org.apache.tomcat.util.buf.MessageBytes;

import org.apache.tomcat.util.log.SystemLogHandler;

import org.apache.tomcat.util.res.StringManager;

import com.preapm.sdk.zipkin.ZipkinClientContext;

import kafka.utils.threadsafe;

import scala.util.Random;

import zipkin.Span;

/**

* Valve that implements the default basic behavior for the

* <code>StandardWrapper</code> container implementation.

*

* @author Craig R. McClanahan

*/

final class StandardWrapperValve

extends ValveBase {

static ThreadLocal<Long> longLocal = new InheritableThreadLocal<Long>();

static ThreadLocalSpanStore localSpanStore = new ThreadLocalSpanStore();

//------------------------------------------------------ Constructor

public StandardWrapperValve() {

super(true);

}

// ----------------------------------------------------- Instance Variables

// Some JMX statistics. This valve is associated with a StandardWrapper.

// We expose the StandardWrapper as JMX ( j2eeType=Servlet ). The fields

// are here for performance.

private volatile long processingTime;

private volatile long maxTime;

private volatile long minTime = Long.MAX_VALUE;

private final AtomicInteger requestCount = new AtomicInteger(0);

private final AtomicInteger errorCount = new AtomicInteger(0);

/**

* The string manager for this package.

*/

private static final StringManager sm =

StringManager.getManager(Constants.Package);

// --------------------------------------------------------- Public Methods

/**

* Invoke the servlet we are managing, respecting the rules regarding

* servlet lifecycle and SingleThreadModel support.

*

* @param request Request to be processed

* @param response Response to be produced

*

* @exception IOException if an input/output error occurred

* @exception ServletException if a servlet error occurred

*/

@Override

public final void invoke(Request request, Response response)

throws IOException, ServletException {

/*if(longLocal.get()!=null) {

System.out.println("============="+Thread.currentThread().getName()+"====get="+longLocal.get());

}else {

Long l = new Random().nextLong();

longLocal.set(l);

System.out.println("============="+Thread.currentThread().getName()+"====set="+l );

}*/

String url = request.getRequestURI();

localSpanStore.startSpan("tomcat");

Span startSpanZ = localSpanStore.getSpan().build();

//System.out.println("nameZZZ=="+Thread.currentThread().getName()+" Span="+startSpanZ.id + " parentId= "+startSpanZ.parentId + " traceId= "+startSpanZ.traceId);

// ZipkinClientContext.getClient().startSpan("tomcat");

Span startSpan = ZipkinClientContext.getClient().getSpan();

System.out.println("url=="+url+" name=="+Thread.currentThread().getName()+" Span="+startSpan.id + " parentId= "+startSpan.parentId + " traceId= "+startSpan.traceId);

/*try {

Thread.sleep(20000);

} catch (InterruptedException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}*/

// Initialize local variables we may need

boolean unavailable = false;

Throwable throwable = null;

// This should be a Request attribute...

long t1=System.currentTimeMillis();

requestCount.incrementAndGet();

StandardWrapper wrapper = (StandardWrapper) getContainer();

Servlet servlet = null;

Context context = (Context) wrapper.getParent();

// Check for the application being marked unavailable

if (!context.getState().isAvailable()) {

response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,

sm.getString("standardContext.isUnavailable"));

unavailable = true;

}

// Check for the servlet being marked unavailable

if (!unavailable && wrapper.isUnavailable()) {

container.getLogger().info(sm.getString("standardWrapper.isUnavailable",

wrapper.getName()));

long available = wrapper.getAvailable();

if ((available > 0L) && (available < Long.MAX_VALUE)) {

response.setDateHeader("Retry-After", available);

response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,

sm.getString("standardWrapper.isUnavailable",

wrapper.getName()));

} else if (available == Long.MAX_VALUE) {

response.sendError(HttpServletResponse.SC_NOT_FOUND,

sm.getString("standardWrapper.notFound",

wrapper.getName()));

}

unavailable = true;

}

// Allocate a servlet instance to process this request

try {

if (!unavailable) {

servlet = wrapper.allocate();

}

} catch (UnavailableException e) {

container.getLogger().error(

sm.getString("standardWrapper.allocateException",

wrapper.getName()), e);

long available = wrapper.getAvailable();

if ((available > 0L) && (available < Long.MAX_VALUE)) {

response.setDateHeader("Retry-After", available);

response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,

sm.getString("standardWrapper.isUnavailable",

wrapper.getName()));

} else if (available == Long.MAX_VALUE) {

response.sendError(HttpServletResponse.SC_NOT_FOUND,

sm.getString("standardWrapper.notFound",

wrapper.getName()));

}

} catch (ServletException e) {

container.getLogger().error(sm.getString("standardWrapper.allocateException",

wrapper.getName()), StandardWrapper.getRootCause(e));

throwable = e;

exception(request, response, e);

} catch (Throwable e) {

ExceptionUtils.handleThrowable(e);

container.getLogger().error(sm.getString("standardWrapper.allocateException",

wrapper.getName()), e);

throwable = e;

exception(request, response, e);

servlet = null;

}

MessageBytes requestPathMB = request.getRequestPathMB();

DispatcherType dispatcherType = DispatcherType.REQUEST;

if (request.getDispatcherType()==DispatcherType.ASYNC) dispatcherType = DispatcherType.ASYNC;

request.setAttribute(Globals.DISPATCHER_TYPE_ATTR,dispatcherType);

request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR,

requestPathMB);

// Create the filter chain for this request

ApplicationFilterChain filterChain =

ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);

// Call the filter chain for this request

// NOTE: This also calls the servlet"s service() method

try {

if ((servlet != null) && (filterChain != null)) {

// Swallow output if needed

if (context.getSwallowOutput()) {

try {

SystemLogHandler.startCapture();

if (request.isAsyncDispatching()) {

request.getAsyncContextInternal().doInternalDispatch();

} else {

filterChain.doFilter(request.getRequest(),

response.getResponse());

}

} finally {

String log = SystemLogHandler.stopCapture();

if (log != null && log.length() > 0) {

context.getLogger().info(log);

}

}

} else {

if (request.isAsyncDispatching()) {

request.getAsyncContextInternal().doInternalDispatch();

} else {

filterChain.doFilter

(request.getRequest(), response.getResponse());

}

}

}

} catch (ClientAbortException e) {

throwable = e;

exception(request, response, e);

} catch (IOException e) {

container.getLogger().error(sm.getString(

"standardWrapper.serviceException", wrapper.getName(),

context.getName()), e);

throwable = e;

exception(request, response, e);

} catch (UnavailableException e) {

container.getLogger().error(sm.getString(

"standardWrapper.serviceException", wrapper.getName(),

context.getName()), e);

// throwable = e;

// exception(request, response, e);

wrapper.unavailable(e);

long available = wrapper.getAvailable();

if ((available > 0L) && (available < Long.MAX_VALUE)) {

response.setDateHeader("Retry-After", available);

response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,

sm.getString("standardWrapper.isUnavailable",

wrapper.getName()));

} else if (available == Long.MAX_VALUE) {

response.sendError(HttpServletResponse.SC_NOT_FOUND,

sm.getString("standardWrapper.notFound",

wrapper.getName()));

}

// Do not save exception in "throwable", because we

// do not want to do exception(request, response, e) processing

} catch (ServletException e) {

Throwable rootCause = StandardWrapper.getRootCause(e);

if (!(rootCause instanceof ClientAbortException)) {

container.getLogger().error(sm.getString(

"standardWrapper.serviceExceptionRoot",

wrapper.getName(), context.getName(), e.getMessage()),

rootCause);

}

throwable = e;

exception(request, response, e);

} catch (Throwable e) {

ExceptionUtils.handleThrowable(e);

container.getLogger().error(sm.getString(

"standardWrapper.serviceException", wrapper.getName(),

context.getName()), e);

throwable = e;

exception(request, response, e);

}

// Release the filter chain (if any) for this request

if (filterChain != null) {

filterChain.release();

}

// Deallocate the allocated servlet instance

try {

if (servlet != null) {

wrapper.deallocate(servlet);

}

} catch (Throwable e) {

ExceptionUtils.handleThrowable(e);

container.getLogger().error(sm.getString("standardWrapper.deallocateException",

wrapper.getName()), e);

if (throwable == null) {

throwable = e;

exception(request, response, e);

}

}

// If this servlet has been marked permanently unavailable,

// unload it and release this instance

try {

if ((servlet != null) &&

(wrapper.getAvailable() == Long.MAX_VALUE)) {

wrapper.unload();

}

} catch (Throwable e) {

ExceptionUtils.handleThrowable(e);

container.getLogger().error(sm.getString("standardWrapper.unloadException",

wrapper.getName()), e);

if (throwable == null) {

throwable = e;

exception(request, response, e);

}

}

long t2=System.currentTimeMillis();

long time=t2-t1;

processingTime += time;

if( time > maxTime) maxTime=time;

if( time < minTime) minTime=time;

localSpanStore.removeSpan();

// ZipkinClientContext.getClient().finishSpan();

System.out.println("借宿了》》》》》》》》》》》》》》》》》》》》》》》》");

}

// -------------------------------------------------------- Private Methods

/**

* Handle the specified ServletException encountered while processing

* the specified Request to produce the specified Response. Any

* exceptions that occur during generation of the exception report are

* logged and swallowed.

*

* @param request The request being processed

* @param response The response being generated

* @param exception The exception that occurred (which possibly wraps

* a root cause exception

*/

private void exception(Request request, Response response,

Throwable exception) {

request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, exception);

response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

response.setError();

}

public long getProcessingTime() {

return processingTime;

}

public long getMaxTime() {

return maxTime;

}

public long getMinTime() {

return minTime;

}

public int getRequestCount() {

return requestCount.get();

}

public int getErrorCount() {

return errorCount.get();

}

public void incrementErrorCount() {

errorCount.incrementAndGet();

}

@Override

protected void initInternal() throws LifecycleException {

// NOOP - Don"t register this Valve in JMX

}

}

//用得是:InheritableThreadLocal

//现象:

//日志:

/**

                 *   tomcat两个线程会传递

                 * http-nio-9005-exec-1 当前span ===-5227500798708065629 parentId  null traceId -5227500798708065629

                  http-nio-9005-exec-2 parent Span   -5227500798708065629 traceId -5227500798708065629

                 */

奇怪,同一级别得tomcat线程,为什么线程1会传递变量到线程二

如果用ThreadLocal就没问题!

//猜测:

拦截得改类应该是父线程执行得set操作,导致会传递到tomcat子线程。所以ThreadLocal没问题。

解决:

每次进入tomcat线程时,重新清空当前tomcat线程变量搞定

 

以上是 pre探针tomcat连接池内同一级别线程池传递问题 的全部内容, 来源链接: utcz.com/z/512156.html

回到顶部