在工作中,我在组里负责一个Proxy(代理)的Module,这个Module是针对微软的Office 365的邮件门户OWA实现,工作起来后,用户访问Office 365 OWA,无需再输入Office 365的网址,只需输入我们Proxy的地址,然后我们会将请求转送到Office 365 OWA,达到用户访问的目的,并使用户的体验如同实际访问Office 365 OWA一样。

  其实我们Proxy的原理是,使用Node.js构建一个http Server,拿到client端(实际是Browser)的请求后,再将请求转给Office 365,将Office 365的返回内容Response再送给Client端,这样实现Proxy的功能

  当然实际实现过程中还有很多细节的事情,包括cookie的处理,URL的转换等,这里不细讲。

  

  但在工作中开发并维护此Module时,我发现一个问题,那就是虽然我们是将请求转发,但还是有很多请求我们需要特殊处理,而且有很多复杂的请求需要研究去支持,因此做为Proxy我必须知道Office 365,即目标网站都有哪些请求的类型,其实就是哪些不同的URL,不同的URL其实Path不同。

  

  因此我做了一个优化,因为Proxy本质是一个Http Server,因此我将客户端发来的所有请求URL打印在Log中,这样我可以在Log中收集到所有的URL,同时将该URL发送出去后收到的结果(Response Status Code)也打印在一起,这样就能知道这个URL是否处理有问题,如果返回值200,则说明OK。

  

  于是打印在Log中后,得到如下的Log,

 /___/outlook.office365.com/, 302
/owa/, 302
/__/login/login.srf, 200
/owa/prefetch.aspx, 200
/___/r1.res.office365.com/owa/prem/16.801.12.1741001/scripts/preboot.js, 200
/___/r1.res.office365.com/owa/prem/16.801.12.1741001/scripts/boot.worldwide.0.mouse.js, 200
/___/outlook.office365.com/GetUserRealm.srf, 200
/___/r1.res.office365.com/owa/prem/16.801.12.1741001/scripts/boot.worldwide.1.mouse.js, 200
/owa/ev.owa2, 200
/owa/ev.owa2, 200
/___/outlook.office365.com/, 302
/owa/ev.owa2, 200
/owa/, 302
/__/login/login.srf, 200
/owa/ev.owa2, 200
/owa/service.svc, 200
/owa/prefetch.aspx, 200
/___/r1.res.office365.com/owa/prem/16.807.12.1742334/scripts/preboot.js, 200
/owa/service.svc, 200
/___/r1.res.office365.com/owa/prem/16.807.12.1742334/scripts/boot.worldwide.0.mouse.js, 200
/owa/ev.owa2, 200
/owa/ev.owa2, 200
/owa/service.svc, 200
/owa/service.svc, 200
/___/outlook.office365.com/GetUserRealm.srf, 200
/___/r1.res.office365.com/owa/prem/16.807.12.1742334/scripts/boot.worldwide.1.mouse.js, 200
/__/login/ppsecure/post.srf, 200
/owa/, 302

  每一行数据,前面是URL,后面是该请求收到的Response Status Code。

  

  同时我自己写了一个脚本来解析Log里的数据,因为数据是重复的,需要去重以及排序。

  脚本如下:

 var lineReader = require('line-reader');
var fs = require('fs'); var fileReadData = "URLs.log";
var fileWriteData = "result.txt"; var ignoreNormalStatusCode = false;
if (process.argv && process.argv[2]) {
ignoreNormalStatusCode = process.argv[2]; // development to be passed as param
} console.log("ignoreNormalStatusCode: " + ignoreNormalStatusCode); // create data object
var createDataObjectFromLine = function (str) {
var data = str.split(","); var obj = {
url: data[0].trim(),
statusCode: data[1].trim(),
number: 1
}; return obj;
}; // get the index in the array
var indexOfObjInArray = function (array, obj) {
var pos = -1; for (var i=0; i<array.length; i++) {
var e = array[i]; if (e.url === obj.url && e.statusCode === obj.statusCode) {
pos = i;
break;
}
} return pos;
}; // compare number to sort
var compare_number = function (a, b) {
return b.number - a.number;
}; // write the array's data to file
var writeResultToFile = function (result, number) {
var string = "";
string += "Here is this URL scan result blow, \n";
string += "Orignial URL number: " + number + "\n";
string += "Unrepeat URL number: " + result.length + "\n";
string += "------------------------------------------\n\n";
string += "req url, this url's response status code (200 is ok), number statics\n";
fs.appendFileSync(fileWriteData, string); for (var i=0; i<result.length; i++) {
fs.appendFileSync(fileWriteData, result[i].url + ", " + result[i].statusCode + ", " + result[i].number + "\n");
}
}; // create an array to save the urls
var result = []; // count the orignial url number
var number = 0; // main function
lineReader.eachLine(fileReadData, function (line, last) {
number++; // parse the data from every line
var obj = createDataObjectFromLine(line);
//console.log(obj); var pos = indexOfObjInArray(result, obj);
if (pos != -1) {
// this object already exists in result array
result[pos].number++;
}
else {
if (ignoreNormalStatusCode && obj.statusCode === '200') {
// ...
}
else {
// add this obj to result
result.push(obj);
}
} if (last) {
// sort the array by number
result.sort(compare_number); // write the result to file
writeResultToFile(result, number); // stop reading lines from the file
return false;
}
});

  这里使用了一个Node.js Module Line-reader,来从文件中一行行的读取数据。

  这样运行之后就可以得到解析后的结果,

 Here is this URL scan result blow,
Orignial URL number: 142
Unrepeat URL number: 6
------------------------------------------ req url, this url's response status code (200 is ok), number statics
/owa/, 302, 10
/___/outlook.office365.com/, 302, 5
/owa/auth/15.1.225/themes/resources/segoeui-regular.ttf, 404, 3
/owa/auth/15.1.225/themes/resources/segoeui-semilight.ttf, 404, 1
/___/outlook.office365.com/favicon.ico, 302, 1
/owa/auth/15.1.219/themes/resources/segoeui-semilight.ttf, 404, 1

  当然以上结果是没有显示Status Code为200的URL,原因是这是Proxy处理正常的URL,暂时没必要统计与分析。

  得到结果后,显而易见,有很多404的URL,我们的Proxy并没有正确的处理,需要进一步的分析,在代码中支持。由此完成此次对产品Module的优化。

  

  个人小感慨,工作中很多小事情,如果自己认为正确,就应坚持去做。小的优化,只要有意义,都会有大用处:-)

                                                      Kevin Song

                                                        2015-7-22

【工作】Proxy Server的优化 - 检测目标网站URL变化的更多相关文章

  1. SQL Server 性能优化详解

    故事开篇:你和你的团队经过不懈努力,终于使网站成功上线,刚开始时,注册用户较少,网站性能表现不错,但随着注册用户的增多,访问速度开始变慢,一些用户开始发来邮件表示抗议,事情变得越来越糟,为了留住用户, ...

  2. proxy server 代理服务器

    有时候,我觉得自己需要去搞明白.搞清楚一个概念,帮我打通一下自己的知识体系,或者说,尝试联络起来. 1. 简介 突破自身IP限制,访问国外站点. 访问单位或者团体内部资源. 突破中国电信的IP封锁. ...

  3. Proxy Server代理服务器(轉載)

    宽带IP城域网开通以来,单位连上了宽带网,10M的带宽让我们感受到了宽带的魅力.电信只提供7个IP地址,对任何一个单位来说都太少了,常用的解决办法是使用代理服务器.微软的MS Proxy Server ...

  4. web性能优化系列之网站瓶颈识别

    最近,公司网站的的访问量日益增大,PV马上过百万了.前期网站一到访问高峰,马上会变得很卡甚至打不开,后来做了很多优化后现在访问比较顺畅了.经过此事明白了一个道理,在遇到这类问题要做到两点,第一要相信自 ...

  5. java gc的工作原理、如何优化GC的性能、如何和GC进行有效的交互

    java gc的工作原理.如何优化GC的性能.如何和GC进行有效的交互 一个优秀的Java 程序员必须了解GC 的工作原理.如何优化GC的性能.如何和GC进行有效的交互,因为有一些应用程序对性能要求较 ...

  6. SQL Server 性能优化之——系统化方法提高性能

    SQL Server 性能优化之——系统化方法提高性能 阅读导航 1. 概述 2. 规范逻辑数据库设计 3. 使用高效索引设计 4. 使用高效的查询设计 5. 使用技术分析低性能 6. 总结 1. 概 ...

  7. 转:Jmeter 用户思考时间(User think time),定时器,和代理服务器(proxy server)

    在负载测试中需要考虑的的一个重要要素是思考时间(think time), 也就是在两次成功的访问请求之间的暂停时间. 有多种情形挥发导致延迟的发生: 用户需要时间阅读文字内容,或者填表,或者查找正确的 ...

  8. SQL SERVER全面优化-------索引有多重要?

    想了好久索引的重要性应该怎么写?讲原理结构?我估计大部分人不愿意看,也不愿意花那么多时间仔细研究.光写应用?感觉不明白原理一样不会用.举例说明?情况太多也写不全....到底该怎么写呢? 随便写吧,想到 ...

  9. 不修改代码就能优化ASP.NET网站性能的一些方法

    阅读目录 开始 配置OutputCache 启用内容过期 解决资源文件升级问题 启用压缩 删除无用的HttpModule 其它优化选项 本文将介绍一些方法用于优化ASP.NET网站性能,这些方法都是不 ...

随机推荐

  1. From表单提交刷新页面?

    form表单提交跳转 写作原因:   楼主的html水平一般,偶然想起周围人常说的form表单提交会刷新页面,闲来无事,就想想其中的原因 想来想去为什么会刷新,猜想了以下几条 1.先提交数据,等服务器 ...

  2. 关于IBOutlet的生命周期

    在调试程序的时候,发现 IBOutlet的对象在执行 getter时,开始一直想找IBOutlet对象getter方法前被执行的代码,但是一直找不到,于是我就想是不是系统自动给IBOutlet 自动初 ...

  3. Python之将字符串转换为字节的两种方法

    s = '你是谁' a = bytes(s,'utf-8') # ==> 得出的 a 的结果就是对应的字节 s.encode('utf-8') # ==> 该命令将字符串转换为字节形式

  4. [转载]pytorch自定义数据集

    为什么要定义Datasets: PyTorch提供了一个工具函数torch.utils.data.DataLoader.通过这个类,我们在准备mini-batch的时候可以多线程并行处理,这样可以加快 ...

  5. Codeforces - 625B 贪心

    求最小不重复匹配次数 改最后一个字符最划算 我当时怎么就没看出来.. #include<bits/stdc++.h> using namespace std; string S,T; in ...

  6. 制作网页logo

    一.先把jpg.png.jpeg等图片通过在线ico图标制作软件变成.ico图片 在线制作ico图标工具: http://www.bitbug.net/ 二.在head里面添加如下代码 <lin ...

  7. django 母版与继承

    在子页面的页面最上方使用下面的语法来继承母版. {% extends 'layouts.html' %} 块: 通过在母版中使用{% block xxx %}来定义块.在子页面中通过定义母版中的blo ...

  8. APPcrawler基础原理解析及使用

    一.背景 一年前,我们一直在用monkey进行Android 的稳定性测试 ,主要目的就是为了测试app 是否会产生Crash,是否会有ANR,页面错误等问题,在monkey测试过程中,实现了脱离Ca ...

  9. Jenkins 第一次访问时提示Unlock Jenkins

    Jenkins启动后录入网址提示Unlock Jenkins,To ensure Jenkins is securely set up by the administrator Jenkins启动后, ...

  10. 15.Servlet程序结构与部署

    1.JavaEE应用程序结构 组成:Servlet  JSP  工具类  第三方jar包,HTML页面(图片.Flash) 部署结构: JavaEE应用根目录下的资源都是允许客户端访问的(WEB-IN ...