[转载]高效程序员系列3、别碰鼠标——让键盘飞起来

mikel阅读(1154)

[转载]【高效程序员系列】3、别碰鼠标——让键盘飞起来 – Alex Leo – 博客园.

看到文章标题,你肯定会很奇怪,为什么“别碰鼠标”,离开鼠标还怎么操作电脑?“让键盘飞起来”,键盘怎么会飞呢?你可以保留这些疑问,先跟着我的描述操作一遍,注意操作的过程中记住你都做了哪些动作,以及花费了多长时间。

前提条件:假设你正在写代码,你的双手都放在键盘上。如果你用Win7,请暂时忽略任务栏锁定的软件。

1、打开QQ

QQ很常用,你可能把它放在桌面了。于是你把手从键盘移到鼠标上,移动鼠标并定位到Win7的右下角点击切换到桌 面。如果是Vista之前的系统,你需要移动鼠标到快速启动栏,定位到“切换到桌面”按钮并点击。然后你在桌面找到QQ的图标,双击启动。这个过程可能花 费你2秒或3秒,似乎并不算长,操作也不繁琐。而我会保持双手在键盘上,按5个键,整个过程不到1秒。

2、打开Visual Studio或者SQL Server

如果你经常用VS,那么在开始菜单中很容易找到。首先你会把手放在鼠标上,然后将光标移动到开始菜单,点击开始菜单,将光标移动到VS的菜单项上,然后点击打开。这个过程可能花费了你2秒或者3秒,也不是很繁琐。如果是我,我依然会使用键盘,按5个键,整个过程不到1秒。

3、打开一个IIS管理器或者不经常用的,比如计算器、PowerPoint或者配置hosts文件

这个就比上面的操作繁琐一些了,你需要到管理工具中找到IIS管理器才能打开。如果你不是经常使用,可能会花费你5秒甚至更多。我还是使用键盘,按下6个键,整个过程还是不到1秒。

4、让一个窗体最大化、最小化、恢复初始大小或者关闭

你需要移动鼠标,双击窗体标题栏或者最大化按钮来实现最大化或恢复初始大小;最小化需要点击最小化按钮;关闭需要点 击关闭按钮或者双击标题栏,如果你会快捷键,可以按Alt+F4,但跨度很大,而且手臂也需要一起动作。我继续选择键盘,而且只需要动手指,手臂不需要 动,操作比之前都快,可以说是在0.2秒左右就可以完成。

怎样,你有没有觉得好奇?我的手一直在键盘上,常用的和不常用的软件,我都只需要1秒就能打开,效率比鼠标高多了。 所以这里才提出“别碰鼠标”的观点,让你的手指在键盘上飞快的敲起来。当然这里说的“别碰鼠标”不只是打开软件这么简单,还包括更多能提高效率的操作。下 面就带你领略键盘的魅力。

注:下文包含一些组合键,比如“Alt+Tab”,意思是同时按下Alt和Tab,中间的+是同时的意思,不要理解为加号;还有“Alt+空格,C”意思是同时按下Alt和空格,然后再按下C,中间的逗号是分隔符。

一、闪电启动软件的秘密

正如很多魔术,外行人苦思冥想也无法得知其中的奥秘,一旦揭穿则会让人大呼:原来是这样,太简单了。其实这里闪电启 动软件业没有什么高深的方法,只不过是调用了运行而已。作为软件开发人员,我们经常会使用到“运行”,输入cmd就可以调用命令行,输入regedit则 是编辑注册表。如果你觉得“运行”只能输入这些固定的命令,那你就大错特错了。

这里先引入一个情景:假如你是公司的老板,你有一件事需要某人来处理,你是愿意自己走过去给他说,还是愿意叫他的名 字,让他主动走过来听你的命令呢?虽然现实中你不是老板,但是在面对电脑的时候,你就是电脑的boss。在你的电脑里有一大堆软件,比如QQ、IE、 Word、VS……。如果你在桌面密密麻麻的图标中寻找对应的软件图标,或者是在需要滚动好几次滚动条的开始菜单中寻找软件快捷方式,你就是那个主动去找 员工的boss,你处在被动状态。你明明知道要打开的软件的名字,为什么不直接叫它的名字呢?下面就叫你怎样变被动为主动,做一个威武的boss,嘿嘿 ^_^

1、在D盘建立一个文件夹,命名为QuickStart或者你喜欢的名字。

2、把桌面的软件快捷方式图标放到QuickStart文件夹中,并给它们重命名,建议用自己能记住的缩写,不重复即可。比如:

clip_image001

3、给QuickStart文件夹建立一个快捷方式,然后重命名为qs,并且把这个快捷方式也放到QuickStart文件夹中,如上图就有一个qs快捷方式。

4、在桌面对“我的电脑”点右键(Win7是“计算机”),然后选择属性,弹出系统属性对话框。如果是Win7则会弹出系统信息窗体,还需要点击左边的“高级系统设置”,如图:

clip_image002

5、在系统属性对话框中,点击“环境变量”按钮,弹出环境变量对话框。如图:

clip_image003

6、在环境变量对话框的系统变量列表中找到Path项,然后点击“编辑”按钮。

clip_image004

7、在编辑对话框中输入路径“D:\QuickStart”,注意和前面的路径用英文的分号分隔,如图:

clip_image005

然后一路点击“确定”按钮,关闭所有对话框。

8、按下Win+R键,调用运行对话框。在运行对话框中输入qq,如果你的电脑够快的话,马上就会弹出QQ的登录界面。输入qs,就会打开D:\QuickStart文件夹。

(注:Win键就是键盘最下面一排,带Windows图标的键,台式机键盘一般左右各一个,笔记本只有左边有,如下图最下方带圆形Windows徽标的键,该键的右边是模拟鼠标右键的按键)

clip_image006

9、当你新安装了软件,需要把快捷方式添加进来,用qs命令就可以很快打开QuickStart文件夹。

10、当你有经常用到的文件夹,也可以把它的快捷方式放到QuickStart中,很方便就可以打开。

怎样,是不是比从一大堆图标里面找软件快多了。一旦你习惯了Win+R,肯定会对它产生依赖。我的电脑桌面一个图标也没有,因为我是一个彻底的Win+R粉丝。

下面列举一些常用的Windows运行命令

这里有一份从网上找到快捷键和命令收集的文章,可以参考一下:常用快捷键知识

不过Win和R之间的距离有点远,在本系列的上一篇文章中提到过两种脚本语言Au3和AHK,可以考虑用它们实现自定义快捷键来调用运行。比如可以用Alt+Q作为快捷键,这样左手基本上不需要移动。下面是用Au3实现的用Alt+Q调用“运行”的代码:

HotKeySet(“!q”,”WinRun”)

Func WinRun()

Send(“{LWINDOWN}r{LWINUP}”)

WinWait(“Run”,””)

If Not WinActive(“Run”,””) Then WinActivate(“Run”,””)

EndFunc

Do

Sleep(500)

Until False

Exit

其实也有其他一些软件可以实现快速启动,这里介绍一款叫做Launchy的免费软件,它不仅可以快速启动软件,还支持查询和搜索功能,如下图。它的官方网址是:http://www.launchy.net/ 不过因为它需要安装,会占用系统资源,虽然占用的不多,但我更倾向于使用原装的Win+R。

clip_image007

clip_image008

二、操作系统常用快捷键(非初学者可以跳过此段,如有遗漏,欢迎补充)

1、不可小视的Alt、Ctrl、Shift

(1)Alt

Alt配合菜单使用:主菜单下面带下划线的都是可以用Alt+对用字母控制的。比如下面的SnagIt,按下Alt 会激活主菜单,如果要选择Edit,按下E即可,要选择Help,按下H即可,或者是同时按下Alt+H即可调用Help菜单。如果是在 Office2007中,按下Alt则会出现如下图的快捷键提示,按下对应的键则可以激活对应的功能。

clip_image009

Alt+Tab:切换窗体。按下Alt+Tab会出现如下的程序窗体预览,按住Alt,多次按下Tab则会从左到右循环选择窗体。而Alt+Shift+Tab则会从右到左循环选择窗体。

clip_image010

Win+Tab:Win7下用预览方式切换窗体,比Alt+Tab更直观。同理Win+Shift+Tab会反向循环选择。

clip_image011

Alt+Down:列出下拉选项。当下拉控件获取焦点时,按下Alt+Down(向下的箭头),则会执行下拉操作,列出下拉框中的候选项。

Alt+Enter:属性命令,当选中一个文件/磁盘时,这个快捷键相当于对文件/磁盘点右键,然后点击属性菜单项。

Alt相关窗体命令

上面提到了用让窗体最大化、最小化、关闭等操作,其实是通过Alt相关命令实现的。对窗体标题栏点右键,可以看到有 一个菜单弹出来。其实用Alt+空格就可以代替对标题栏点右键。而一旦标题栏菜单出来之后,按下菜单项对应的字母,则相当于点击菜单项,所以通过这些命令 可以极速操作窗体大小。熟悉这些命令后,左手大拇指按下Alt,同时右手大拇指按下空格,然后按下对应的菜单命令字母,则可以实现窗体大小操作。具体的操 操作如下:

(2)Ctrl

Ctrl+Left/Right:按单词移动光标,而不是按字母移动,在编程的时候经常会用到,很多时候比鼠标快捷。

Ctrl+Home/End:定位到文章或者页面的顶部/底部,看网页或者编辑文章的时候比较有用。

Ctrl+鼠标点击:对于文本编辑是选中单词,可以代替双击;对于资源管理器是选中多个文件。

(3)Shift

Shift+方向键:选中连续的字符串或文件

Shift+Ctrl+方向键:按单词连续选中字符串

Ctrl+Shift、Ctrl+空格、Shift+空格:切换语言

以上三个键组合使用,在操作菜单、文本编辑、查看文件等方面会带来不小的便利。

2、方便的Windows键

Windows键上面已经介绍过它在键盘上的位置了,按下这个键,就相当于点击了开始菜单。但是Windows键的功能不只是为了很方便的打开开始菜单,配合其他键使用,才能表现出它的方便所在。下面就介绍一下它的妙用,以下用“Win”代表Windows键。

3、其他快捷键

(1)Tab

跳转:界面上有多个控件,按下Tab会使焦点跳转到下一个控件。

反向跳转:按下Shift+Tab,会使焦点按照相反的顺序在控件之间跳转。

在文本编辑区域中:Tab是缩进一个制表符,Shift+Tab是取消缩进一个制表符。

(2)空格键

默认确定:当弹出对话框时,或者焦点定位在某个按钮或者菜单项时,按下空格键相当于点击确认。

浏览器滚屏:当浏览器有滚动条时,按下空格键相当于翻页。

选中文件:在资源管理器中,当某个对象被虚线框住时,按下空格键就会选中该项。

(3)Fx系列按键

Fx系列按键是键盘最顶上一排按键,从F1到F12。其中常用按键对应的功能为

以上是Fx系列按键最常见的用法。很多软件都定义了自己的Fx系列功能键,需要根据实际情况操作。

(4)Esc

Esc就是取消键,在弹出对话框时,按下Esc默认就是点击“取消”。它处在键盘左上角,比移动鼠标到“取消”按钮上要快捷不少。

(5)键盘模拟右键

该键处在键盘右边的Ctrl和Win键之间,按下该键相当于对选定对象点右键。焦点已经定位到某个对象上,常规操作 方法是移动鼠标到该对象,然后点击右键并点击指定菜单项。如果用该键,则只需要按下该键,再按下对应菜单项的快捷键,相比之下要快速。比如压缩文件,如果 熟练的话,按下模拟右键,按下T回车,就可以完成压缩。在实际工作中,我也倾向于用该键,比移动鼠标到对应菜单项要方便。

三、工作中的快捷键

在日常工作中使用的软件,比如Visual Studio,它的功能非常多,菜单项有几十上百个。如果是在密密麻麻的菜单中寻找需要执行的命令,不可避免要花费一番功夫。如果能够记住最常用的快捷 键,也能让操作效率提高不少。下面列举一下工作中用到的快捷键,只列举暂时想到的,大家可以在后面补充。有些未列举的,可以自己在菜单里面查找。

Visual Studio(部分快捷键会因为选择的开发环境不同而不同,VS安装好之后第一次打开都会让用户选择模式,我一般选择常规模式。)

SQL Server

有部分快捷键和Visual Studio相同,比如注释,大家也可以多收集快捷键,对提高工作效率肯定有帮助。

四、用脚本语言加速

在本系列的上一篇文章中提到的Au3和AHK可以从很大程度上降低鼠标频繁操作。特别是遇到需要重复做机械性的鼠标 操作时,可以用脚本语言实现鼠标和键盘的操作,甚至可以用脚本录制工具把鼠标键盘操作记录下来。如果是安装了Au3,在安装文件夹中找到 SciTe\ScriptWriter\AU3Record.exe运行,点击左上角的Au3图标就开始录制了,很容易上手,如下图:

clip_image012

五、不需要鼠标的编辑器-Vim

如果你经常进行文本编辑操作,而且有希望能达到高手级别,那么强烈推荐你使用Vim编辑器。平时编辑文本的时候,经 常需要把手在键盘和鼠标之间切换,这个过程就比较影响效率。即便是使用方向键,也需要把右手从键盘的主区域移开。而Vim则完全不用鼠标和方向键,完全依 靠键盘的主区域。但是学习使用Vim是一个痛苦的过程,需要记住大量的命令。不过既然编程的那么多技术你都学会了,掌握Vim也不是难事。一旦你掌握了 Vim,你就会明白什么才是真正的编辑利器。详细信息可以参考以下文章:普通人的编辑利器——Vim简明 Vim 练级攻略

clip_image013

六、鼠标也可以飞

当然,本篇的目的是让你尽量少用鼠标,减少键盘和鼠标的切换,完全不用鼠标也是不可能的。上面讲到了对键盘进行增强,其实鼠标的功能也可以增强的,可以让鼠标和键盘一起飞。

首先是鼠标本身,一般的鼠标只有左键、右键、滚轮、滚轮点击。但是好一点的鼠标则可以有更多的键,比如前进、后退、双击、滚轮左右点击等等。这些更高级的功能可以从一定程度上提高鼠标操作的效率,多花一点钱也是值得的。

现在很流行触摸屏的手机,而且是多点触摸,因为手势操作可以带来很便捷的操作。虽然普通的电脑还没法像手机那样使用 触摸屏,但是鼠标手势也可以便利。我最开始接触鼠标手势是使用傲游浏览器,鼠标操作不再局限于点击和拖动,而是变成了笔画一样的方式。不同的手势意味着不 同的命令,操作便利性大幅提升。

clip_image014

傲游的鼠标手势确实非常好用,但是它只是局限于傲游浏览器本身。之后其他浏览器也都加入了鼠标手势功能,然而都没有 脱离软件本身。直到某一天看到搜狗输入法里面包含一个小工具:搜狗鼠标手势。它将鼠标手势扩展到了整个系统,而不仅仅局限于单个软件,再次提升了鼠标手势 的应用范围。

clip_image015

本文就介绍这些,快捷键和Windows命令只是介绍了常用的一些,遗漏的部分欢迎大家积极补充,让大家能更快的操作电脑,更快的完成工作!

[转载]PHP底层工作原理

mikel阅读(828)

[转载]PHP底层工作原理 – PHP淮北 – 博客园.

最近搭建服务器,突然感觉lamp之间到底是怎么工作的,或者是怎么联系起来?平时只是写程序,重来没有思考过他们之间的工作原理:

PHP底层工作原理

wps_clip_image-29471

图1 php结构

从图上可以看出,php从下到上是一个4层体系

①Zend引擎

Zend整体用纯c实现,是php的内核部分,它将php代码翻译(词法、语法解析等一系列编译过程)为可执行opcode的处理并实现相应的处理 方法、实现了基本的数据结构(如hashtable、oo)、内存分配及管理、提供了相应的api方法供外部调用,是一切的核心,所有的外围功能均围绕 zend实现。

②Extensions

围绕着zend引擎,extensions通过组件式的方式提供各种基础服务,我们常见的各种内置函数(如array系列)、标准库等都是通过 extension来实现,用户也可以根据需要实现自己的extension以达到功能扩展、性能优化等目的(如贴吧正在使用的php中间层、富文本解析 就是extension的典型应用)。

③Sapi

Sapi全称是Server Application Programming Interface,也就是服务端应用编程接口,sapi通过一系列钩子函数,使得php可以和外围交互数据,这是php非常优雅和成功的一个设计,通过 sapi成功的将php本身和上层应用解耦隔离,php可以不再考虑如何针对不同应用进行兼容,而应用本身也可以针对自己的特点实现不同的处理方式。后面 将在sapi章节中介绍

④上层应用

这就是我们平时编写的php程序,通过不同的sapi方式得到各种各样的应用模式,如通过webserver实现web应用、在命令行下以脚本方式运行等等。

构架思想:

引擎(Zend)+组件(ext)的模式降低内部耦合

中间层(sapi)隔绝web server和php

**************************************************************************

如果php是一辆车,那么

车的框架就是php本身

Zend是车的引擎(发动机)

Ext下面的各种组件就是车的轮子

Sapi可以看做是公路,车可以跑在不同类型的公路上

而一次php程序的执行就是汽车跑在公路上。

因此,我们需要:性能优异的引擎+合适的车轮+正确的跑道

Apache和php的关系

Apache对于php的解析,就是通过众多Module中的php Module来完成的。

wps_clip_image-31721

把php最终集成到Apache系统中,还需要对Apache进行一些必要的设置。这里,我们就以php的mod_php5 SAPI运行模式为例进行讲解,至于SAPI这个概念后面我们还会详细讲解。

假定我们安装的版本是Apache2 和 Php5,那么需要编辑Apache的主配置文件http.conf,在其中加入下面的几行内容:

Unix/Linux环境下:

LoadModule php5_module modules/mod_php5.so

AddType application/x-httpd-php .php

注:其中modules/mod_php5.so 是X系统环境下mod_php5.so文件的安装位置。

Windows环境下:

LoadModule php5_module d:/php/php5apache2.dll

AddType application/x-httpd-php .php

注:其中d:/php/php5apache2.dll 是在Windows环境下php5apache2.dll文件的安装位置。

这两项配置就是告诉Apache Server,以后收到的Url用户请求,凡是以php作为后缀,就需要调用php5_module模块(mod_php5.so/ php5apache2.dll)进行处理。

Apache的生命周期

wps_clip_image-8490

Apach的请求处理流程

wps_clip_image-17917

Apache请求处理循环详解
Apache请求处理循环的11个阶段都做了哪些事情呢?

1、Post-Read-Request阶段

在正常请求处理流程中,这是模块可以插入钩子的第一个阶段。对于那些想很早进入处理请求的模块来说,这个阶段可以被利用。

2、URI Translation阶段
Apache在本阶段的主要工作:将请求的URL映射到本地文件系统。模块可以在这阶段插入钩子,执行自己的映射逻辑。mod_alias就是利用这个阶段工作的。

3、Header Parsing阶段
Apache在本阶段的主要工作:检查请求的头部。由于模块可以在请求处理流程的任何一个点上执行检查请求头部的任务,因此这个钩子很少被使用。mod_setenvif就是利用这个阶段工作的。

4、Access Control阶段
Apache在本阶段的主要工作:根据配置文件检查是否允许访问请求的资源。Apache的标准逻辑实现了允许和拒绝指令。mod_authz_host就是利用这个阶段工作的。

5、Authentication阶段
Apache在本阶段的主要工作:按照配置文件设定的策略对用户进行认证,并设定用户名区域。模块可以在这阶段插入钩子,实现一个认证方法。

6、Authorization阶段
Apache在本阶段的主要工作:根据配置文件检查是否允许认证过的用户执行请求的操作。模块可以在这阶段插入钩子,实现一个用户权限管理的方法。

7、MIME Type Checking阶段
Apache在本阶段的主要工作:根据请求资源的MIME类型的相关规则,判定将要使用的内容处理函数。标准模块mod_negotiation和mod_mime实现了这个钩子。

8、FixUp阶段
这是一个通用的阶段,允许模块在内容生成器之前,运行任何必要的处理流程。和Post_Read_Request类似,这是一个能够捕获任何信息的钩子,也是最常使用的钩子。

9、Response阶段
Apache在本阶段的主要工作:生成返回客户端的内容,负责给客户端发送一个恰当的回复。这个阶段是整个处理流程的核心部分。

10、Logging阶段
Apache在本阶段的主要工作:在回复已经发送给客户端之后记录事务。模块可能修改或者替换Apache的标准日志记录。

11、CleanUp阶段
Apache在本阶段的主要工作:清理本次请求事务处理完成之后遗留的环境,比如文件、目录的处理或者Socket的关闭等等,这是Apache一次请求处理的最后一个阶段。

LAMP架构:

wps_clip_image-24435

从下往上四层:

①liunx 属于操作系统的底层

②apache服务器,属于次服务器,沟通linux和PHP

③php:属于服务端编程语言,通过php_module 模块 和apache关联

④mySQL和其他web服务:属于应用服务,通过PHP的Extensions外 挂模块和mySQL关联

Android系统架构图

lamp和安卓的架构图比较一下,貌似和lamp架构有点相似,本人不懂安卓,只是感觉上有点相似,高手可以指出区别,小弟在此不胜感谢

wps_clip_image-27187

从上往下:

安卓架构————–说明——–LAMP架构

1.应用程序 ——–具体应用——–web应用

2.应用程序框架 —-java————-PHP语言和库

3.系统运行库 :—-虚拟机———WEB服务器

⒋Linux 内核 :—操作系统——-lamp架构中的L

更深入的学习和了解可以查看下面:

风雨的博客http://www.laruence.com/2008/08/12/180.html

百度研发中心的博客http://stblog.baidu-tech.com/?p=763

王兴宾的博客http://blog.csdn.net/wanghao72214/article/details/3916825

[原创]C#的JSON数据格式转换方法

mikel阅读(1298)

之前一直用ASP.NET MVC中Json(value)方法转换成JsonResult格式的数据异步返回给JQuery进行处理,很爽,结果最近不用

ASP.NET MVC开发应用了,异步地区调用涉及到Json数据的获取发现居然没有好的Json格式数据转换方法像过去一样简单调用

很是不爽,搜了下找到个利用System.Runtime.Serialization.Json转换数据的方法,可以转换为JQuery可以识别的格式,不过

调用过程中发现它将实体类的属性名称转换成:”<属性名>k__BackingField ”

这种格式,调用起来很不方便,不过还是将这种方法编写的助手类贴出来:
注意需要引用:
首先,当然是项目是3.5的,

只引用一个System.Runtime.Serialization 是不够的,

还要添加 System.ServiceModel

System.ServiceModel.Web

的引用,OK
转载的文章中提到了

代码如下:

    /// <summary>
    /// FileName: JSONHelper.cs
    /// CLRVersion: 2.0.50727.3623
    /// Author: Mikel
    /// Corporation:
    /// Description:JSON格式数据转换助手类
    /// 1.将List<T>类型的数据转换为JSON格式
    /// 2.将T类型对象转换为JSON格式对象
    /// 3.将JSON格式对象转换为T类型对象
    /// DateTime: 2011-09-13 14:11:34
    /// </summary>
    public static class JSONHelper
    {
        /// <summary>
        /// 转换对象为JSON格式数据
        /// </summary>
        /// <typeparam name="T">类</typeparam>
        /// <param name="obj">对象</param>
        /// <returns>字符格式的JSON数据</returns>
        public static string GetJSON<T>(object obj)
        {
            string result = String.Empty;
            try
            {
                System.Runtime.Serialization.Json.DataContractJsonSerializer serializer =
                new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));
                using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
                {
                    serializer.WriteObject(ms, obj);
                    result = System.Text.Encoding.UTF8.GetString(ms.ToArray());
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return result;
        }
        /// <summary>
        /// 转换List<T>的数据为JSON格式
        /// </summary>
        /// <typeparam name="T">类</typeparam>
        /// <param name="vals">列表值</param>
        /// <returns>JSON格式数据</returns>
        public static string JSON<T>(List<T> vals)
        {
            System.Text.StringBuilder st = new System.Text.StringBuilder();
            try
            {
                System.Runtime.Serialization.Json.DataContractJsonSerializer s = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));

                foreach (T city in vals)
                {
                    using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
                    {
                        s.WriteObject(ms, city);
                        st.Append(System.Text.Encoding.UTF8.GetString(ms.ToArray()));
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return st.ToString();
        }
        /// <summary>
        /// JSON格式字符转换为T类型的对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="jsonStr"></param>
        /// <returns></returns>
        public static T ParseFormByJson<T>(string jsonStr)
        {
            T obj = Activator.CreateInstance<T>();
            using (System.IO.MemoryStream ms =
            new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(jsonStr)))
            {
                System.Runtime.Serialization.Json.DataContractJsonSerializer serializer =
                new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));
                return (T)serializer.ReadObject(ms);
            }
        }
    }

还是觉得ASP.NET MVC的Json转换比较地道,于是翻找其源码,发现是利用的.net Framework 3.5特有的
c:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Web.Extensions.dll
实现的Json数据格式转换,实现代码如下:

namespace System.Web.Mvc {
    using System;
    using System.Text;
    using System.Web;
    using System.Web.Script.Serialization;

    [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    [AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    public class JsonResult : ActionResult {

        public Encoding ContentEncoding {
            get;
            set;
        }

        public string ContentType {
            get;
            set;
        }

        public object Data {
            get;
            set;
        }

        public override void ExecuteResult(ControllerContext context) {
            if (context == null) {
                throw new ArgumentNullException("context");
            }

            HttpResponseBase response = context.HttpContext.Response;

            if (!String.IsNullOrEmpty(ContentType)) {
                response.ContentType = ContentType;
            }
            else {
                response.ContentType = "application/json";
            }
            if (ContentEncoding != null) {
                response.ContentEncoding = ContentEncoding;
            }
            if (Data != null) {
#pragma warning disable 0618
                JavaScriptSerializer serializer = new JavaScriptSerializer();
                response.Write(serializer.Serialize(Data));
#pragma warning restore 0618
            }
        }
    }
}

看到这大家应该明白了,原来.net Framework3.5已经做好了转换的方法,只需要调用即可,不过提醒大家注意:
一定要先引用c:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Web.Extensions.dll
才能使用JavaScriptSerializer serializer = new JavaScriptSerializer();
切记!切记!

[转载]如何引用 System.Runtime.Serialization.Json

mikel阅读(1112)

[转载]如何引用 System.Runtime.Serialization.Json; – Blackie – 博客园.

今天新开的一个项目突然发现引用System.Runtime.Serialization.Json 提示 命名空间 不存在类型或命名空间名称 json

明明前段时间刚开发的WCF是很正常的引用的,认真比照了引用的文件位置是一样的,记得前段时间在CSDN上也有人抱怨看不到System.Runtime.Serialization.Json

后面发现

首先,当然是项目是3.5的,

只引用一个System.Runtime.Serialization 是不够的,

还要添加 System.ServiceModel

System.ServiceModel.Web

的引用,OK

System.Runtime.Serialization.Json 出来了,可以开始对JSON字符串转为实体了。

命名空间 不存在类型或命名空间名称 json

[转载]JSON 数据格式解析

mikel阅读(935)

[转载]JSON 数据格式解析 – chen eric – 博客园.

JSON 数据格式解析

和 XML 一样,JSON 也是基于纯文本的数据格式。由于 JSON 天生是为 JavaScript 准备的,因此,JSON 的数据格式非常简单,您可以用 JSON 传输一个简单的 String,Number,Boolean,也可以传输一个数组,或者一个复杂的 Object 对象。

String,Number 和 Boolean 用 JSON 表示非常简单。例如,用 JSON 表示一个简单的 String “ abc ”,其格式为:

"abc"

除了字符 "\/ 和一些控制符(\b\f\n\r\t)需要编码外,其他 Unicode 字符可以直接输出。下图是一个 String 的完整表示结构:
图 1. String 的完整表示结构
 图 1. String 的完整表示结构
一个 Number 可以根据整型或浮点数表示如下:
图 2. Number 的表示结构
 图 2. Number 的表示结构
这与绝大多数编程语言的表示方法一致,例如:

12345(整数)
            -3.9e10(浮点数)

Boolean 类型表示为 truefalse 。此外,JavaScript 中的 null 被表示为 null,注意,truefalsenull 都没有双引号,否则将被视为一个 String 。

JSON 还可以表示一个数组对象,使用 [] 包含所有元素,每个元素用逗号分隔,元素可以是任意的 Value,例如,以下数组包含了一个 String,Number,Boolean 和一个 null:

["abc",12345,false,null]

Object 对象在 JSON 中是用 {} 包含一系列无序的 Key-Value 键值对表示的,实际上此处的 Object 相当于 Java 中的 Map<String, Object>,而不是 Java 的 Class 。注意 Key 只能用 String 表示。

例如,一个 Address 对象包含如下 Key-Value:

city:Beijing
            street:Chaoyang Road
            postcode:100025(整数)

用 JSON 表示如下:

{"city":"Beijing","street":" Chaoyang Road ","postcode":100025}

其中 Value 也可以是另一个 Object 或者数组,因此,复杂的 Object 可以嵌套表示,例如,一个 Person 对象包含 name 和 address 对象,可以表示如下:

{"name":"Michael","address":
            {"city":"Beijing","street":" Chaoyang Road ","postcode":100025}
            }

JavaScript 处理 JSON 数据

上面介绍了如何用 JSON 表示数据,接下来,我们还要解决如何在服务器端生成 JSON 格式的数据以便发送到客户端,以及客户端如何使用 JavaScript 处理 JSON 格式的数据。

我们先讨论如何在 Web 页面中用 JavaScript 处理 JSON 数据。我们通过一个简单的 JavaScript 方法就能看到客户端如何将 JSON 数据表示给用户:

function handleJson() {
            var j={"name":"Michael","address":
            {"city":"Beijing","street":" Chaoyang Road ","postcode":100025}
            };
            document.write(j.name);
            document.write(j.address.city);
            }

假定服务器返回的 JSON 数据是上文的:

{"name":"Michael","address":
            {"city":"Beijing","street":" Chaoyang Road ","postcode":100025}
            }

只需将其赋值给一个 JavaScript 变量,就可以立刻使用该变量并更新页面中的信息了,相比 XML 需要从 DOM 中读取各种节点而言,JSON 的使用非常容易。我们需要做的仅仅是发送一个 Ajax 请求,然后将服务器返回的 JSON 数据赋值给一个变量即可。有许多 Ajax 框架早已包含了处理 JSON 数据的能力,例如 Prototype(一个流行的 JavaScript 库:http://prototypejs.org)提供了 evalJSON() 方法,能直接将服务器返回的 JSON 文本变成一个 JavaScript 变量:

new Ajax.Request("http://url", {
            method: "get",
            onSuccess: function(transport) {
            var json = transport.responseText.evalJSON();
            // TODO: document.write(json.xxx);
            }
            });

服务器端输出 JSON 格式数据

下面我们讨论如何在服务器端输出 JSON 格式的数据。以 Java 为例,我们将演示将一个 Java 对象编码为 JSON 格式的文本。

将 String 对象编码为 JSON 格式时,只需处理好特殊字符即可。另外,必须用 (") 而非 (') 表示字符串:

            static String string2Json(String s) {
            StringBuilder sb = new StringBuilder(s.length()+20);
            sb.append('\"');
            for (int i=0; i<s.length(); i++) {
            char c = s.charAt(i);
            switch (c) {
            case '\"':
            sb.append("\\\"");
            break;
            case '\\':
            sb.append("\\\\");
            break;
            case '/':
            sb.append("\\/");
            break;
            case '\b':
            sb.append("\\b");
            break;
            case '\f':
            sb.append("\\f");
            break;
            case '\n':
            sb.append("\\n");
            break;
            case '\r':
            sb.append("\\r");
            break;
            case '\t':
            sb.append("\\t");
            break;
            default:
            sb.append(c);
            }
            }
            sb.append('\"');
            return sb.toString();
            }

将 Number 表示为 JSON 就容易得多,利用 Java 的多态,我们可以处理 Integer,Long,Float 等多种 Number 格式:

            static String number2Json(Number number) {
            return number.toString();
            }

Boolean 类型也可以直接通过 toString() 方法得到 JSON 的表示:

            static String boolean2Json(Boolean bool) {
            return bool.toString();
            }

要将数组编码为 JSON 格式,可以通过循环将每一个元素编码出来:

            static String array2Json(Object[] array) {
            if (array.length==0)
            return "[]";
            StringBuilder sb = new StringBuilder(array.length << 4);
            sb.append('[');
            for (Object o : array) {
            sb.append(toJson(o));
            sb.append(',');
            }
            // 将最后添加的 ',' 变为 ']':
            sb.setCharAt(sb.length()-1, ']');
            return sb.toString();
            }

最后,我们需要将 Map<String, Object> 编码为 JSON 格式,因为 JavaScript 的 Object 实际上对应的是 Java 的 Map<String, Object> 。该方法如下:

            static String map2Json(Map<String, Object> map) {
            if (map.isEmpty())
            return "{}";
            StringBuilder sb = new StringBuilder(map.size() << 4);
            sb.append('{');
            Set<String> keys = map.keySet();
            for (String key : keys) {
            Object value = map.get(key);
            sb.append('\"');
            sb.append(key);
            sb.append('\"');
            sb.append(':');
            sb.append(toJson(value));
            sb.append(',');
            }
            // 将最后的 ',' 变为 '}':
            sb.setCharAt(sb.length()-1, '}');
            return sb.toString();
            }

为了统一处理任意的 Java 对象,我们编写一个入口方法 toJson(Object),能够将任意的 Java 对象编码为 JSON 格式:

            public static String toJson(Object o) {
            if (o==null)
            return "null";
            if (o instanceof String)
            return string2Json((String)o);
            if (o instanceof Boolean)
            return boolean2Json((Boolean)o);
            if (o instanceof Number)
            return number2Json((Number)o);
            if (o instanceof Map)
            return map2Json((Map<String, Object>)o);
            if (o instanceof Object[])
            return array2Json((Object[])o);
            throw new RuntimeException("Unsupported type: " + o.getClass().getName());
            }

我们并未对 Java 对象作严格的检查。不被支持的对象(例如 List)将直接抛出 RuntimeException 。此外,为了保证输出的 JSON 是有效的,Map<String, Object> 对象的 Key 也不能包含特殊字符。细心的读者可能还会发现循环引用的对象会引发无限递归,例如,精心构造一个循环引用的 Map,就可以检测到 StackOverflowException

            @Test(expected=StackOverflowError.class)
            public void testRecurrsiveMap2Json() {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("key", map);
            JsonUtil.map2Json(map);
            }

好在服务器处理的 JSON 数据最终都应该转化为简单的 JavaScript 对象,因此,递归引用的可能性很小。

最后,通过 Servlet 或 MVC 框架输出 JSON 时,需要设置正确的 MIME 类型(application/json)和字符编码。假定服务器使用 UTF-8 编码,则可以使用以下代码输出编码后的 JSON 文本:

            response.setContentType("application/json;charset=UTF-8");
            response.setCharacterEncoding("UTF-8");
            PrintWriter pw = response.getWriter();
            pw.write(JsonUtil.toJson(obj));
            pw.flush();

小结

JSON 已经是 JavaScript 标准的一部分。目前,主流的浏览器对 JSON 支持都非常完善。应用 JSON,我们可以从 XML 的解析中摆脱出来,对那些应用 Ajax 的 Web 2.0 网站来说,JSON 确实是目前最灵活的轻量级方案。

[转载]LAMP网站架构方案分析

mikel阅读(820)

[转载]LAMP网站架构方案分析【精辟】 – PHP淮北 – 博客园.

LAMP(Linux- Apache-MySQL-PHP)网站架构是目前国际流行的Web框架,该框架包括:Linux操作系统,Apache网络服务器,MySQL数据 库,Perl、PHP或者Python编程语言,所有组成产品均是开源软件,是国际上成熟的架构框架,很多流行的商业应用都是采取这个架构,和 Java/J2EE架构相比,LAMP具有Web资源丰富、轻量、快速开发等特点,微软的.NET架构相比,LAMP具有通用、跨平台、高性能、低价格的 优势,因此LAMP无论是性能、质量还是价格都是企业搭建网站的首选平台。

对于大流量、大并发量的网站系统架构来说,除了硬件上使用高性能的服务器、负载均衡、CDN等之外,在软件架构上需要重点关注下面几个环节:使用高性能 的操作系统(OS)、高性能的网页服务器(Web Server)、高性能的数据库(Databse)、高效率的编程语言等。下面我将从这几点对其一一讨论。

操作系统

Linux操作系统有很多个不同的发行版,如Red Hat Enterprise Linux、SUSE Linux Enterprice、Debian、Ubuntu、CentOS等,每一个发行版都有自己的特色,比如RHEL的稳定,Ubuntu的易用,基于稳定性 和性能的考虑,操作系统选择CentOS(Community ENTerprise Operating System)是一个理想的方案。

CentOS(Community ENTerprise Operating System)是Linux发行版之一,是RHEL/Red Hat Enterprise Linux的精简免费版,和RHEL为同样的源代码,不过,RHEL和SUSE LE等企业版,提供的升级服务均是收费升级,无法免费在线升级,因此要求免费的高度稳定性的服务器可以用CentOS替代Red Hat Enterprise Linux使用。

LAMP网站架构方案分析

LAMP网站架构图

Web服务器、缓存和PHP加速

Apache是LAMP架构最核心的Web Server,开源、稳定、模块丰富是Apache的优势。但Apache的缺点是有些臃肿,内存和CPU开销大,性能上有损耗,不如一些轻量级的Web 服务器(例如nginx)高效,轻量级的Web服务器对于静态文件的响应能力来说远高于Apache服务器。

Apache做为Web Server是负载PHP的最佳选择,如果流量很大的话,可以采用nginx来负载非PHP的Web请求。nginx是一个高性能的HTTP和反向代理服 务器,Nginx以它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。Nginx不支持PHP和CGI等动态语言,但支持负载均衡和容 错,可和Apache配合使用,是轻量级的HTTP服务器的首选。

Web服务器的缓存也有多种方案,Apache提供了自己的缓存模块,也可以使用外加的Squid模块进行缓存,这两种方式均可以有效的提高 Apache的访问响应能力。Squid Cache是一个Web缓存服务器,支持高效的缓存,可以作为网页服务器的前置cache服务器缓存相关请求来提高Web服务器的速度,把Squid放在 Apache的前端来缓存Web服务器生成的动态内容,而Web应用程序只需要适当地设置页面实效时间即可。如访问量巨大则可考虑使用memcache作 为分布式缓存。

PHP的加速使用eAccelerator加速器,eAccelerator是一个自由开放源码PHP加速器,优化和动态内容缓存,提高了性能PHP脚 本的缓存性能,使得PHP脚本在编译的状态下,对服务器的开销几乎完全消除。它还有对脚本起优化作用,以加快其执行效率。使PHP程序代码执效率能提高 1-10倍。

具体的解决方案有以下几种:

1、squid + Apache + PHP + eAccelerator

使用Apache负载PHP,使用squid进行缓存,html或图片的请求可以直接由squid返回给用户。很多大型网站都采用这种架构。

2、nginx/Apache + PHP(fastcgi) + eAccelerator

使用nginx或Apache负载PHP,PHP使用fastcgi方式运行,效率较高。

3、nginx + Apache + PHP + eAccelerator

此方案综合了nginx和Apache的优点,使用Apache负载PHP,nginx负责解析其他Web请求,使用nginx的rewrite模块,Apache端口不对外开放。

数据库

开源的数据库中,MySQL在性能、稳定性和功能上是首选,可以达到百万级别的数据存储,网站初期可以将MySQL和Web服务器放在一起,但是当访问 量达到一定规模后,应该将MySQL数据库从Web Server上独立出来,在单独的服务器上运行,同时保持Web Server和MySQL服务器的稳定连接。

当数据库访问量达到更大的级别,可以考虑使用MySQL Cluster等数据库集群或者库表散列等解决方案。

总的来说,LAMP架构的网站性能会远远优于Windows IIS + ASP + Access(例如月光博客)这样的网站,可以负载的访问量也非常大,国内的大量个人网站如果想要支撑大访问量,采用LAMP架构是一个不错的方案。

综上所述,基于LAMP架构设计具有成本低廉、部署灵活、快速开发、安全稳定等特点,是Web网络应用和环境的优秀组合。

[转载]JQuery图表插件——Highcharts

mikel阅读(1060)

[转载]JQuery图表插件——Highcharts – LyIng.Net – 博客园.

因为项目中需要用到图表生成,所有Google了下,找到了这个插件,顺带写了个DEMO。点击跳转官网

先上三个图,分别是曲线、柱状、扇形。

图表中的数据纯属于DEMO的测试数据,没有实际用意。下面讲下大致的实现步骤

第一步,下载并且引用JS包(highcharts.js),theme顾名思义是放皮肤的。可以下载DEMO逐一试试就知道效果怎么样了,上图就 应用了两个样式。download中放的是打印和导出成图片的js文件(貌似是通过js上传到官网,然后再下载到本地),因为项目是放到内网的所以就没有 用了。

第二步,实现,贴代码。

var chart;
        $(document).ready(function() {
            chart = new Highcharts.Chart({
                chart: {
                    renderTo: 'container',          //放置图表的容器
                    plotBackgroundColor: null,
                    plotBorderWidth: null,
                    defaultSeriesType: 'line'   
                },
                title: {
                    text: 'JQuery曲线图演示'
                },
                subtitle: {
                    text: '副标题'
                },
                xAxis: {//X轴数据
                    categories: ['一月份', '二月份', '三月份', '四月份', '五月份', '六月份', '七月份', '八月份', '九月份', '十月份', '十一月份', '十二月份'],
                    labels: {
                        rotation: -45, //字体倾斜
                        align: 'right',
                        style: { font: 'normal 13px 宋体' }
                    }
                },
                yAxis: {//Y轴显示文字
                    title: {
                        text: '产量/百万'
                    }
                },
                tooltip: {
                    enabled: true,
                    formatter: function() {
                        return '<b>' + this.x + '</b><br/>' + this.series.name + ': ' + Highcharts.numberFormat(this.y, 1);
                    }
                },
                plotOptions: {
                    line: {
                        dataLabels: {
                            enabled: true
                        },
                        enableMouseTracking: true//是否显示title
                    }
                },
                series: [{
                    name: '杭州',
                    data: [7.0, 6.9, 9.5, 14.5, 18.4, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]
                }, {
                    name: '江西',
                    data: [4.0, 2.9, 5.5, 24.5, 18.4, 11.5, 35.2, 36.5, 23.3, 38.3, 23.9, 3.6]
                }, {
                    name: '北京',
                    data: [14.0, 12.9, 15.5, 14.5, 28.4, 21.5, 15.2, 16.5, 13.3, 28.3, 13.9, 13.6]
                }, {
                    name: '湖南',
                    data: [3.9, 4.2, 5.7, 8.5, 11.9, 15.2, 17.0, 16.6, 14.2, 10.3, 6.6, 4.8]
}]
                });
            });

这写都是配置,最重要的就是series里面的数据了,如果需要从数据库中取出来的话,直接生成json然后赋值上去就OK了,效果很炫,还有动态感,感兴趣的朋友可以下载下来跑跑。

注意,DEMO里的download文件夹中的js文件,本来导出及打印的一些提示是英文,我已经修改成中文了,在引用js文件的时候需要 charset=”gb2312″,具体DEMO中我已经写好了注释。好的,到此为止。下载地址

[转载]ASP.NET性能优化之构建自定义文件缓存

mikel阅读(864)

[转载]ASP.NET性能优化之构建自定义文件缓存 – 陆敏技 – 博客园.

SP.NET的输出缓存(即静态HTML)在.NET4.0前一直是基于内存的。这意味着如果我们的站点含有大量的缓存,则很容易消耗掉本机内存。 现在,借助于.NET4.0中的OutputCacheProvider,我们可以有多种选择创建自己的缓存。如,我们可以把HTML输出缓存存储到 memcached分布式集群服务器,或者MongoDB中(一种常用的面向文档数据库,不妨阅读本篇http://msdn.microsoft.com/zh-cn/magazine/gg650661.aspx)。当然,我们也可以把缓存作为文件存储到硬盘上,考虑到可扩展性,这是一种最廉价的做法,本文就是介绍如果构建自定义文件缓存。

1:OutputCacheProvider

OutputCacheProvider是一个抽象基类,我们需要override其中的四个方法,它们分别是:

Add 方法,将指定项插入输出缓存中。

Get 方法,返回对输出缓存中指定项的引用。

Remove 方法,从输出缓存中移除指定项。

Set 方法,将指定项插入输出缓存中,如果该项已缓存,则覆盖该项。

2:创建自己的文件缓存处理类

该类型为FileCacheProvider,代码如下:

public class FileCacheProvider : OutputCacheProvider
{
private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

public override void Initialize(string name, NameValueCollection attributes)
{
base.Initialize(name, attributes);
CachePath = HttpContext.Current.Server.MapPath(attributes["cachePath"]);
}

public override object Add(string key, object entry, DateTime utcExpiry)
{
Object obj = Get(key);
if (obj != null)    //这一步很重要
{
return obj;
}
Set(key,entry,utcExpiry);
return entry;
}

public override object Get(string key)
{
string path = ConvertKeyToPath(key);
if (!File.Exists(path))
{
return null;
}
CacheItem item = null;
using (FileStream file = File.OpenRead(path))
{
var formatter = new BinaryFormatter();
item = (CacheItem)formatter.Deserialize(file);
}

if (item.ExpiryDate &lt;= DateTime.Now.ToUniversalTime())
{
log.Info(item.ExpiryDate + "*" + key);
Remove(key);
return null;
}
return item.Item;
}

public override void Set(string key, object entry, DateTime utcExpiry)
{
CacheItem item = new CacheItem(entry, utcExpiry);
string path = ConvertKeyToPath(key);
using (FileStream file = File.OpenWrite(path))
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(file, item);
}
}

public override void Remove(string key)
{
string path = ConvertKeyToPath(key);
if (File.Exists(path))
File.Delete(path);
}

public string CachePath
{
get;
set;
}

private string ConvertKeyToPath(string key)
{
string file = key.Replace('/', '-');
file += ".txt";
return Path.Combine(CachePath, file);
}
}

[Serializable]
public class CacheItem
{
public DateTime ExpiryDate;
public object Item;

public CacheItem(object entry, DateTime utcExpiry)
{
Item = entry;
ExpiryDate = utcExpiry;
}
}

有两个地方需要特别说明:

在Add方法中,有一个条件判断,必须做出这样的处理,否则缓存机制将会缓存第一次的结果,过了有效期后缓存讲失效并不再重建;

在示例程序中,我们简单的将缓存放到了Cache目录下,在实际的项目实践中,考虑到缓存的页面将是成千上万的,所以我们必须要做目录分级,否则寻找并读取缓存文件将会成为效率瓶颈,这会耗尽CPU。

3:配置文件

我们需要在Web.config中配置缓存处理程序是自定义的FileCacheProvider,即在  <system.web>下添加节点:


4:缓存的使用

我们假设在MVC的控制中使用(如果要在ASP.NET页面中使用,则在页面中包含<%@OutputCache VaryByParam=”none”  Duration=”10″ %>),可以看到,Index是未进行输出缓存的,而Index2进行了输出缓存,缓存时间为10秒。

public class HomeController : Controller
{
private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
static string s_conn = "Data Source=192.168.0.77;Initial Catalog=luminjidb;User Id=sa;Password=sa;";
public ActionResult Index()
{
using (DataSet ds = Common.SqlHelper.ExecuteDataset(s_conn, CommandType.Text, "select top 1* from NameTb a, DepTb b where a.DepID = b.ID ORDER BY NEWID()"))
{
ViewBag.Message = ds.Tables[0].Rows[0]["name"].ToString();
}
return View();
}

[OutputCache(Duration = 10, VaryByParam = "none")]
public ActionResult Index2()
{
using (DataSet ds = Common.SqlHelper.ExecuteDataset(s_conn, CommandType.Text, "select top 1* from NameTb a, DepTb b where a.DepID = b.ID ORDER BY NEWID()"))
{
ViewBag.Message = ds.Tables[0].Rows[0]["name"].ToString();
}
return View();
}
}

5:查看下效果

上面的代码,在访问了Index2后,将会在Cache文件夹下产生缓存文件,如下:

image

现在,我们开始评价下有输出缓存和无输出缓存的性能对比,模拟100个用户并发1000次请求如下:

image

可以看到,有输出缓存后,吞吐率明显提高了10倍。

6:代码下载

FileCacheProvider的原始代码来自于网络,我修改了其中的BUG,全部代码下载如下:MvcApplication20110907.rar

[转载]优酷网架构分享

mikel阅读(778)

[转载]优酷网架构分享 – 一场情动,半世流离 – 博客园.

记得以前给大家介绍过视频网站龙头老大YouTube的技术架构,相信大家看了都会有不少的感触,互联网就是这么一个神奇的东西。今天我突然想到,优酷网在国内也算是视频网站的老大了,不知道他的架构相对于YouTube是怎么样的,于是带着这个好奇心去网上找了优酷网架构的各方面资料,虽然谈得没有YouTube那么详细,但多少还是挖掘了一点,现在总结一下,希望对喜欢架构的朋友有所帮助。

一、网站基本数据概览

  • 据2010年统计,优酷网日均独立访问人数(uv)达到了8900万,日均访问量(pv)更是达到了17亿,优酷凭借这一数据成为google榜单中国内视频网站排名最高的厂商。
  • 硬件方面,优酷网引进的戴尔服务器主要以 PowerEdge 1950与PowerEdge 860为主,存储阵列以戴尔MD1000为主,2007的数据表明,优酷网已有1000多台服务器遍布在全国各大省市,现在应该更多了吧。

二、网站前端框架

从一开始,优酷网就自建了一套CMS来解决前端的页面显示,各个模块之间分离得比较恰当,前端可扩展性很好,UI的分离,让开发与维护变得十分简单和灵活,下图是优酷前端的模块调用关系:

这样,就根据module、method及params来确定调用相对独立的模块,显得非常简洁。下面附一张优酷的前端局部架构图:

三、数据库架构

应该说优酷的数据库架构也是经历了许多波折,从一开始的单台MySQL服务器(Just Running)到简单的MySQL主从复制、SSD优化、垂直分库、水平sharding分库,这一系列过程只有经历过才会有更深的体会吧,就像MySpace的架构经历一样,架构也是一步步慢慢成长和成熟的。

1、简单的MySQL主从复制:

MySQL的主从复制解决了数据库的读写分离,并很好的提升了读的性能,其原来图如下:

其主从复制的过程如下图所示:

但是,主从复制也带来其他一系列性能瓶颈问题:

  1. 写入无法扩展
  2. 写入无法缓存
  3. 复制延时
  4. 锁表率上升
  5. 表变大,缓存率下降

那问题产生总得解决的,这就产生下面的优化方案,一起来看看。

2、MySQL垂直分区

如果把业务切割得足够独立,那把不同业务的数据放到不同的数据库服务器将是一个不错的方案,而且万一其中一个业务崩溃了也不会影响其他业务的正常进行,并且也起到了负载分流的作用,大大提升了数据库的吞吐能力。经过垂直分区后的数据库架构图如下:

然而,尽管业务之间已经足够独立了,但是有些业务之间或多或少总会有点联系,如用户,基本上都会和每个业务相关联,况且这种分区方式,也不能解决单张表数据量暴涨的问题,因此为何不试试水平sharding呢?

3、MySQL水平分片(Sharding)

这是一个非常好的思路,将用户按一定规则(按id哈希)分组,并把该组用户的数据存储到一个数据库分片中,即一个sharding,这样随着用户数量的增加,只要简单地配置一台服务器即可,原理图如下:

如何来确定某个用户所在的shard呢,可以建一张用户和shard对应的数据表,每次请求先从这张表找用户的shard id,再从对应shard中查询相关数据,如下图所示:

但是,优酷是如何解决跨shard的查询呢,这个是个难点,据介绍优酷是尽量不跨shard查询,实在不行通过多维分片索引、分布式搜索引擎,下策是分布式数据库查询(这个非常麻烦而且耗性能)

四、缓存策略

貌似大的系统都对“缓存”情有独钟,从http缓存到memcached内存数据缓存,但优酷表示没有用内存缓存,理由如下:

  1. 避免内存拷贝,避免内存锁
  2. 如接到老大哥通知要把某个视频撤下来,如果在缓存里是比较麻烦的

而且Squid 的 write() 用户进程空间有消耗,Lighttpd 1.5 的 AIO(异步I/O) 读取文件到用户内存导致效率也比较低下。

但为何我们访问优酷会如此流畅,与土豆相比优酷的视频加载速度略胜一筹?这个要归功于优酷建立的比较完善的内容分发网络(CDN),它 通过多种方式保证分布在全国各地的用户进行就近访问——用户点击视频请求后,优酷网将根据用户所处地区位置,将离用户最近、服务状况最好的视频服务器地址 传送给用户,从而保证用户可以得到快速的视频体验。这就是CDN带来的优势,就近访问,有关CDN的更多内容,请大家Google一下。

备注:本文转载自http://www.it-ezone.com

[转载]工作多年的.NET程序员,是否建立了自己的开发知识库?分享制作电子书的经验

mikel阅读(838)

[转载]工作多年的.NET程序员,是否建立了自己的开发知识库?分享制作电子书的经验 – James Li – 博客园.

经过多年的编程经验的积累,工作中肯定会遇到很多问题,也都通过各种办法解决了。无论是 上网搜索,或是向同事寻求帮忙,在遇到问题时,都会把这个系列的问题的网页都保存起来,以便以后查找起来方便。这样,随着时间的积累,知识库的内容会越来 越多,如何整理这些文件,方便查找,一直是工作之外努力的方向。

曾经用EverNote建立各种知识库,如下图所示,定期抽出时间,在网上搜索,看到好的文章,都剪贴下来

image

几个月下来,就积累了几十兆的数据,大部分是含有简单格式的文本数据,可设置格式,打印,非常方便。而且EverNote这个软件是绿色版,一共才8M多。每次要重装系统或是搬动数据资料,也连同软件一起拷贝。

与 EverNote同名的是微软的OneNote,一直不喜欢微软的捆绑风格,为了记个笔记,搜集点资料,要装那么大的软件,而且有时候会安装不成功,文件 组织方式也不同于EverNote,EverNote会按照数据库来组织你的笔记内容,你可以把相关的知识内容都放到一个数据库中,OneNote是按照 文件名来组织笔记,相比两者,更喜欢EverNote的风格。

更多的时候,忙于工作,没有时间上网,一直等到空闲的时候,想找个安静的地方学习(图书馆),又没有条件上网,如果你面对这样的情况,推荐下面这种方式给你,依照这个步骤,可以让你达到同样的效果。

1 下载网页文件到本机磁盘中

image

Data Loader是我为了搜集资料而开发的一个软件,如图所示。文本编辑器中是博客园中排名靠前的博主,他们的文章质量高,读起来效果好,项目忙,工作忙,常 常没有时间去一页页的读,然后拷贝到WORD,于是就想到用这个软件,分门别类,把他们的文章,都下载到本机磁盘中。点击Start按钮后,后台程序会下 载他们的文章到本地磁盘的G:\Document中。

image

所采用的格式是mht格式,可以保存图片,mht也是邮件的格式。如果可能,也可以通过互操作类型,把它存成DOC/DOCX格式,PDF格式也行,做这件事,对于程序员来说,不难。

2  Power CHM 登场,制作成CHM格式

博客园中Foundation博主写的工作流系列非常精彩,我用Power CHM导入上图中的目录,效果如下

image

这些是简单的活,不需要复杂的技术,点击File->Import Directory即可。可能有的页面会报脚本错误,没有关系,先不管,到后面再编辑它。点击Tools->CHM Compile ,生成CHM文件。
Power CHM已经内置了编译CHM文件的类型库,不需要安装Help workshop。顺便来看一下它的文件结构,我对这个hh.exe,hha.ddl感觉特别亲切,因为自己也曾经调用它来生成CHM文件,只是没有想到 做得更好,做成像Power CHM这样优秀的软件。这使我想到,做技术的致命缺点,懂一点,但又懂得不精,没有深入的研究,浅尝辙止。

image

等待一段时间,喝杯茶提提神,或是吃个苹果,片刻之后,就可以看到产生出的CHM文件了,如下图所示

image

我们就轻松的获取了CHM格式的电子书。依照这个办法,你可以做很多电子书。

在 我的Data Loader开放下载之前,你可以使用其他的网页下载软件,把网页下载到本地。实在找不到,写一个,调用WebClient类型,也应该是个把钟头的事 情,不会太难。先不要考虑太多问题,比如多线程,比如异步,你只是需要一个小程序来帮忙你把指定的网页下载到本地,记住,先把问题简化,有助于达到最终的 目的。

3  编辑CHM文件 整理成精致的CHM电子书

每位开发人员对技术的定位点不同,不同的开发阶段有不同的知识需求,这样,需要对CHM文件的内容进行取舍,制作需要的电子书。启动CHM Editor,打开刚才生成的Foundation.chm文件,如下图所示

image

CHM Editor专门用来编辑CHM文件,可对它直接进行编辑,即时保存。把不需要的文章删除,不需要的部分去掉,保存之后,就是我们需要的专题电子书了。此外,CHM Editor也是制作CHM文件的好工具,有了这个工具,你可以忽视网页

的存在。直接编辑,即时保存,就是你所需要的电子书文件。

CHM 格式仍然是Windows平台上流行的电子书格式文件,EXE格式容易被报病毒,或是被感染,PDF的格式查找不方便,缺少了CHM文件左边的树型导航 (虽然可以做出书签来,但是大量的免费的书都没有书签,自己做又很麻烦),会逊色很多。不过PDF着重点在于可移植的文档格式,是通用的格式,而CHM只 适用于Windows平台。