Axure在新款Macbook下使用时,出现LookupViewService意外停止问题的解决方案

最近,换了新的macbook,新的ForceTouch技术的触控板使用体验不错,触控板在不下陷的情况下能够带来轻按、重击两种不同的体验,并且还没有太损失点按手感,的确用起来爽歪歪。

新的ForceTouch机型上,系统默认开启了“用力点按和触觉反馈”功能,让TouchPad能够支持两种力量的点按,以此来执行不一样的任务。不过,这个新特性也引发了Axure的一个BUG,当开启了这个属性后,在axure中点选相关文字,都会引起弹出LookupViewService意外停止的问题,十分烦人。

目前Axure官方并没有提供BUG的解决补丁,只能我们自己关闭掉用力点按属性,来避免频繁弹出这个错误提示,影响了你正常的工作。

关闭的位置如图:


去掉该新特性之后,使用Axure终于清静了。。。

Read More

用Node.js开发基于正方教务系统的手机选课神器

对于我们来说,学校的选课系统和网络架构共同组合成了一个黑盒系统,需要对其进行逆向思维的Web开发,因为代码涉及到校内系统的一些不安全因素,也暂时无法整理出一份不包含敏感内容的代码,所以有了本文,分析一些开发这个产品的思路。

我最初的想法是想做一款基于Node为后端的手机选课Webapp,由于学校系统和网络架构的封闭性,给我们带来了无数个坑……

产品最终表现

  • 峰值3880位独立用户在线同时发送选课请求(受限于学校最终的系统负载能力)
  • 发送了27735条选课请求,三天内的5w多次登录请求
  • 在官方系统大面积瘫痪后依然稳定运行
  • 实现免验证码提交
  • 一键选课,将繁琐的网页官方版系统的选课操作浓缩为一步
  • 整合实现WebApp和NativeApp共享,同一套方案,适应多渠道的交互体验
  • 可以快速适配地部署到不同学校的“正方教务系统”

为什么要开发这样一款产品

  • 学校官方系统速度缓慢,并发能力弱,且易出错
  • 能选课的场地限制很多,而智能手机几乎人手一部
  • 可以收集到很多有用的行为数据,提供后续分析利用
  • 官方系统操作体验极差,常年遭到学生吐槽
  • 等等等等。。。

挑战和技术选型

面临的问题

  • 没有学校教务数据库的直接读写权限
  • 每个年级大约有4000-5000人,会同时刷上半小时以上
  • 多终端的接入兼容(内嵌Webview及独立Webapp)
  • 每次提交都要输入验证码?!
  • 开工之后和完工之时才会发现的更严重的坑。。。

技术选型

  • 前端与后端通过RESTful API交互
  • 后端作为中间层,代理用户请求,以更快速的方式将请求转发到选课服务器
  • 3台Centos 6.4跑选课代理服务,分配1台MongoDB进行行为记录,以及1台Watcher机
  • 前端NginxLB,sticky session
  • 项目托管于 bitbucket.org
  • 将用户登录选课系统的cookie集中到服务器上管理
  • Nodejs + cheerio + Mongoose

     

    "dependencies": {
      "express": "3.4.4",
      "ejs": "0.8.5",
      "iconv-lite": "0.2.11", //快速的GB2312 TO UTF-8
      "cheerio": "0.12.4", /** 替代jquery,对jsdom的增强,
                           同时兼容jquery语法,实测解析速度会比jquery快1到1.2倍 **/
      "request": "2.27.0",
      "mongoose": "3.8.1", //将各类行为和访问写入mongo日志
      "pm": "2.2.2", // @朋春 的cluster
      "connect-mongo": "0.4.0" //处理express mongo session
    }

各种的坑和解决方案

坑一

maxSockets

request 在发送http请求时的最大可用agent数量默认限制为5(实际上是 http 对其自己的maxSockets初始为5),导致了在并发情况下,排队等候的请求无法addListener,会报如下错误。

(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.
Trace: 
    at EventEmitter.<anonymous> (events.js:139:15)
    at EventEmitter.<anonymous> (node.js:385:29)
    at Server.<anonymous> (server.js:20:17)
    at Server.emit (events.js:70:17)
    at HTTPParser.onIncoming (http.js:1514:12)
    at HTTPParser.onHeadersComplete (http.js:102:31)
    at Socket.ondata (http.js:1410:22)
    at TCP.onread (net.js:354:27)

这个warning带来的问题是,新增的http请求一律被拒绝,返回500 Internal Server Error。而其实此时的服务器Load毫无压力。所以增大maxSockets是毋庸置疑的。 之后找到 request 的作者回复的一个issue, @mikeal给到的解决方案是

require('http').globalAgent.maxSockets = Infinity

而实际上呢? 当我们设置到无限制之后,使用JMeter进行压测,发现1000qps的时候,前几秒还能正常处理,之后立马瞬间马上500返回了剩余的所有请求。并且在console里面报错ENOTFOUND或ETIMEOUT(这俩错误是由网络层返回回来的)

俩开发猜了好久,有抓包分析了相关response,发现是遭到了sangfor firewall的封杀。原来是已经超过了允许的每秒单机HTTP请求通过数了(服务器群网段也限啊,真是BT),所以在后来 request 虽然顺利发出了http request,但是从网络层被forbidden。那么,既然猜到是这样的原因,我们就可以采取“保持在允许的单机最大qps,连续发送请求”的方式进行请求了,这样既不会被防火墙从网络层切断,又能保证传输的最高效率。

经过实测,发现设定为150时,是我们当前服务器和网络环境下的最佳值。

http.globalAgent.maxSockets = 150;

坑二

最佳http超时

由于Node中默认的http超时时间为120s之久,大量长时的异步请求不会因为用户刷新或断开浏览器连接而断开,给服务器上造成了很多不必要的资源占用,导致队列排的很满,后过来的请求只能被阻塞。实际表现出的结果是,服务器发送出1000个http请求之后,后来的访问者的请求会被node自动排队到队列的最后,给用户带来的直接感受就是程序仿佛卡死了、很慢很满,于是用户再又刷新,一个新的http请求又出去了,用户一多,造成了很多无用的连接资源占用。因此我们需要寻找一个最佳的超时时间设置,经过我们的实践数据显示

Alt text

根据测试结果设置 request 的默认超时时间,单位为ms

var request = require('request').
defaults({
  timeout: 95000
});

 

其他坑,待更新分享

   更智能地导向到最快且好的选课服务上

   CAS系统的登录和跳转

   让connect-mongo与mongoose更美好地共存

   mongoose查询结果必须JSON.parse()?!

 

Read More

[在家园的知识分享]到底什么是互联网运营?

       今天参加了一次关于运营的分享会,不论是从活动话题的讨论点还是活动形式上看都展现了独到的风格,向听讲者传递了很多当下较为前端的互联网产品的运营理念和思路,并且从需求分析上做了详细的案例讲解. 看到了诸位童鞋对互联网知识对互联网产品的那份热情,现在便借此次分享会的提点,想向大家分享一些互联网运营大概念的基础知识,并会结合家园论坛的运营发展风格进行我们个性化的分析. 希望藉此抛砖引玉,从提供一些基础知识和技能的角度,激发大家对互联网的探索对互联网产品运营的探索,都来关注到如何研发、运营、推广我们自己的产品,共同打造一个具有杭电特色的具有价值的平台

说了这么多,到底什么是互联网产品运营?
在家园的很多发展时期,产品运营究竟是干什么的,这个概念也模糊不清,缺乏一个标准定义。有时候跟客服混淆在一起,有时候跟推广混淆在一起,有时候跟编辑混淆在一起。即便声称“运营很重要”的人,也未必能解释这一点。基本上运营工作就是个跟内容,跟用户打交道的大杂烩。
纵观整个互联网业内的运营人员,大部分被称作“论坛(社区)管理员”或者“活动策划”或“网络编辑(小编)”,小部分被称作“内容审核员”,听上去都不是高级岗位。但实际上,他却在整个互联网产品的发展过程中占据着最为重要的角色。如果说一个互联网产品是一家大超市,超市的货架的装配、内部的装修甚至是整个超市框架的设计搭建等等都可以归于是技术类人员的工作,那么运营人员就是计划怎么进货,怎么安排好所有货物的安放位置并且对今后超市所有的销售情况和业务调整具有唯一说话权的一群人,他们是距离超市的客户最近的一群人。

如果对运营工作做一个总结的话,那么他是······

1、BBS或者说是论坛(但实际上bbs是Bulletin Board System 电子公告板 的缩写),基本上是内容型的产品,受到“趋同扩散”法则的影响。因此必须得建立内容标准,什么样的内容是好的,被提倡的;什么样的内容是不好的,不受欢迎的。
建立标准有两个手段:
首先是审核,将不适当的内容和申请给剔除出去;
其次是推荐,利用加精、置顶、推荐位更新、专题制作等方式,让好的内容增加曝光率,在鼓励作者的同时也传播了内容价值观。

与传统编辑工作不同的是,运营人员追求的并非流量,而是内容价值观的普及,通过内容价值观来筛选用户群,再引导用户群 去自发维护适当的内容氛围。
如果没有运营工作,内容就会泥沙俱下,劣质的内容驱逐优质的用户,目标用户难以在这里找到归属感,广告垃圾泛滥,使产品失去控制。

番外:
也有人曾经问我,版主不就是干这事情的吗,为什么还需要专职的运营人员?
这问题解释起来比较复杂。首先,版主也是需要发掘和管理的,干这事儿的通常是专职运营人员。其次,只有在一个成熟的社区,版主才能获取足够的成就感,他的投入才是值得的。这其实就是一个先有鸡还是先有蛋的悖论问题了,但针对互联网产品运营,答案是,先由专职运营人员将社区推向成熟,创造一个更具价值的内容发布平台,自己拥有的足够多了才有能力去做分享,将平台价值分享给第三方的潜在可能的版主或者超级版主,再将管理职责逐步下放给版主和超级版主,他们会积极主动地共享更多的价值内容给我们的平台,从而平台价值得到丰盈,丰盈的平台价值又反哺平台用户进而又创造出更多潜在价值的用户或是版主,形成良好的循环体系。
除此之外,对于内容公共中心的主题和人群细分(比如开版),使阅读和讨论更有针对性,也是另一项技术含量非常高的内容建设任务。

2、运营人员应该掌握的用户维护的能力。
用户维护是平台技术建成之后,运营人怎么保证平台的所有用户能够持久地、依赖地、无私地为你的产品发展而奉献价值数据。直白的说,就是怎么样保证当前用户不流失的同时还能吸引更多的用户。“用户维护”的概念是来自于产品营销学中的一个内容,相信专业课有营销学内容的童鞋应该上课老师会有讲过?因为不是本专业的人,也没能有更多专业性的理解和分析了,就说一说我对在互联网产品行业的用户维护的一些观点。
用户维护对于我们现有的单一的论坛来说,简单的划分为老用户和新用户两块,这两块看似冲突却其实道理统一。
我们的新用户是每年杭电招生录取的所有本科、硕士新生,我们的老用户是所有大二、大三、大四以及所有毕业出去但帐户未注销的人。这批用户的复杂度足以让人感到头疼(其中的故事相信大三大四的童鞋会懂的。。),但实际上如果能抓住以下几块共同点出发,去做好用户工作,很多问题可就此避免。

一是建立和完善新生帮助内容,让新人三分钟速成学会使用常用功能;
二是发布内容更加友好的公告(新产品、功能发布;故障恢复;活动通知等等······);
三是解决用户的投诉和困难,尤其与高端精华用户保持密切联系,为他们提供更好的人工服务;
四是主动邀请有价值的用户前来尝试新产品;
五是某些强调等级权限的高级功能(譬如上传),要形成曲线形递增,不能造成高级用户功能权限过高出现浪费;初级用户权限过低无法正常使用(挫伤新用户积极性);
六是调节用户群的矛盾,裁决争议,调和氛围;
七是对某些新推出的产品或功能,用户维护就包括引导用户了解新品特性,让他们快速适应并融入其中,关注用户反馈并及时反馈给技术类部门进行解决。

相比起内容建设来说,用户维护的工作通常琐碎,很难作量化的评估,也就很容易被低估。但如果我们换一个宏大的说法:用户维护,即用户群与产品之间的情绪管理,即这款产品的公共关系管理,这其实更接近本质。以“管理员”虚拟角色直接面对用户的运营人员,在某种意义上代言了产品形象并与用户对话,他们面向高端用户或群体用户提供的客户服务,资源投入低而情感附加值高,能够非常有效地提高用户的忠诚度和产品品牌形象。

3、产品(论坛)活动的组织
这里将活动组织的头衔上升到产品活动组织而不单一性指向论坛活动组织,此中的更多含义和内容会在今后的过程中慢慢向各位解释和剖析,最先知道了解的应该是总监层的各位童鞋。
那么说到产品活动一般情况下有三种:
一种是内容导向型,引导用户产出符合要求的内容,借此传播产品的内容价值观。例如各种校内社团活动和各类思政宣传任务。
一种是社交群体导向型,通过带动用户直接或间接的关系互动来推动社区内各用户群的关系的扩展,活跃社交氛围。例如论坛内部的小社交圈的形成(比较可惜的是目前仅有小小游泳池一个案例)
一种是产品导向型,通过大众化的参与来普及产品特性,加强我们的固有品牌(红色家园or家园论坛),通过用户参与活动来让他们熟悉或使用某项功能产品。例如许愿板 阳光乐跑查询等拓展。

但是,不论哪一种活动,都需要方案策划,页面排版设计,组织实施。都需要专业的运营人员来操作。所谓“专业”,不是指他点子多,点子鬼,而是指他非常了解自己的产品,非常了解自己的用户,能结合产品特点和用户特点去策划组织活动,能控制好活动的氛围和节奏,最终为产品带来预计的促进效果。

4、最好的产品运营人员也一定是个不错的产品设计师。
可能不论技术PM怎么叫嚷着要“从用户需求出发”设计产品,也无法回避这么一个事实:只有接近用户的人才能了解用户。
那么,谁最接近用户?
答案显然是:产品运营人员。
只有成天跟用户打交道的他们,才最了解用户的感受。因此运营人员同时也承担了一部分,甚至是大部分的用户研究的职责。他们需要既理解用户的需求,又理解产品的结构,站在这样一个立场上,能够为新产品的策划带来非常大的帮助,提升产品设计上的可靠性。所以我们的运营人员也应更多更积极地参与到新产品的策划和设计当中,不是理所当然地认为产品的开发设计都只是技术类部门的工作,自己不能参与。反而你们才是产品需求设计中最有说话权利的人。

总结:此篇作为“领进门”系列的首篇内容,参考学习了互联网各位大牛的经验文章、家园各位前辈的分享和交流、家园现任各副站的体验,旨在帮助各位新同学尽早学习和熟悉到互联网行业内的相关基础知识和经验,引发大家更多对互联网的思考交流和学习。由于编排时间较短和个人知识系统的缺漏,难免会给本文带来不少影响,还望各位批评斧正,一起完善更多属于家园自己的互联网产品运营资料,共建未来即将启用的家园wiki平台。

Read More

家园2012全新综合智能面试系统-办公自动化初探-第一篇 初始想法

之前和家园的童鞋们提到今年面试的时候有兴趣想尝试一个全新的领域,使用基本的web开发技术制作一整套从面试报名 -> 排队 -> 评判的综合智能化系统,也算是朝着类似OA系统开发方向做些研究.

其中这些内容在网上也是没有任何参考资料的,正好可以挑战一下整套系统的0参考开发.

虽然说手头几个项目都还在烦人地纠缠中,但是做爱好的事情是不容任何东西来改变和质疑地!!所以说开工就开工.

 

 

 

最初设计的想法是这样:

 

由于去年的招新第一轮”海面”的环节报名人数N多,导致当时晚上到场的时候异常混乱还有人插队以及找不到报名表等各种不可控的突发事件,给来参加面试的很多同学留了一个不甚佳的面试体验,所以今年着手做些改变.

目前的报名方式分为

1.线下填写报名表报名 (超炫丽的报名表由设计中心出品)

2.在线报名系统报名 http://join.redhome.cc (基于Thinkphp2.0?忘了,后台不是我做的.当时只负责了前端的内容….)

然后今年经过和各位同僚的讨论之后决定对此进行更深一步的整合,实现线上线下的一体化避免了潜在的混乱也更加正规而且效率上应该会有不错的提升.  接着自己的想法就像天马行空般的不断蹦出来蹦出来,然后自动在大脑里面进行了快速的技术分析和执行性分析后综合得出我们现在可能需要的一套系统和大致的实现方案,现特别在博客上记录一下开发过程,到时候有新人加入开发也可以作为一个参考.

本套系统没有一个很合适的名字,我就暂时叫他 家园综合智能面试系统 ,本套系统的设计最终为实现如下功能:

1.线上线下报名者的统一管理 :所有数据都统一到这套系统的数据库当中并进行统一格式统一编号的管理

2.首轮面试时远程自动排号叫号 : 海量的面试者集中到一个大的面试等待教室,大屏幕显示当前各部门的面试情况,面试者根据自己填报的不同部门和大屏幕显示的叫号进度进入不同的面试室,其中叫号过程需要语言提示.类似银行的叫号系统,当然我们这边没有VIP号,大家一视同仁,(PS:不过你愿意搬几砖给我的话,可以考虑帮你刷出一个VIP号来…偷笑.哈哈)

3.各中心面试区进度及评分管理 : 每个部门每个面试区需要标配一台电脑or大屏智能手机 (到时候电源是个问题?) 在面试完当前这位面试者之后,在系统后台有个简易快速的评分记录功能,完全抛弃传统的纸质记录模式,方便快捷.甚至可以做到科学地从几大方面来进行评判然后系统最终智能得出综合评分,对于面试者来说也是更加客观公平. 完成一个人的面试之后,敲一下键盘,系统自动叫下一位面试者.

4.首轮面试结束后的自动化统计 : 根据各中心自己不同的筛选要求,系统可以自动排序出要求的若干位入选成员.并显示出他们的相关信息方便后续联系.

5.后续面试环节的记录和评分 : 各中心的总监及副总监可以对后续的2 3轮面试过程进行系统记录,方便以后换届之后作为一个参考.此功能先YY着,不一定有时间会完成.

Read More

56网100000话费活动页面漏洞分析

最近从童鞋那边听说56网搞起送话费和公仔的一个活动..可悲的是56网的营销策划真是非常滴糟糕,这个活动没多少人知道和参加.不过目测到现在逐渐参加活动的人也多起来了…..但是很糟糕的56网的工程师们真是做活儿不认真啊…这么明显的一个刷分bug竟然就爆现了.

好了废话不多说.来分析一下页面的情况

首先活动主页是:http://huodong.56.com/2012/videoPrize/index.php

 

 

 

 

 

按照活动正常流程,是用户登录账户结束之后,在观看若干个视频的时候随机出现大礼包图片链接,从该链接处每次随机获取10 20 30 50不等的积分.

我们获取到礼包地址来分析一下看看

第一个礼包:http://huodong.56.com/2012/videoPrize/index.php?vid=XXXXX0ODQXXXXX&ts=1340686300&token=XXccae7c5XXXX12468da2cXXXX70

第二个礼包:http://huodong.56.com/2012/videoPrize/index.php?vid=XXXXXMjA1XXXXX&ts=1340686226&token=cXXXX317db0387eXXXXc9a7XXXX4

对比分析一下传给后台的几个变量,vid ts token表意都非常明显(其中的XXXX以示隐藏部分内容,大家忽略,复制此地址也无效)

 

继续看页面js,注意到一个取奖品function.

function getPrize(obj,pt_id,p_index){
var pli_time = $(“#exchange ul.time_line li.current”).attr(“val_time”);
$.ajax({
type : “post”,
dataType : “json”,
data : {“pt_id”:pt_id, “p_index”:p_index, “pli_time”:pli_time},
url : “index.php?do=getPrize”,
beforeSend : function(){
$(obj).html(“兑换中…”);
$(obj).attr(“disabled”,”disabled”);
},
success : function(data){
if(data === 1){
window.location.href=”index.php?do=getPrizeSuccess”;
}
else if(data === 0 || data === 4){
window.location.href=”index.php?do=getPrizeFail”;
}
else if(data === 2){
alert(‘请先登录再兑换’);
return false;
}
else if(data === 3){
alert(‘您的积分不够’);
return false;
}
}
})
}

 

分析代码,实在是写着弱爆了,通过jason往后台传递pt_id p_index pli_time等三个参数

其一pt_id为奖品id每个时间点不同, p_index为该时段的一号or二号奖品 pli_time取自#exchange内li的val_time参数值.

再找出后台兑换地址为http://huodong.56.com/2012/videoPrize/index.php?do=getPrize

返回值分析

返回data = 1兑换成功

返回data = 0或4兑换失败(猜测0为数量兑换完毕4为时间未到)

data = 2 为用户未登录

data = 3 积分不足

其中兑换成功则跳到网址:http://huodong.56.com/2012/videoPrize/index.php?do=getPrizeSuccess

增对do变量也可以做很多事情,这个变量再未命名时候返回的[0,0,”method not exists”],又一大问题…暴露了部分错误信息,而且返回的0,0两个参数位置可以针对进行猜解.这里木有继续深入下去.

 

接下来从积分获取方式中分析可得.后台不验证上述的vid ts token,估计vid ts token只做入库记录并且不检查时间是否与当前时间相符,所以爆出刷分漏洞,打开上述两个地址之后轮流进行刷新结果发现积分依旧可以进行重复累加,得出结论后台只验证两次的时间是否相同,如果不相同就进行积分累加.

因此利用这个漏洞,在两个地址直接轮流刷新,积分一就一个劲暴涨了.

 

接下来更劲爆的是还能不在对应的时间点提交兑换礼品的请求.

用firebug看到开始兑换的按钮处的代码为 <a onclick=”getPrize(this,’22’,’2′)”>开始兑换</a>

分析function getPrize可知若改变传递的第二个礼品id参数,23 24 25就可以直接兑换到下一时段要开始才能兑换的礼品了.照这个思路去改了一下测试,果真可以兑换成功,查询兑奖记录显示礼品已经兑换得到.

 

 

综述,56网的这次活动程序要么是临时工做的要么是初出茅庐的工程师的练手作品…不过bug暴露的如此明显也比较无语了…js html里面的注释你上线后怎么样也记得删掉去一下好吧…不然真的暴露出来给外人提供了很多的方便.希望56滴工程师们多多注意…

Read More