软件架构之美 - 软件工程&架构
这个讲座的话题可能属于老生常谈了。不过我的个性不太喜欢重复别人的话题,所以本文的内容还算是比较新的,多数内容在互联网上不太见得到。 这个讲座我迄今讲了4遍: 第一遍是在百度(BIDU)网页搜索(PS)团队讲的。时间上大约在2008年10月~11月之间。 第二遍,是在盛大(SNDA)创新院入职的时候,又讲了一次。时间上大约在2009年3月~4月之间。 第三遍,是受盛大在线(SDO)之邀,又讲了一次。时间上大约在2010年7月。 第四遍,是受老东家金山软件(Kingsoft)之邀,去珠海讲了一次。时间为2010年8月17日。 接下来我还会讲第五遍、第六遍: 分别将在盛大创新院、ECUG 2010大会上讲。时间上都是在10月份。 这可能是我唯一一份不停去重复讲的一个PPT。 为什么需要去重复讲?这其中的道理就像传教士在传达他们的信仰一样。在软件架构领域,存在不少误区。我见过太多的例子。很多人推崇设计模式。但是在我眼里,设计模式是没有任何价值,如果不能够明白软件架构的本质的话。 如果用一句话总结架构,那么我的话是: 软件架构就是准确把控需求的基础上对系统的解剖。 准确把控需求,不只是要准确理解当前的需求,也要准确理解需求的变化,预见什么会发生,而什么不会发生。 讲座PPT下载:软件架构之美 - 软件工程 架构 更新:ECUG Con 2010...
Mac OS X下系统内置的截屏方法
新用Mac机器的朋友总是爱问,“有没有好的截屏软件啊?我在Window用xxx,这里有类似的么?” 肯定有,不过我从来不用,我用默认的热键已经很好用了,所以建议你寻找截屏软件前,先看看系统内置的够不够用再说。 Command-Shift-3:截取整个屏幕,保存至桌面。 Command-Shift-4:鼠标光标会变成一个十字,你可以拖拽出一个区域,然后松开鼠标,即可把选中的屏幕区域截图,保存至桌面。 Command-Shift-4,出现十字光标后,按空格键出现鼠标光标变为照相机图标:照相机指在什么窗口,什么窗口就会被淡蓝色阴影覆盖,点击鼠标就可以截图,保存至桌面。(非常适合用来截取窗口) 感谢Seraph和Lin Yong的补充(高级特性,一般应用可以无需了解):选取范围后按住Space拖动鼠标可以移动选择框,如果按住Shift,然后移动鼠标,如果左右移动则可以固定高度改变选择框的宽度,如果上下移动则可以固定宽度改变选择框高度。不松开Shift同时按住Option,可以在高宽选择之间切换。单独按下Option拖动鼠标则按原比例扩大缩小选择框。 以上热键,在按键的同时,按住Ctrl键,则可以不保存至桌面,而保存至剪贴板(方便进行编辑)。...
jQuery ContextMenu Plugin
http://www.trendskitchens.co.nz/jquery/contextmenu/
RabbitMQ
FoldUnfold Table of Contents RabbitMQ 介绍 应用参考 PHP 客户端 RabbitMQ 介绍 用 Erlang 写的 :) 遵循 AMQP 协议。 应用参考 rabbitmq消息件在idc机房监控中的应用 PHP 客户端 RabbitMQ 的 PHP 扩展 http://cn.php.net/manual/en/book.amqp.php
Form 服务之签到功能(Check in)
表单的 List 页面,除了正常列出用户注册/反馈信息外,还有独特的签到(Check in)功能。 何为签到(Check in)?最初需求也是因为 ECUG Con 大会而来。参加会议的朋友们来到会场,按传统会议的思路,当然是让大家在一张纸上签到。不过我们 ECUG Con 提倡的是绿色环保,那些纸就省了,直接进入参会人员名单列表中,找到自己然后点 Check in 即可。 那么签到(Check in)功能是不是只有表单是开会才用的着呢?也不完全是。举个例子,假设表单是一个用户意见反馈表。那么Check in功能可以是,每当你处理完一条用户反馈意见,就将该意见Check in,表示已经处理。 还有其他可能更多可能的应用场景否?这就看大家的发挥啦。 ps. List 页面还有一个特殊的功能入口,叫 Register Check...
发布 Form 服务!比 Google Docs 的 Form 好用哦
FoldUnfold Table of Contents 创建一个表单 Form 服务用户反馈 ECUG 社区建设意见反馈 ECUG Con 2010 与会者注册 查看表单数据 签到功能(Check in) 创建一个表单 进入 http://form.xushiwei.com/ 并登录。Form 服务使用 Google 帐号。如果你没有,可以去免费注册一个 Google 帐号。 点击 Create new form。 在编辑表单的页面,输入表单数据(Form Data),并为该表单取一个名字(Name,最好不要用中文)。 点击 Save form,即创建表单成功。 表单数据(Form Data)是一个 YAML 格式的文本,举几个例子: Form 服务用户反馈 title: Form 服务用户反馈 confirm: p 感谢您的意见! p 您的支持是我们进步的动力! entries: - text: name: name title: 姓名 - text: name: email title: 电子邮件 hint: 留下您的电子邮件,以便我们可以答复您的意见。 required: true - paragraph_text: name: feedback title: 意见 建议 hint: 请详细描述您遇到的问题,或者告诉我们您的好主意。 required: true 这是 Form 服务自身的用户意见反馈表。效果见 http://form.xushiwei.com/v/?id=4c8be6d28ead0e20190b0000 ECUG 社区建设意见反馈 title: ECUG 社区建设意见反馈 ...
在 PHP 中使用 YAML (Ubuntu)
相比 XML 和 Json 而言,YAML 是面向人类阅读和书写方便的标记语言。官网: http://www.yaml.org/。 先安装 re2c。从 http://sourceforge.net/projects/re2c/ 下载一个 re2c 的最新版本(.tar.gz) 解包,configure,再 sudo make install。 sudo apt-get install libyaml-dev sudo pecl install yaml-beta 编辑 php.ini 加入 extension=yaml.so 用这个命令可检测 yaml 是否已经可用: php --re yaml
ARM正式发布Cortex-A15处理器:主频2.5GHz、加速5倍
照此下去,ARM 对 Intel 的威胁不小。另据称,Facebook计划建ARM架构节能化数据中心。
迅雷推出免息贷款,激励核心员工
有图有真相: 无息贷款覆盖对象及可申请额度: 主管工程师:15万元 核心工程师:20万元 杰出工程师:30万元 其实类似的方案早年金山有过,我是受益者之一,只是后来取消了。憾甚。 参阅:http://t.sina.com.cn/1701886454/wr0nHGvtcn
re2c - 将正则表达式转为c代码
re2c 是蛮有趣的工具。它为了提升正则表达式匹配的性能,将正则表达式转换为对应的c代码,思路类似于 lex + yacc 这种组合,只是更加轻便而已。 http://sourceforge.net/projects/re2c/ http://re2c.org/manual.html
这些广告的受益者并非本人,而是 Wikidot。我个人从不掩饰对 Wikidot 的喜爱,它给了我想要的东西,我们为它赚点广告费,我觉得这是很正常事情。Wikidot 也是很有原则的一家公司,她对客户的尊重是我喜爱她的另一个重要原因,要想进入本站而不出现广告很简单,注册个 Wikidot 账号,在浏览本站的时候保持登录状态就好了,你会看到一个很干净的界面。
许哥,能说一下,go和erlang的一些比较吗?
哪一个更适合大规模的实际应用?
多谢
如果你不考虑具体的使用场景,建议选择 golang。erlang 的适用范围相对狭窄。
两者目前都重服务端,所以客户端开发来说,都不是特别适合,如果非要用,建议用 golang。
服务端开发,如果团队比较小,喜欢函数式编程,而且网络模块偏重 io,逻辑不复杂,用 erlang 可以获得比 go 更好的性能,目前 go 语言在性能上还没做过非常大力度的优化。其他情况我建议用 golang。
我用erlang做过手机银行的服务端,效果还是不错的
多谢许哥这么详细的说明,这样就清楚怎么选择了,多谢
在执行单元的公平调度方面,还是请指点下:
比如我要做一个管理大量设备(成千上万)的程序,需要即时监控设备状态,erlang进程的公平调度性是适合这个场景的,golang在这点上机制如何?
许哥您好:
看到您编写的winx, 我有一个问题请教, 为什么MFC的消息映射要提供_AFXDLL和非_AFXDLL两个implementation, 比如
#ifdef _AFXDLL
#define DECLARE_MESSAGE_MAP() private: static const AFX_MSGMAP_ENTRY _messageEntries[]; protected: static AFX_DATA const AFX_MSGMAP messageMap; static const AFX_MSGMAP* PASCAL _GetBaseMessageMap(); virtual const AFX_MSGMAP* GetMessageMap() const;
#else
#define DECLARE_MESSAGE_MAP() private: static const AFX_MSGMAP_ENTRY _messageEntries[]; protected: static AFX_DATA const AFX_MSGMAP messageMap; virtual const AFX_MSGMAP* GetMessageMap() const; #endif
为什么直接用非_AFXDLL的版本的不行? 非要用一个函数_GetBaseMessageMap()去取基类的messageMap?
许哥您好,请教一个问题:
golang http.ResponseWriter 的Write()方法,服务的QPS由3万降到7000。附上我的测试代码和boom测试结果:
现在我测试到的情况是这样的,如果我只填写http的header,那么服务端的处理速度很高,单纯测试(没有业务逻辑),QPS能达到3万,但是如果我添加payload,那么QPS就只能达到不足8000了,只有6000的样子。这个落差太大了,我尝试直接使用http.ResponseWriter 接口中的Write方法写入一个[50]Byte,效果一样。根据我的测试和你们的分析,应该是IO的问题,不过这个也太夸张了。
func handleHeader(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Length", "0") }
func handlePayload50(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Length", "50") w.Write(make([]byte, 50)) }
func handlePayload128(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Length", "128") w.Write(make([]byte, 128)) }
func handlePayload1024(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Length", "1024") w.Write(make([]byte, 1024)) }
func main() { runtime.GOMAXPROCS(runtime.NumCPU()) http.HandleFunc("/header", handleHeader) http.HandleFunc("/payload50", handlePayload50) http.HandleFunc("/payload128", handlePayload128) http.HandleFunc("/payload1024", handlePayload1024) host := fmt.Sprintf("%s:%d", "0.0.0.0", 5001) http.ListenAndServe(host, nil) }
and the boom test result: ./boom -c 1000 -n 500000 -cpus 12 XXXXXX/header 500000 / 500000 Boooooooooooooooooooooooooooooooooooooooooooooooooooo! 100.00 %
Summary: Total: 12.8799 secs. Slowest: 3.2799 secs. Fastest: 0.0018 secs. Average: 0.0239 secs. Requests/sec: 38810.4907
Status code distribution: [200] 499875 responses
Response time histogram: 0.002 [1] | 0.330 [499306] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ 0.657 [0] | 0.985 [0] | 1.313 [312] | 1.641 [0] | 1.969 [0] | 2.297 [0] | 2.624 [0] | 2.952 [0] | 3.280 [256] |
Latency distribution: 10% in 0.0125 secs. 25% in 0.0172 secs. 50% in 0.0216 secs. 75% in 0.0257 secs. 90% in 0.0295 secs. 95% in 0.0327 secs. 99% in 0.0549 secs.
./boom -c 500 -n 500000 -cpus 12 XXXXXX/payload128 500000 / 500000 Boooooooooooooooooooooooooooooooooooooooooooooooooooo! 100.00 %
Summary: Total: 62.5205 secs. Slowest: 3.0714 secs. Fastest: 0.0112 secs. Average: 0.0601 secs. Requests/sec: 7997.1501 Total Data Received: 63998208 bytes. Response Size per Request: 128 bytes.
Status code distribution: [200] 499986 responses
Response time histogram: 0.011 [1] | 0.317 [495652] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ 0.623 [0] | 0.929 [0] | 1.235 [4092] | 1.541 [0] | 1.847 [0] | 2.153 [0] | 2.459 [0] | 2.765 [0] | 3.071 [241] |
Latency distribution: 10% in 0.0405 secs. 25% in 0.0436 secs. 50% in 0.0481 secs. 75% in 0.0546 secs. 90% in 0.0629 secs. 95% in 0.0731 secs. 99% in 0.1054 secs.
许哥:go如何通过一个字串动态创建对象?
比如java里面,有myObject = class.forName("my.com.myObject");
假设有一个mysql库字串是 "github/mysql",我如何像java一样动态得到这个mysql的接口或结构?比如假设可以 sqltest=newObject("github/mysql")?
Post preview:
Close preview