【工作】Proxy Server的优化 - 检测目标网站URL变化
在工作中,我在组里负责一个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变化的更多相关文章
- SQL Server 性能优化详解
故事开篇:你和你的团队经过不懈努力,终于使网站成功上线,刚开始时,注册用户较少,网站性能表现不错,但随着注册用户的增多,访问速度开始变慢,一些用户开始发来邮件表示抗议,事情变得越来越糟,为了留住用户, ...
- proxy server 代理服务器
有时候,我觉得自己需要去搞明白.搞清楚一个概念,帮我打通一下自己的知识体系,或者说,尝试联络起来. 1. 简介 突破自身IP限制,访问国外站点. 访问单位或者团体内部资源. 突破中国电信的IP封锁. ...
- Proxy Server代理服务器(轉載)
宽带IP城域网开通以来,单位连上了宽带网,10M的带宽让我们感受到了宽带的魅力.电信只提供7个IP地址,对任何一个单位来说都太少了,常用的解决办法是使用代理服务器.微软的MS Proxy Server ...
- web性能优化系列之网站瓶颈识别
最近,公司网站的的访问量日益增大,PV马上过百万了.前期网站一到访问高峰,马上会变得很卡甚至打不开,后来做了很多优化后现在访问比较顺畅了.经过此事明白了一个道理,在遇到这类问题要做到两点,第一要相信自 ...
- java gc的工作原理、如何优化GC的性能、如何和GC进行有效的交互
java gc的工作原理.如何优化GC的性能.如何和GC进行有效的交互 一个优秀的Java 程序员必须了解GC 的工作原理.如何优化GC的性能.如何和GC进行有效的交互,因为有一些应用程序对性能要求较 ...
- SQL Server 性能优化之——系统化方法提高性能
SQL Server 性能优化之——系统化方法提高性能 阅读导航 1. 概述 2. 规范逻辑数据库设计 3. 使用高效索引设计 4. 使用高效的查询设计 5. 使用技术分析低性能 6. 总结 1. 概 ...
- 转:Jmeter 用户思考时间(User think time),定时器,和代理服务器(proxy server)
在负载测试中需要考虑的的一个重要要素是思考时间(think time), 也就是在两次成功的访问请求之间的暂停时间. 有多种情形挥发导致延迟的发生: 用户需要时间阅读文字内容,或者填表,或者查找正确的 ...
- SQL SERVER全面优化-------索引有多重要?
想了好久索引的重要性应该怎么写?讲原理结构?我估计大部分人不愿意看,也不愿意花那么多时间仔细研究.光写应用?感觉不明白原理一样不会用.举例说明?情况太多也写不全....到底该怎么写呢? 随便写吧,想到 ...
- 不修改代码就能优化ASP.NET网站性能的一些方法
阅读目录 开始 配置OutputCache 启用内容过期 解决资源文件升级问题 启用压缩 删除无用的HttpModule 其它优化选项 本文将介绍一些方法用于优化ASP.NET网站性能,这些方法都是不 ...
随机推荐
- 20.Add Two Numbers(两个链表的和)
Level: Medium 题目描述: You are given two non-empty linked lists representing two non-negative integer ...
- 使用Mybatis-plus发生org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
容我慢慢说来,之前是使用springboot+mybatis.我一直采用xml配置文件写sql. 后来采用了mybatis-plus之后,在本地上面测试没有一点问题.一放到服务器就发生这种情况 在本地 ...
- echarts设置线条粗细
series: [ { name:"buy", type:'line', data:[], itemStyle: { normal: { color: '#6cb041', lin ...
- 三嫖客之awk
awk '{h[$1]++}END{for(pol in h)print pol,h[pol]}' access.log |sort -rnk2|head awk -F: -vOFS=":& ...
- centos7初始优化
第1章 优化 1.1 修改yum源 epel源 curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Cen ...
- python3+selenium获取列表某一列的值
python3+selenium获取列表某一列的值 我们在坐自动化测试时,我们可能不想单纯的想验证一个选项卡,我们让脚本随机选择一个选项进行接下来的操作.例如我们想获取列表某一列的某一个数据(随机的) ...
- 8 Operator overloading
在类中,Groovy支持你使用标准的操作符.例如,如果你想使用a+b操作(a和b来自于Z类),那么你在Z类中,必须实现(implement)plus(Zname)方法.
- java——变量
1.静态变量: 随着类的加载而生成并初始化 随着类的消失而消失 2.成员变量: 随对象的加载而生成并初始化 随对象被回收而消失 3.局部变量: 作用范围由{}决定 随方法调用而创建 随方法的执行完毕而 ...
- java——java只有值传递
真的只有值传递! java中对象作为参数传递给一个方法,到底是值传递,还是引用传递? 答:值传递 这里说的很清楚了:https://www.cnblogs.com/zhouxiansheng/p/39 ...
- 学习Laravel遇到的问题纪录
1.更换git remote $ git remote rm origin $ git remote add origin git@github.com:your_username/hello_la ...