没有找到合适的产品?
联系客服协助选型:023-68661681
提供3000多款全球软件/控件产品
针对软件研发的各个阶段提供专业培训与技术咨询
根据客户需求提供定制化的软件开发服务
全球知名设计软件,显著提升设计质量
打造以经营为中心,实现生产过程透明化管理
帮助企业合理产能分配,提高资源利用率
快速打造数字化生产线,实现全流程追溯
生产过程精准追溯,满足企业合规要求
以六西格玛为理论基础,实现产品质量全数字化管理
通过大屏电子看板,实现车间透明化管理
对设备进行全生命周期管理,提高设备综合利用率
实现设备数据的实时采集与监控
利用数字化技术提升油气勘探的效率和成功率
钻井计划优化、实时监控和风险评估
提供业务洞察与决策支持实现数据驱动决策
转帖|其它|编辑:郝浩|2009-04-20 10:50:58.000|阅读 574 次
概述:在ASP.NET应用程序运行过程中,很可能会遇到各种意料之外的问题。如果在开发环境下,我们可以设置断点,对程序状态一探究竟。但是很显然,在产品环境中我们几乎无法使用这样的状态。也正因为如此,Dump一个内存快照并进行分析才成为一种“高级技术”,同时在线调试也成为一种需要结合技术能力、分析能力,甚至抗压能力的工作。对于调试和解决问题的探索永远不会停止,各成熟的技术团队几乎都会有一个丰富工具箱,用于应付生产环境中的各种状况。
# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>
在上一篇文章中,我们在一个请求中执行了IronPython代码,通过这个方法我们可以轻松地的检查系统运行的状态,或对系统进行一些简单修改。但是这种做法只能检查系统在当前时刻的状态,在很多情况下,我们需要对系统的请求进行一段时间的采样。对于简单的数据(例如每秒执行的请求数量,请求时间),我们可以通过查看Performance Monitor中相关的计数器来获得一些概要的数据。但是,如果我们需要获取一些系统的详细状态,甚至是需要根据需要进行动态改变的自定义需求,则势必要深入到系统内部进行数据采集。因此,我们可能需要让代码执行“一段时间”,并将直接结果进行汇总输出。
让代码执行一段时间不难,简单地使用Thread.Sleep便可,也不会造成什么性能或吞吐量上的损失。关键就在于,在代码停留的这“一段时间”内,我们使用什么样的做法来采集数据。这时候,老赵脑海中立即浮现出的便是HttpModule般监听请求管道(Pipeline)中的各式事件。于是立马写出以下的代码(在前文的示例基础上进行修改):
protected void btnExecute_Click(object sender, EventArgs e) { ScriptEngine engine = Python.CreateEngine(); var scope = engine.CreateScope(); var script = engine.CreateScriptSourceFromString( this.txtCode.Text, SourceCodeKind.Statements); script.Execute(scope); TextWriter writer = new StringWriter(); scope.SetVariable("logger", writer); Action<HttpContext> traceRequest; if (scope.TryGetVariable<Action<HttpContext>>
("traceRequest", out traceRequest)) { Action endTraceRequests; scope.TryGetVariable<Action>
("endTraceRequests", out endTraceRequests); int waitTime; if (!scope.TryGetVariable<int>
("waitTime", out waitTime)) { waitTime = 10000; } this.TraceRequests(traceRequest,
waitTime, endTraceRequests); } this.txtOutput.Text = writer.ToString(); } private void TraceRequests(Action<HttpContext>
traceRequest, int waitTime, Action endTraceRequests) { EventHandler handler = (sender, e) => { try { traceRequest((sender as HttpApplication).Context); } catch { } }; this.Context.ApplicationInstance.BeginRequest += handler; Thread.Sleep(waitTime); this.Context.ApplicationInstance.BeginRequest -= handler; if (endTraceRequests != null) endTraceRequests(); }
再编译了IronPython代码之后,我们会设法获取其中的traceRequest和endTraceRequests函数,前者用于“记录每个请求”,而后者用于采样最后的“聚合”。此外,还会设法从代码中获取等待时间waitTime。然后,使用TraceRequest方法开始对当前请求进行采样。具体做法为监听当前Application的BeginRequest事件,并在每次获得请求时调用traceRequest委托进行“记录”。在等待时间过后,自然将委托从BeginRequest事件中剥离。最后,再通过endTraceRequests函数进行聚合输出。
代码逻辑很清晰,但可惜的是,上面这段代码不能生效。具体原因不明,可能是ASP.NET对这方面进行了限制,使得我们无法在HttpModule之外为请求管道动态添加事件处理函数(存疑,求证)。对此我们只能进行让步。不过,既然ASP.NET允许HttpModule监听管道事件,那么我们不如事先准备一个HttpModule监听各种事件,并且在合适的时候把这一事件转发给IronPython函数。我们这里还是以BeginRequest事件为例:
public class IronPythonTraceModule : IHttpModule { private class TraceRequestEventArgs : EventArgs { public TraceRequestEventArgs(HttpContext context) { this.HttpContext = context; } public HttpContext HttpContext { get; private set; } } public void Dispose() { } public void Init(HttpApplication context) { context.BeginRequest += new EventHandler(OnBeginRequest); } static void OnBeginRequest(object sender, EventArgs e) { var traceRequest = IronPythonTraceModule.TraceRequest; if (traceRequest != null) { var context = (sender as HttpApplication).Context; traceRequest(null, new TraceRequestEventArgs(context)); } } private static event EventHandler<TraceRequestEventArgs> TraceRequest; public static void TraceRequests( Action<HttpContext> traceRequest, Action endTraceRequests, int milliseconds) { EventHandler<TraceRequestEventArgs> handler = (sender, e) => { try { traceRequest(e.HttpContext); } catch { } }; IronPythonTraceModule.TraceRequest += handler; Thread.Sleep(milliseconds); IronPythonTraceModule.TraceRequest -= handler; if (endTraceRequests != null) endTraceRequests(); } }
IronPythonTraceModule需要放入应用程序中,它时刻对请求管道的BeginRequest进行监听,只是在合适的时候才会发起TraceRequest静态事件(显然这并不会对系统性能造成什么影响)。Module包函一个静态的TraceRequests方法,这便是给外部调用的接口。可以发现这段代码和之前的TraceRequests方法非常接近,唯一不同的只是动态添加/删除处理函数的事件是IronPythonTraceModule.TraceRequest,而不是HttpApplication.BeginRequest。于是,原来的代码也需要做一定修改:
protected void btnExecute_Click(object sender, EventArgs e) { ... Action<HttpContext> traceRequest; if (scope.TryGetVariable<Action<HttpContext>>
("traceRequest", out traceRequest)) { Action endTraceRequests; scope.TryGetVariable<Action>
("endTraceRequests", out endTraceRequests); int waitTime; if (!scope.TryGetVariable<int>
("waitTime", out waitTime)) { waitTime = 10000; } // 以下代码有所修改 IronPythonTraceModule.TraceRequests
(traceRequest, endTraceRequests, waitTime); } this.txtOutput.Text = writer.ToString(); }
现在我们进行一番测试,简单地检测一下5秒钟内收到 了多少请求:
使用自己的Module进行处理还有其他一些好处,比如可以提供更好的控制。事实上,目前文章里的解决方案有一些缺陷,并且肯定无法完全满足真实需求。不过我们完全可以对目前的做法进行改进,例如:
不过,除了应对前一篇文章中所提到的负载均衡环境下的问题之外,这个解决方案还有另一个较为重要的情况需要特殊对待。如果使用目前的做法,每次采样都是通过一个请求进行的,所以它并不会在在请求队列阻塞时立即执行,但是采样的常见场景便是在队列阻塞时间检查状况,这显然形成了一个矛盾。不过要解决这个问题并非难事,只要采样不要通过IIS即可。例如您使用普通Socket,或“偷偷懒”使用WCF的TcpBinding进行采样便可——只要和被检查的应用程序在同一进程(即w3wp.exe,还有人用IIS5 吗?)中,便可以使用任何方式进行通信。
改变、探索的过程,其实都是在追求一种编程的美感。老赵喜欢“不拘一格”,只要是有价值的都会去设法尝试一番,探索的过程会遇到大量问题,解决问题后又能带来成就感以及新的感受。因为美感和成就感,所以产生乐趣,因为乐趣才有源源不断地动力。因为有这样的切身体会,所以在这里也建议大家,不妨放开思路,海纳百川。我们可以获得和想到的东西,远比预料中来的丰富。
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com
文章转载自:博客园面对“数字中国”建设和中国制造2025战略实施的机遇期,中车信息公司紧跟时代的步伐,以“集约化、专业化、标准化、精益化、一体化、平台化”为工作目标,大力推进信息服务、工业软件等核心产品及业务的发展。在慧都3D解决方案的实施下,清软英泰建成了多模型来源的综合轻量化显示平台、实现文件不失真的百倍压缩比、针对模型中的大模型文件,在展示平台上进行流畅展示,提升工作效率,优化了使用体验。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
服务电话
重庆/ 023-68661681
华东/ 13452821722
华南/ 18100878085
华北/ 17347785263
客户支持
技术支持咨询服务
服务热线:400-700-1020
邮箱:sales@evget.com
关注我们
地址 : 重庆市九龙坡区火炬大道69号6幢
慧都科技 版权所有 Copyright 2003-
2025 渝ICP备12000582号-13 渝公网安备
50010702500608号