`
snowyregion
  • 浏览: 11767 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

blazeds 关闭 httpFlexSession 解决方案

阅读更多

在使用flex/as java做项目时 appserver中没有使用到httpSession, 应用服务器提供的httpSession是在用到的时候才会创建, 而blazeds中是不管你需要不需要每一个请求来的时候都会拿到httpSession  新建一个httpFlexSession对象放到threadLocal中去

 

引发的问题: 在使用集群分发(没有保持会话/session)的时候, 会创建大量并且无用的httpSession对像, 而且httpSession会保持对象(tomcat默认30分钟)很长一段时间,导致appServier内存泄漏

 

解决方案:

① 缩短httpSession对象保持的时间, 在用户量到一定数量的时候不再起做用

②关闭blazeds的httpFlexSession的创建, 不过blazeds本身并没有提供关闭session的支持 这个时候就需要自己去更改blazeds的源码, 或者自己创建一个messageBrokerServlet. 下面附上修改过后的messgeBrokerServlet(包名必须用flex.messaging, 这里边有用到一个flex.messaging下面另外一个类的一个protected方法)

 

package flex.messaging;

import java.io.IOException;
import java.io.InputStream;
import java.security.Principal;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
import flex.messaging.config.ChannelSettings;
import flex.messaging.config.ConfigMap;
import flex.messaging.config.ConfigurationManager;
import flex.messaging.config.FlexConfigurationManager;
import flex.messaging.config.MessagingConfiguration;
import flex.messaging.endpoints.Endpoint;
import flex.messaging.log.Log;
import flex.messaging.log.LogCategories;
import flex.messaging.log.Logger;
import flex.messaging.log.ServletLogTarget;
import flex.messaging.services.AuthenticationService;
import flex.messaging.util.ClassUtil;
import flex.messaging.util.ExceptionUtil;
import flex.messaging.util.Trace;

public class MessageBrokerServlet4Self extends MessageBrokerServlet {

	private static final long serialVersionUID = -2509928967558653217L;
	
	private MessageBroker broker;
    private static String FLEXDIR = "/WEB-INF/flex/";
    private boolean enableFlexSession = false;//关闭httpFlexSession的标志(增加的代码)

    //由于继承了messageBrokerServlet 没有办法在init的时候使用super(servletConfig)所以增加了一个属性
    //当然也可以不用继承messageBrokerServlet 那样必须把blazeds中messageBrokerServlet中的代码都copy过来
    //在这里我只copy了init和service方法 并增加对httpFlexSession的关闭代码
    private transient ServletConfig config;
    
    public ServletConfig getConfig() {
		return config;
	}

	/**
     * Initializes the servlet in its web container, then creates
     * the MessageBroker and adds Endpoints and Services to that broker.
     * This servlet may keep a reference to an endpoint if it needs to
     * delegate to it in the <code>service</code> method.
     */
    public void init(ServletConfig servletConfig) throws ServletException, UnavailableException{
    	config = servletConfig;//super.init(servletConfig)改为自己的属性

        // allocate thread local variables
        createThreadLocals();
        
        // Set the servlet config as thread local
        FlexContext.setThreadLocalObjects(null, null, null, null, null, servletConfig);

        ServletLogTarget.setServletContext(servletConfig.getServletContext());

        ClassLoader loader = getClassLoader();

        String useCCLoader;

        if ((useCCLoader = servletConfig.getInitParameter("useContextClassLoader")) != null &&
             useCCLoader.equalsIgnoreCase("true"))
            loader = Thread.currentThread().getContextClassLoader();

        // Start the broker
        try{
            // Get the configuration manager
            ConfigurationManager configManager = loadMessagingConfiguration(servletConfig);

            // Load configuration
            MessagingConfiguration config = configManager.getMessagingConfiguration(servletConfig);

            // Set up logging system ahead of everything else.
            config.createLogAndTargets();

            // Create broker.
            broker = config.createBroker(servletConfig.getInitParameter("messageBrokerId"), loader);

            // Set the servlet config as thread local
            FlexContext.setThreadLocalObjects(null, null, broker, null, null, servletConfig);

            setupInternalPathResolver();

            // Set initial servlet context on broker
            broker.setInitServletContext(servletConfig.getServletContext());

            Logger logger = Log.getLogger(ConfigurationManager.LOG_CATEGORY);
            if (Log.isInfo()) {
                logger.info(VersionInfo.buildMessage());
            }

            // Create endpoints, services, security, and logger on the broker based on configuration
            config.configureBroker(broker);

            long timeBeforeStartup = 0;
			if (Log.isDebug()) {
				timeBeforeStartup = System.currentTimeMillis();
				Log.getLogger(LOG_CATEGORY_STARTUP_BROKER).debug("MessageBroker with id '{0}' is starting.", new Object[] { broker.getId() });
			}

            //initialize the httpSessionToFlexSessionMap
			synchronized (HttpFlexSession.mapLock) {
				if (servletConfig.getServletContext().getAttribute(HttpFlexSession.SESSION_MAP) == null)
					servletConfig.getServletContext().setAttribute(HttpFlexSession.SESSION_MAP, new ConcurrentHashMap());
			}

            broker.start();

			if (Log.isDebug()) {
				long timeAfterStartup = System.currentTimeMillis();
				Long diffMillis = new Long(timeAfterStartup - timeBeforeStartup);
				Log.getLogger(LOG_CATEGORY_STARTUP_BROKER).debug("MessageBroker with id '{0}' is ready (startup time: '{1}' ms)",
						new Object[] { broker.getId(), diffMillis });
			}
			
            //以下是从service-config.xml中取得是否需要开启httpFlexSession的配置
			//配置的标签为flexSession-enabled
			//channel-amf为配置该标签地方的id属性的值(channle-amf是配置文件中提供的一个默认的id)
			//读取到了该配置就可以在service方法中控制httpFlexSession是否关闭了
            ChannelSettings channelSettings = config.getChannelSettings("channel-amf");
            ConfigMap properties = channelSettings.getProperties();
            String str = (String) properties.get("flexSession-enabled");
            if(str != null){
            	enableFlexSession = Boolean.valueOf(str);
            }
            
            // Report replaced tokens
            configManager.reportTokens();

            // Report any unused properties.
            config.reportUnusedProperties();
            
            // clear the broker and servlet config as this thread is done
            FlexContext.clearThreadLocalObjects();
            
        }
        catch (Throwable t) {
        	// On any unhandled exception destroy the broker, log it and
        	// rethrow.
        	System.err.println("**** MessageBrokerServlet failed to initialize due to runtime exception: "
        			+ ExceptionUtil.exceptionFollowedByRootCausesToString(t));
        	destroy();
        	throw new UnavailableException(t.getMessage());
        }
    }

	private void setupInternalPathResolver() {
		broker.setInternalPathResolver(new MessageBroker.InternalPathResolver() {
			public InputStream resolve(String filename) {
				InputStream is = getServletContext().getResourceAsStream(FLEXDIR + filename);
				return is;
			}
		});
	}

	@SuppressWarnings("unchecked")
	private ConfigurationManager loadMessagingConfiguration(ServletConfig servletConfig) {
		ConfigurationManager manager = null;
		Class managerClass = null;
		String className = null;

		// Check for Custom Configuration Manager Specification
		if (servletConfig != null) {
			String p = servletConfig.getInitParameter("services.configuration.manager");
			if (p != null) {
				className = p.trim();
				try {
					managerClass = ClassUtil.createClass(className);
					manager = (ConfigurationManager) managerClass.newInstance();
				} catch (Throwable t) {
					if (Trace.config) // Log is not initialized yet.
						Trace.trace("Could not load configuration manager as: " + className);
				}
			}
		}

		if (manager == null) {
			manager = (ConfigurationManager) new FlexConfigurationManager();
		}

		return manager;
	}

    /**
     * Handle an incoming request, and delegate to an endpoint based on
     * content type, if appropriate. The content type mappings for endpoints
     * are not externally configurable, and currently the AmfEndpoint
     * is the only delegate.
     */
	public void service(HttpServletRequest req, HttpServletResponse res) {
		try {
            // Update thread locals
            broker.initThreadLocals();
            // Set this first so it is in place for the session creation event.  The
            // current session is set by the FlexSession stuff right when it is available.
            // The threadlocal FlexClient is set up during message deserialization in the
            // MessageBrokerFilter.
            FlexContext.setThreadLocalObjects(null, null, broker, req, res, getServletConfig());
            Principal principal = null;
            //下面的这段代码是改动了源码的地方
			if (FlexContext.isPerClientAuthentication()) {
				principal = FlexContext.getUserPrincipal();
			} else {
				//判断是否需要httpFlexSession如果不需要则不创建httpFlexSession
				if (enableFlexSession) {
					HttpFlexSession fs = HttpFlexSession.getFlexSession(req);
					principal = fs.getUserPrincipal();
				}
			}

			if (principal == null && req.getHeader("Authorization") != null) {
				String encoded = req.getHeader("Authorization");
				if (encoded.indexOf("Basic") > -1) {
					encoded = encoded.substring(6); // Basic.length()+1
					try {
						AuthenticationService.decodeAndLogin(encoded, broker.getLoginManager());
					} catch (Exception e) {
						if (Log.isDebug())
							Log.getLogger(LogCategories.SECURITY).info("Authentication service could not decode and login: " + e.getMessage());
					}
				}
			}

            String contextPath = req.getContextPath();
            String pathInfo = req.getPathInfo();
            String endpointPath = req.getServletPath();
            if (pathInfo != null)
                endpointPath = endpointPath + pathInfo;

            Endpoint endpoint = null;
			try {
				endpoint = broker.getEndpoint(endpointPath, contextPath);
			} catch (MessageException me) {
				if (Log.isInfo())
					Log.getLogger(LogCategories.ENDPOINT_GENERAL).info("Received invalid request for endpoint path '{0}'.",
							new Object[] { endpointPath });

				if (!res.isCommitted()) {
					try {
						res.sendError(HttpServletResponse.SC_NOT_FOUND);
					} catch (IOException ignore) {
					}
				}
				return;
			}
            
			try {
				if (Log.isInfo()) {
					Log.getLogger(LogCategories.ENDPOINT_GENERAL).info("Channel endpoint {0} received request.", new Object[] { endpoint.getId() });
				}
				endpoint.service(req, res);
			} catch (UnsupportedOperationException ue) {
				if (Log.isInfo()) {
					Log.getLogger(LogCategories.ENDPOINT_GENERAL).info("Channel endpoint {0} received request for an unsupported operation.",
							new Object[] { endpoint.getId() }, ue);
				}

				if (!res.isCommitted()) {
					try {
						res.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
					} catch (IOException ignore) {
					}
				}
			}
		} finally {
			FlexContext.clearThreadLocalObjects();
		}
    }
	
}

 以下是services-config.xml中的配置(当然也可以不配置, 不配置就会使用在代码中设置的默认值)

 

        <channel-definition id="channel-amf" class="mx.messaging.channels.AMFChannel">
            <endpoint
                    url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf"
                    class="flex.messaging.endpoints.AMFEndpoint"/>
            <properties>
                <polling-enabled>false</polling-enabled>
                <flexSession-enabled>false</flexSession-enabled><!-- 这个地方配置是否需要开启 -->
                <serialization><legacy-collection>true</legacy-collection></serialization>                
            </properties>
        </channel-definition>

 这里改动的代码需要把配置写在channel-definition标签并且ID是channel-amf的properties节点下面

当然也改动代码把使用配置可以更灵活

 

改动到目前就可开启或关闭httpFlexSession了

 

当然在appservice中的web.xml中启动的servlet就要换成改动之后的servlet了 <servlet>

		<servlet-name>MessageBrokerServlet</servlet-name>
		<servlet-class>flex.messaging.MessageBrokerServlet4Self</servlet-class>
		<init-param>
			<param-name>services.configuration.file</param-name>
			<param-value>/WEB-INF/flex/services-config.xml</param-value>
		</init-param>
		<init-param>
			<param-name>flex.write.path</param-name>
			<param-value>/WEB-INF/flex</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
分享到:
评论

相关推荐

    构建全栈式Flex、BlazeDS和Spring集成解决方案\构建全栈式Flex、BlazeDS和Spring集成解决方案–第二部分 编写to-do list服务器端.pdf

    ### 构建全栈式Flex、BlazeDS和Spring集成解决方案——第二部分:编写to-do list服务器端 #### 概述 本篇文章是构建全栈式Flex、BlazeDS和Spring集成解决方案系列的第二部分,重点在于搭建to-do list应用程序的...

    构建全栈式Flex、BlazeDS和Spring集成解决方案.zip

    构建全栈式Flex、BlazeDS和Spring集成解决方案意味着将这些技术有效地整合在一起,创建出一个高效、可扩展的富互联网应用程序(RIA)平台。 Flex是一个基于ActionScript和Flash Player的开源框架,用于构建具有丰富...

    构建全栈式Flex、BlazeDS和Spring集成解决方案

    构建全栈式Flex、BlazeDS和Spring集成解决方案的关键步骤包括: 1. **设置开发环境**:首先,确保安装了Flex SDK和IntelliJ IDEA或Flash Builder等IDE,同时配置好Java和Spring环境。 2. **创建Flex项目**:在IDE...

    构建全栈式Flex、BlazeDS和Spring集成解决方案–第一部分 创建Maven Flex模块

    构建全栈式Flex、BlazeDS和Spring集成解决方案:创建Maven Flex模块 在富互联网应用(RIA)领域,Adobe Flex以其丰富的用户界面和高性能的数据处理能力,成为了开发者们的首选工具之一。随着技术的不断发展,将Flex...

    Flex、BlazeDS和Spring集成解决方案案例todolist1

    本案例"todolist1"将这三个技术结合,提供了一个实用的集成解决方案。 Flex是一款由Adobe开发的开源框架,用于构建富互联网应用程序(RIA)。它基于ActionScript和MXML,可以创建动态、交互性强的用户界面,提供...

    构建全栈式Flex、BlazeDS和Spring集成解决方案.rar

    Flex、BlazeDS和Spring是三个在Web开发领域中至关重要的技术组件,它们分别负责不同的功能层,共同构建了一个强大的全栈式开发解决方案。本文将深入探讨这三个技术以及它们如何协同工作,帮助开发者构建高性能、可...

    Maven构建全栈式Flex、BlazeDS和Spring集成解决方案–第三部分_整合全部应用

    ### Maven构建全栈式Flex、BlazeDS和Spring集成解决方案——第三部分:整合全部应用 #### 知识点概述 本篇文章将详细介绍如何利用Maven工具链构建一个完整的Flex、BlazeDS和Spring集成解决方案。文章分为三个部分...

    Maven构建全栈式Flex、BlazeDS和Spring集成解决方案–第一部分_创建Maven_Flex模块

    ### Maven构建全栈式Flex、BlazeDS和Spring集成解决方案 #### 一、概述 随着富互联网应用(RIA)技术的日益成熟,如何将类似Adobe Flex这样的RIA应用与稳健的服务器端技术进行集成成为了关键问题。Java开发者常用...

    构建全栈式Flex、BlazeDS和Spring集成解决方案–第三部分 整合全部应用.pdf

    ### 构建全栈式Flex、BlazeDS和Spring集成解决方案——第三部分 整合全部应用 #### 知识点概述 本篇文章旨在探讨一种基于Flex、BlazeDS和Spring框架构建全栈式应用程序的方法。文章分为三个部分,分别介绍了服务器...

    Maven构建全栈式Flex、BlazeDS和Spring集成解决方案–第二部分_编写to-do_list服务器端

    ### Maven构建全栈式Flex、BlazeDS和Spring集成解决方案:第二部分——编写to-do_list服务器端 在深入探讨如何构建一个集成了Flex、BlazeDS和Spring的全栈式解决方案之前,让我们先简要回顾一下这个系列文章的背景...

    blazeds4.7官方下载

    BlazeDS是Adobe公司开发的一款开源的服务器端技术,它主要负责实现Java应用程序与客户端的Flex应用程序之间的数据交互。BlazeDS的出现极大地推动了富互联网应用(RIA)的发展,使得开发者可以利用Flex的图形界面优势...

    Blazeds入门教程.doc

    - LCDS最初被称为Flex Data Service,它是基于Java或ColdFusion的后端数据服务解决方案。 - 主要功能包括:映射Java对象到Flex对象、支持实时消息协议(RTMP)、代理服务、服务器端PDF生成等。 - 官方提供免费版本...

    blazeds 服务器war包

    Blazeds,全称BlazeDS,是Adobe Flex和后端服务器之间进行数据交换的一种解决方案。它的主要目标是提供灵活的数据集成,使Flex前端可以与Java后端服务进行实时通信。Blazeds以WAR(Web Application Archive)文件的...

    FLex与Java交互必备blazeds

    总之,Blazeds为Flex和Java之间的数据交互提供了一种高效、便捷的解决方案,让开发人员能够专注于业务逻辑,而非底层通信细节。如果你正在使用Flex进行前端开发,并且希望与Java后端紧密结合,那么掌握Blazeds的相关...

    Blazeds与java通信

    它提供了一个全面的解决方案,使开发人员能够构建富互联网应用程序(RIA),这些应用程序可以利用服务器上的数据和服务。在本篇中,我们将深入探讨Blazeds与Java通信的核心概念和技术。 1. **Blazeds简介**: ...

    blazeds flash开源服务器

    总的来说,Blazeds是一个强大的工具,它为开发人员构建富互联网应用程序(RIA)提供了一种高效、灵活的解决方案,通过AMF实现了Flash和Java服务器间的无缝通信。对于需要在Web应用中实现复杂交互和实时数据同步的...

Global site tag (gtag.js) - Google Analytics