[转载]前向代理和反向代理 - 捣乱小子 - 博客园

mikel阅读(935)

[转载]前向代理和反向代理 – 捣乱小子 – 博客园.

第一次接触代理是在大二计算机网络课堂中,通由代理服务器可以让网络访问更具伸缩性,可以拒绝访问某些网站和协助访问被和谐的网站。最近无意中接触了反向代理,有对比正好有机会可以搞清楚前向代理和反向代理着两个概念。

前向代理 一般提到的是前向代理。表面上客户端 C 可以直接访问服务器 S,但实际上 C 在访问 S 的时候经过了中间的另一个中间的服务器 M,M就是代理服务器。为什么说是前向代理?因为前向代理是面向客户端的,而不是服务器。M 接收了 C 的请求后,(有选择的)对请求进行简化或者其他处理,再向目标服务器请求数据。

C————-M————-S

前向代理
前向代理

对请求进行简化或者其他处理意味着可以无视某些请求,譬如:学校发现 abc.com 站点上的内容很黄很暴力,为了在校学生的身心健康,在学校的代理服务器上对 abc.com 做限制,于是学生就不能访问 abc.com 站点了,也可以说 abc.com 被和谐了。除此之外,前向代理还有:

  1. 访问被和谐的站点,譬如翻墙等
  2. 隐藏客户端,真正与服务器打交道的是前向代理
  3. 提高访问速度,前向代理的缓存功能

关于前向代理,我们不得不熟悉闻名遐迩的 goagent 了。goagent 将 Google App Engine GAE 作为代理服务器中转,从而突破围墙。

反向代理 与前向代理相反,反向代理面向服务器,对于客户端 C 访问服务器 S 而言,好像 A 真的再访问 S 一样,其实真正的服务器是在 S 后面的 M.

C————-S————-M

反向代理
反向代理

所以,这幅图已经告诉我们反向代理能做些什么:

  1. 负载均衡,真正处理业务逻辑的是再往后的 web 服务器
  2. 加速访问静态内容,和前向代理一样有缓存的功能
  3. 隐藏真实服务器,客户端不知道真正后台服务器是怎么样的….

在这里要提一下 CDN 内容分发网络,反向代理可以是 CDN 的一种实现原理。为此,找到一幅好图:

CDN

从图中可以看到 www.yourdomain.com 设置有三个节点,USA、EU、APAC。这三个节点可以缓存一些静态内容,从而减轻后端服务器压力。当然,这只是原理,其中还很多很牛犇的技术在里面。欢迎补充。

捣乱 2013-08-01

http://daoluan.net/blog

[转载].NET框架设计—常被忽视的框架设计技巧 - 王清培 - 博客园

mikel阅读(883)

[转载].NET框架设计—常被忽视的框架设计技巧 – 王清培 – 博客园.

1】开篇介绍

通过上一篇的“.NET框架设计—常被忽视的C#设计技巧”一文来看,对于框架设计的技巧还是有很多人比较有兴趣的,那么框架设计思想对于我们日常开发来说其实并不是很重要,但是对于我们理解框架背后的运行原理至关重要;当我们使用着LINQ灵活的语法的同时我们是否能理解它的背后运行原理、设计原理更深一点就是它的设计模式及复杂的对象模型;

从一开始学习.NET我就比较喜欢框架背后的设计模型,框架提供给我们的使用接口是及其简单的,单纯从使用上来看我们不会随着对框架的使用时间而增加我们对框架内部设计的理解,反而会养成一样哪来即用的习惯,我们只有去了解、深挖它的内部设计原理才是我们长久学习的目标;因为框架的内部设计模式是可以提炼出来并被总结的;

 

这篇文章总结了几个我最近接触的框架设计思想,可以称他们为模式;由于时间关 系,这里只是介绍加一个简单的介绍和示例让我们能基本的了解它并且能在日后设计框架的时候想起来有这么一个模式、设计方式可以借鉴;当然,这每一节都是一 个很大主题,用的时候在去细心的分析学习吧;

2】元数据缓存池模式(在运行时构造元数据缓存池)

很多框架都有将特性放在属性上面用来标识某种东西,但是这种方式使用不当的话会对性能造成影响;再从框架设计原则来讲也是对DomainModel极大的污染,从EntityFramework5.0之前的版本我们就能体会到了,它原本是将部分Attribute加在了Entity上的,但是这毕竟是业务代码的核心,原则上来说这不能有任何的污染,要绝对的POJO;后来5.0之后就完全独立了DomainModel.Entity,所有的管理都在运行时构造绑定关系,因为它有EDMX元数据描述文件;

那么这些Attribute其实本质是.NET在运行时的一种元数据,主要的 目的是我们想在运行时将它读取出来,用来对某些方面的判断;那么现在的问题是如果我们每次都去读取这个Attribute是必须要走反射机制,当然你可以 找一些框架来解决这个问题;(我们这里讨论的是你作为开发框架的设计者!)

反射影响性能这不用多讲了,那么常规的做法是会在第一次反射之后将这些对象缓 存起来,下次再用的时候直接在缓存中读取;这没有问题,这是解决了反射的性能问题,那么你的Attribute是否还要加在DomainModel中呢, 如果加的话随着代码量的增加,这些都会成为后面维护的成本开销;那么我们如何将干净的POJO对象提供给程序员用,但是在后台我们也能对POJO进行强大 的控制?这是否是一种设计问题?

2.1】元数据设计模式(抽象出对数据的描述数据)

我一直比较关注对象与数据之间的关系,面向对象的这种纵横向关系如何平滑的与E-R实体关系模型对接,这一直是复杂软件开发的核心问题;这里就用它来作为本章的示例的基本概要;

我们有一个基本的DomainModel聚合,如何在不影响本身简洁性的情况下与E-R关系对接,比如我们在对聚合进行一个Add操作如何被映射成对数据库的Insert操作;我们来看一下元数据设计模式思想;

View Code

这里有一个以Employee实体为聚合根的聚合,里面包含一些基本的属性,特别需要强调的是Sex属性和Address,这两个属性分别是Complex类型的属性;
Complex类型的属性是符合面向对象的需要的,但是在关系型数据库中是很难实现的,这里就需要我们用元数据将它描述出来并能在一些行为上进行控制;

View Code

这是Address类型的定义;

View Code

这是SexType类型的定义;都比较简单;  

只有这样我们才能对DomainModel进行大面积的复杂设计,如果我们不能将数据对象化我们无法使用设计模式,也就谈不上扩展性;

图1:

这是我们的对象模型,那么我们如何将它与数据库相关的信息提取出来形成独立的元数据信息,对元数据的抽取需要动、静结合才行;

什么动、静结合,我们是否都会碰见过这样的问题,很多时候我们的代码在编译时是确定的,但是有部分的代码需要在运行时动态的构造,甚至有些时候代码需要根据当前的IDE来生成才行,但是最终在使用的时候这些在不同阶段生成的代码都需要结合起来变成一个完整的元数据对象;

框架在很多时候需要跟IDE结合才能使使用变的顺手,比如我们在开发自己的 ORM框架如果不能直接嵌入到VisualStudio中的话,用起来会很不爽;当我们用自己的插件去连接数据库并且生成代码的时候,有部分的元数据模型 已经在代码中实现,但是有部分需要我们动态的去设置才行;

我们来看一下关于元数据的基础代码;

View Code

这表示数据源上下文,属于运行时元数据的基础设施;

View Code

简单的表示一个Table,里面包含一系列的Columns;要记住在设计元数据基础代码的时候将接口留出来,方便在IDE中植入初始化元数据代码;

图2:

到目前为止我们都是在为元数据做基础工作,我们看一下有系统生成的声明的元数据代码;

View Code

我假设这是我们框架在IDE中生成的部分元数据代码,当然你可以用任何方式来存放这些元数据,但是最后还是要去对象化;

图3:

这个目录你可以直接隐藏,在后台属于你的框架需要的一部分,没有必要让它污染项目结构,当然放出来也有理由;如果想让你的LINQ或者表达式能直接穿过你的元数据上下文你需要直接扩展;

复制代码
1 static void Main(string[] args)
2         {
3             using (Repository.DesignBuilder_DataBaseContext context = new Repository.DesignBuilder_DataBaseContext())
4             {
5                 var employee = from emp in context.Employee where emp.EId == "Wqp123" select emp;
6             }
7         }
复制代码

 

这里所有的代码看上去很简单,没有多高深的技术,这也不是本篇文章的目的,任 何代码都需要设计的驱动才能产生价值,我们构建的基础代码都是元数据驱动;当你在运行时把这些元数据放入Cache,既不需要加Attribute也不需 要反射反而活动了更大程度上的控制,但是要想构建一个能用的元数据结构需要结合具体的需求才行;

2.2】借助Dynamic来改变IOC、AOP动态绑定的问题

要想在运行时完全动态的绑定在编译时定义的对象行为是需要强大的IOC框架支 撑的,这样的框架我们是做不来的或者需要很多精力,得不偿失;对于元数据设计需要将AOP通过IOC的方式注入,在使用的时候需要改变一下思路,AOP的 所有的切面在编译时无法确定,后期通过IOC的方式将所有的行为注入;这里我们需要使用动态类型特性;

使用Dynamic之后我们很多以往不能解决问题都可以解决,更向元编程跨进了一步;对于IOC、AOP的使用也将变的很简单,也有可能颠覆以往IOC、AOP的使用方式;而且动态编程将在很大程度上越过设计模式了,也就是设计模式的使用方式在动态编程中将不复存在了;

复制代码
 1 using (Repository.DesignBuilder_DataBaseContext context = new Repository.DesignBuilder_DataBaseContext())
 2             {
 3                 var employees = from emp in context.Employee where emp.EId == "Wqp123" select emp;
 4 
 5                 Employee employee = new Employee() { EId = "Wqp123" };
 6 
 7                 var entityOpeartion = DynamicBehavior.EntityDymanicBehavior.GetEntityBehavior<Employee>(employee);
 8 
 9                 entityOpeartion.Add();
10             }
复制代码

 

复制代码
 1 /*==============================================================================
 2  * Author:深度训练
 3  * Create time: 2013-08-04
 4  * Blog Address:http://www.cnblogs.com/wangiqngpei557/
 5  * Author Description:特定领域软件工程实践;
 6  *==============================================================================*/
 7 
 8 namespace ConsoleApplication1.DynamicBehavior
 9 {
10     using System;
11     using System.Dynamic;
12 
13     public class EntityDymanicBehavior
14     {
15         public static dynamic GetEntityBehavior<TEntity>(TEntity entity)
16         {
17             //auto mark entity behavior
18             dynamic dy = new ExpandoObject();
19             //load meta data mark dynamic behavior
20             dy.Entity = entity;
21             dy.Add = new Action(() =>
22             {
23                 Console.WriteLine("Action Add " + entity.GetType());
24             });
25             return dy;
26         }
27     }
28 }
复制代码

图4:

画红线的部分是可以抽取来放入扩展方法Add中的,在构造的内部是完全可以进入到元数据缓存池中拿到这些数据然后直接动态生成扩展方法背后的真实方法;

2.3】元数据和模型绑定、元数据应该隐藏在Model背后、元数据与DSL的关系

元数据的绑定应该在运行时动态去完成,这点在以往我们需要大费力气,通过 CodeDom、Emit才能完成,但是现在可以通过Dynamic、DLR来完成;思维需要转变一下,动态编程我们以往用的最多的地方在JS上,现在可 以在C#中使用,当然你也可以使用专门的动态语言来写更强大的元数据框架,IronRuby、IronPython都是很不错的,简单的了解过Ruby的 元数据编程,很强大,如果我们.NET程序员眼馋就用Iron…系列;

在开发复杂的动态行为时尽量使用元数据设计思想,不要把数据和表示数据的数据揉在一起,要把他们分开,在运行时Dynamic绑定;元数据应该在Model的背后应该在DomainModel的背后;

元数据和DSL有着天然的渊源,如果我们能把所有的语句组件化就可以将其封入.NET组件中,在IDE中进行所见即所得的DSL设计,然后生成可以直接运行的Dynamic代码,这可能也是元编程的思想之一吧;

图5:

这可能是未来10年要改变的编程路线吧,我只是猜测;最后软件将进一步被自定义;

3】链式配置Dynamic模式(爱不释手的思维习惯编程)

再一次提起链式编程是觉得它的灵活性无话可说,语言特性本身用在哪里完全需求驱动;把链式用来做配置相关的工作非常的合适;我们上面做了元数据配置相关的工作,这里我们试着用链式的方法来改善它;

Dynamic类型本身的所有行为属性都是可以动态构建的,那么我们把它放入链式的方法中去,根据不同的参数来实现动态的添加行为;

扩展Dynamic类型需要使用ExpandoObject开始;

复制代码
 1 /*==============================================================================
 2  * Author:深度训练
 3  * Create time: 2013-08-04
 4  * Blog Address:http://www.cnblogs.com/wangiqngpei557/
 5  * Author Description:特定领域软件工程实践;
 6  *==============================================================================*/
 7 
 8 namespace ConsoleApplication1.DynamicBehavior
 9 {
10     using System;
11     using System.Dynamic;
12 
13     public static class EntityDynamicBehaviorExtent
14     {
15         /// <summary>
16         /// Add dynamic method.
17         /// </summary>
18         /// <param name="entity"></param>
19         /// <returns></returns>
20         public static ExpandoObject AddExten(this ExpandoObject entity)
21         {
22             dynamic dy = entity as dynamic;
23             dy.Add = new Func<ExpandoObject>(() => { Console.WriteLine("add " + entity); return entity; });
24             return entity;
25         }
26         /// <summary>
27         /// where  dynamic method. 
28         /// </summary>
29         /// <typeparam name="T"></typeparam>
30         /// <param name="entity"></param>
31         /// <param name="where"></param>
32         /// <returns></returns>
33         public static ExpandoObject WhereExten<T>(this ExpandoObject entity, Func<T, bool> where)
34         {
35             dynamic dy = entity as dynamic;
36             dy.Where = where;
37             return entity;
38         }
39     }
40 }
复制代码

扩展方法需要扩展 ExpandoObject对象,DLR在运行时使用的是ExpandoObject对象实例,所以我们不能够直接扩展Dynamic关键字;

复制代码
1 Employee employee1 = new Employee() { EId = "Wqp123" };
2                 var dynamicEntity = DynamicBehavior.EntityDymanicBehavior.GetEntityBehavior<Employee>(employee1);
3                 (dynamicEntity as System.Dynamic.ExpandoObject).AddExten().WhereExten<Employee>(emp =>
4                 {
5                     Console.WriteLine("Where Method.");
6                     return emp.EId == "Wqp123";
7                 });
8                 dynamicEntity.Add().Where(employee1);
复制代码

 图6:

红线部分必须要转换才能顺利添加行为;

4】委托工厂模式(要优于常见的 工厂,概念更加准确,减少污染)

对于工厂模式我们都会熟悉的一塌糊涂,各种各样的工厂模式我们见的多了,但是这种类型的工厂使用方式你还真的没见过;其实这种委托是想部分的逻辑交给外部来处理;

复制代码
 1 /*==============================================================================
 2  * Author:深度训练
 3  * Create time: 2013-08-04
 4  * Blog Address:http://www.cnblogs.com/wangiqngpei557/
 5  * Author Description:特定领域软件工程实践;
 6  *==============================================================================*/
 7 
 8 namespace ConsoleApplication1.DomainModel
 9 {
10     /// <summary>
11     /// Address factory.
12     /// </summary>
13     /// <returns></returns>
14     public delegate Address Factory();
15 
16     /// <summary>
17     /// Employee.<see cref="DomainModel.Employee"/>
18     /// </summary>
19     public class Employee
20     {
21         public Employee() { }
22         /// <summary>
23         /// Mark employee instance.
24         /// </summary>
25         /// <param name="eID"></param>
26         /// <param name="name"></param>
27         /// <param name="sex"></param>
28         /// <param name="addressFactory">address factory.</param>
29         public Employee(string eID, string name, SexType sex, Factory addressFactory)
30         {
31             this.EId = eID;
32             this.Name = name;
33             this.Sex = sex;
34             this.Address = addressFactory();
35         }
36         /// <summary>
37         /// Primary id.
38         /// </summary>
39         public string EId { get; set; }
40 
41         /// <summary>
42         /// Name.
43         /// </summary>
44         public string Name { get; set; }
45 
46         /// <summary>
47         /// Sex.<see cref="DomainModel.SexType"/>
48         /// </summary>
49         public SexType Sex { get; set; }
50 
51         /// <summary>
52         /// Address.
53         /// </summary>
54         public Address Address { get; set; }
55     }
56 }
复制代码

我们定义了一个用来创建Employee.Address对象的Factory,然后通过构造函数传入;

View Code

这里纯粹为了演示方便,这种功能是不应该在DommianModel中使用的,都是在一些框架、工具中用来做灵活接口用的;

5】规则外挂(视委托为特殊的规则对象原型)

规则外挂其实跟上面的委托工厂有点像,但是绝对不一样的设计思想;如何将规则外挂出去,放入Cache中让运行时可以配置这个规则参数;委托是规则的天然宿主,我们只要将委托序列化进Cache就可以对它进行参数的配置;

复制代码
 1 /*==============================================================================
 2  * Author:深度训练
 3  * Create time: 2013-08-04
 4  * Blog Address:http://www.cnblogs.com/wangiqngpei557/
 5  * Author Description:特定领域软件工程实践;
 6  *==============================================================================*/
 7 
 8 namespace ConsoleApplication1.DomainModel.Specification
 9 {
10     using System;
11     using System.Linq.Expressions;
12 
13     /// <summary>
14     /// Employee add specification.
15     /// </summary>
16     [Serializable]
17     public class EmployeeSpecificationAdd : System.Runtime.Serialization.IDeserializationCallback
18     {
19         /// <summary>
20         /// specification.
21         /// </summary>
22         [NonSerialized]
23         private Func<Employee, bool> _specification;
24         /// <summary>
25         /// Gets specification.
26         /// </summary>
27         public Func<Employee, bool> Specificaion { get { return _specification; } }
28 
29         /// <summary>
30         /// employee.
31         /// </summary>
32         private Employee Employee { get; set; }
33 
34         /// <summary>
35         /// Mark employee specificatoin.
36         /// </summary>
37         /// <param name="employee"></param>
38         public EmployeeSpecificationAdd(Employee employee)
39         {
40             this.Employee = employee;

41             InitSpecification();
42         }
43         /// <summary>
44         /// Is Check.
45         /// </summary>
46         /// <returns></returns>
47         public bool IsCheck()
48         {
49             return _specification(Employee);
50         }
51 
52         public void OnDeserialization(object sender)
53         {
54             InitSpecification();
55         }
56         private void InitSpecification()
57         {
58             this._specification = (emp) =>
59             {
60                 return !string.IsNullOrWhiteSpace(emp.EId) && !string.IsNullOrWhiteSpace(emp.Name);
61             };
62         }
63     }
64 }
复制代码

图7:

注意这里的反序列化接口实现,因为Lambda无法进行序列化,也没有必要进行序列化;

复制代码
 1 EmployeeSpecificationAdd specification = new EmployeeSpecificationAdd(employee2);
 2 
 3                 Stream stream = File.Open("specification.xml", FileMode.Create);
 4                 BinaryFormatter formattter = new BinaryFormatter();
 5                 formattter.Serialize(stream, specification);
 6 
 7                 stream.Seek(0, SeekOrigin.Begin);
 8                 specification = formattter.Deserialize(stream) as EmployeeSpecificationAdd;
 9 
10                 stream.Close();
11                 stream.Dispose();
12                 if (specification.IsCheck())
13                 {
14                     Console.WriteLine("Ok...");
15                 }
复制代码

既然能将规则序列化了,就可以把它放在任何可以使用的地方了,配置化已经没有问题了;

示例Demo地址:http://files.cnblogs.com/wangiqngpei557/ConsoleApplication2.zip

[转载]CSS从大图片上截取小图标的操作 - 翟中龙 - 博客园

mikel阅读(1043)

[转载]CSS从大图片上截取小图标的操作 – 翟中龙 – 博客园.

注:图片名称(tabicons.png)每个小图标width:18px;height:18px从左上角坐标为(-0px;-0px;);

例如第一个对号的坐标为(-0px;-0px;)第二个加号的图标为(-20px;-0px;)中间依次加20个像素

截取小图标样式

复制代码
.icon
{
    background: url(imges/tabicons.png) no-repeat;
    width: 18px;
    line-height: 18px;
    display: inline-block;
}
.icon-set
{
 background-position: -380px -200px;
}

.icon-add
{
 background-position: -20px 0px;
}
复制代码
 样式调用示例
<form id="form1" runat="server">
    <div class="icon icon-sys">
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>
    </form>

 

[转载]JQuery MiniUI前端库最新越狱方法 - guoja - 博客园

mikel阅读(1746)

[转载]JQuery MiniUI前端库最新越狱方法 – guoja – 博客园.

前端时间有个项目不想用HTML自己画后台UI。图省事就准备用现成的JS UI库

当时初步选择了:

ExtJS:

功能比较全,但是库比较大,并且学习门槛较高,放弃

JQuery EasyUI

提供源码,功能丰富,使用方便,但是测试下来发现验证控件在某些情况下兼容性不太好。

并且个别控件的的性能极低,特别是TreeGrid,犹豫

MiniUI:

性能不错,上手容易。唯一不足就是非开源,代码混淆过,开发授权要上万张RMB,源码版价格更是夸张。

并且据说试用时间到期后:会不定时的弹出

 

经过一番比较,比较倾向于Miniui,虽然有使用时间限制。但是纯JS的,对码农来说应该和容易就越狱的。

(MINIUI貌似版权保护的很变态,网上所有的破解帖子\破解版都被和谐了)

 

项目进展顺利,很快就完成了上线了。可近期登陆后台就会不定时的出现,途中的弹出框。

虽然频率不高,但是用户很有意见。索性想办法处理掉。

下面就是本文重点:

MINIUI核心库经过混淆+文字编码位移等一系列手段,并且代码格式化后近3W行,靠读代码,修改代码肯定是不行了。

另辟途径:MINIUI的到期提示是通过JS的Alert 方法弹出的。

那么我们可以不可以截获所有Alert方法,过滤文本。然后….你们懂得

我们只需要在页面底部加入:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
var WinAlerts = window.alert;
window.alert = function (e) {
    if (e != null && e.indexOf("提示内容")>-1)
    {
        //和谐了
    }
    else
    {
        WinAlerts (e);
    }
    
};   

方法比较简单,就不细说了。。。

 

懂得自然就懂了。。。

 

特此声明:

本人没有改动Miniui的任何代码

[转载]Microsoft 电信项目组 Net代码生成器1.1 - Capo - 博客园

mikel阅读(844)

[转载]Microsoft 电信项目组 Net代码生成器1.1 – Capo – 博客园.

微软电信项目组代码生成器

为什么要使用这个代码生成器:

1.这个代码生成器采用 微软 企业库5.0 版本,目前CAPO所在的项目组都在使用这个

2.采用里面的代码我们做了一个 4W 人的项目,目前运行一年了,所有的一切运行良好

3.生成代码,非常简单,但是效率并不低下,很适合中小型项目的使用

4.代码生成器会自动根据 数据库(MsSQL2005以上) 主外键生成简单的业务逻辑

使用说明

1.生成的解决方案打开之后,您需要依次生成项目的顺序是: Framework,Model,DBUtility,DAL,BLL

2.生成的数据库存储过程,在DAL项目下的此命名空间下的 SQLCmd 目录里面,存储过程Insert 默认返回 @@Identity

3.项目所需要的类库,在项目目录下的 Library 文件夹下

4.目前数据库只支持 MsSQL 2005 以上系列

5.ORM架构马上推出

 

 

 

连接地址:http://files.cnblogs.com/capo/Microsoft%E7%94%B5%E4%BF%A1%E9%A1%B9%E7%9B%AE%E7%BB%84Net%E4%BB%A3%E7%A0%81%E7%94%9F%E6%88%90%E5%99%A8.rar

[转载]VOL.1 利用vmware ThinApp 制作非XP下可以运行的IE6 【无插件版】(windows vista/7/8 x86/x64 ) - 小明爱切糕 - 博客园

mikel阅读(828)

[转载]VOL.1 利用vmware ThinApp 制作非XP下可以运行的IE6 【无插件版】(windows vista/7/8 x86/x64 ) – 小明爱切糕 – 博客园.

作为一名前端开发工程师,不免要考虑IE6的兼容性,但是大部分挑剔的同行们估计都不会 用XP,所以基本上IE6的兼容性测试,都是使用IE Tester或者虚拟机。 IE Tester的话,很多地方模拟的还不够真实。至于虚拟机,效果是非常不错的,完美模拟,但是缺点也很明显,体积大,吃内存,分享不方便。最近看到网上同 学分享的使用ThinApp制作的IE6效果不错,这里分享给大家,目前是没有集成调试工具的,下一期将带来集成插件版的制作教程(目前是HTTP watch和IE dev Tool,有好用的IE6调试插件,欢迎留言)。在这里抛砖引玉,希望大家能指出错误或不足,互相学习,欢迎批评或参与讨论。

送给伸手党们(运行报错的话,欢迎留言):

http://pan.baidu.com/share/link?shareid=3602612818&uk=3424911262

准备工具

oracle VM VirualBox(虚拟机)

xp sp3镜像

vmware ThinApp

安装过程

XP的虚拟机安装过程就不再赘述了,网上教程很多。这里我用的虚拟机是用的virtualbox,vmvare的虚拟机也可以的。

1.打开虚拟机

2.启动XP到桌面

3.启动vmware ThinApp

4.点击下一步,什么都不用管

5.再点击下一步,会自动扫描系统

6.扫描完成之后,点击下面的“Internet Explorer… ”按钮,图中红框部分

7.弹出如图对话框,选择第三项

8.点击OK,点击下一步

9.继续下一步

10.继续下一步,这里选择第二项

11.点击下一步,选择第二项

12.点击下一步,选择第二项

13.点击下一步

14 点击下一步

15 点击保存,进入下一步

16 系统正在保存文件和注册信息

17 点击build,这个软件用熟练的同学可以直接编辑 package.ini

18 等待扫描完成之后,点击finish

19 好了,大功告成了,38.7M,集成插件之后差不多80M左右的样子

20 放在其他系统中试一下,本人是windows 7 x64 ultimate,截图挺多,整体过程还是挺简单的。

好了,制作好之后可以分享给你的同学或同事们,细心的同学可以尝试去阅读每个选项,这个软件可以将很多软件制作成单文件版,有兴趣的同学可以自己去研究一下,本期就到这里了。

[转载]几种Memcache的状态监控的工具,以及安装和使用【linux系统】 - 缘来小詹 - 博客园

mikel阅读(1346)

[转载]几种Memcache的状态监控的工具,以及安装和使用【linux系统】 – 缘来小詹 – 博客园.

1.Memcache-top的简介及安装和用法

简介:memcache-top是用perl语言编写的,可以运行在term下。它能够像top一样显示各个memcached节点的状态变化,其中包括系统管理员最关心的几个指数,例如:缓存命中率,内存使用率,读写QPS等
由于memcached安装时,需要使用libevent类库,所以先
安装libevent
libevent下载网址:https://github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gz

本手册中下载的是 libevent-2.0.21-stable.tar.gz版本安装步骤如下:

  1. 解压缩

  tar xzfv libevent-2.0.21-stable.tar.gz

  2. 进入到 libevent-2.0.21-stable目录

  cd libevent-2.0.21-stable

  3. 编译,安装

  ./configure

  make

  make install

  注:默认安装到/usr/local/lib/ 目录

安装memcached

  接下来,安装memcached

  memcached下载网址:http://memcached.googlecode.com/files/memcached-1.4.15.tar.gz

  本手册中下载的是 memcached-1.4.15.tar.gz版本

  安装步骤如下:

  1. 解压缩

  tar xzfv memcached-1.4.15.tar.gz

  2. 进入到 memcached-1.4.15目录

  cd memcached-1.4.15

  3. 编译,安装

  ./configure –prefix=/local/memcached

  make

  make install

  安装完成后,会在 usr/local/memcached 出现 bin和share目录

  进行 bin目录,启动 memcache

      ./configure

    Memcache-Top 安裝步驟如下:

 

  mkdir ~/srv/ 
  cd ~/srv/  
  svn checkout http://memcache-top.googlecode.com/svn/trunk/ memcache-top  
  cd memcache-top  
  sudo ln -s ~/srv/memcache-top/memcache-top /usr/bin/memcache-top  
  直接输入 memcache-top 就可以看到(预设是 localhost:11211)
  多台机器可用 memcache-top --instances localhost:11211,example1.com:11211,example2.com:11211

      下载后只有一个文件,可以打开它并进行memcached集群配置,多个节点之间以逗号分隔。

  # List of servers/ ports to query.
  @default_instances = (
   '127.0.0.1:11211',
  );
执行的时候,找到安装的位置,执行这个命令./memcache-top

用telnet 127.0.0.1 11211这样的命令连接上memcache,然后直接输入stats就可以得到当前memcache的状态。
这些状态的说明如下:

pid memcache服务器的进程ID
uptime 服务器已经运行的秒数
time 服务器当前的unix时间戳
version memcache版本
pointer_size 当前操作系统的指针大小(32位系统一般是32bit)
rusage_user 进程的累计用户时间
rusage_system 进程的累计系统时间
curr_items 服务器当前存储的items数量
total_items 从服务器启动以后存储的items总数量
bytes 当前服务器存储items占用的字节数
curr_connections 当前打开着的连接数
total_connections 从服务器启动以后曾经打开过的连接数
connection_structures 服务器分配的连接构造数
cmd_get get命令(获取)总请求次数
cmd_set set命令(保存)总请求次数
get_hits 总命中次数
get_misses 总未命中次数
evictions 为获取空闲内存而删除的items数(分配给memcache的空间用满后需要删除旧的items来得到空间分配给新的items)
bytes_read 总读取字节数(请求字节数)
bytes_written 总发送字节数(结果字节数)
limit_maxbytes 分配给memcache的内存大小(字节)
threads 当前线程数
2.Mc-top的简介及安装和用法
mctop 与 memcache-top 相似,主要用于监视 Memcache 的流量,包括 key 的调用次数、对象存储大小、每秒的请求数、以及消耗的网络带宽等。 
源代码:https://github.com/etsy/mctop

安装指令
  1. [root@ycw-houcm /]#cd usr
  2. [root@ycw-houcm usr]#cd local
  3. [root@ycw-houcm local]# yum install libpcap-devel ruby-devel rubygems git
  4. [root@ycw-houcm local]# gem install ruby-pcap -v ‘0.7.8’
  5. [root@ycw-houcm local]# gem install bundle
  6. [root@ycw-houcm local]# gem install rake
  7. [root@ycw-houcm local]# git clone git:github.com/etsy/mctop.git 
  8. [root@memcache2 mctop]# cd mctop/
  9. [root@memcache2 mctop]# bundle install 
  10. [root@memcache2 mctop]# rake install 
  11. [root@memcache2 mctop]# mctop -h
  12. [root@ycw-houcm mctop]# mctop -i eth0 -p 11211
使用方法:在安装目录执行命令 mctop -i eth0 -p 11211
3.memkeys的简介及安装和用法

简介memkeys是tumblr开源的类似top的工具,可用于实时查看memcached的key使用情况.

    memkeys安装

安装autoconf(要求版本2.68以上):

   安装其它依赖:

  • # yum install libpcap-devel pcre-devel ncurses-devel

   安装memkeys:

memkeys使用

  • # memkeys -h
  • Usage: memkeys -i NIC [options]
  • -d, –discard=THRESH Discard keys where req/s rate is below THRESH
  • -i, –interface=NIC Network interface to capture traffic on (required)
  • -p, –port=PORT Network port to capture memcache traffic on (default 11211)
  • -r, –refresh=INTERVAL Refresh the stats display every INTERVAL ms (default 500)
  • -l, –logfile=FILE Output logs to FILE
  • -R, –report=REPORT Output data in REPORT format (CSV or curses, default curses)
  •  
  • -h, –help This help
  • -v, –verbose Increase verbosity. May be used multiple times.
  • -V, –version Show program info and exit.

 例子1:

# memkeys -i eth0 -l /tmp/memkeys.log

 例子2:

# memkeys -i eth0 -d 10.0 -l /tmp/memkeys.log

写的不全的地方,希望大伙见谅,写的有错误的地方,希望大伙指点一下,我对linux不熟悉,只是最近用到了,就随便瞄几眼linux命令,有不了解的问题,大伙共同探讨一下O(∩_∩)O~

[转载]Go学习笔记 - 关于Java、Python、Go编程思想的不同 - 黑暗伯爵 - 博客园

mikel阅读(735)

[转载]Go学习笔记 – 关于Java、Python、Go编程思想的不同 – 黑暗伯爵 – 博客园.

看了两周七牛团队翻译的《Go语言程序设计》,基本上领略到了Go语言的魅力。学习一个语言,语法什么的任何人都是很容易学会,难就难在充分领略到这门编程语言的思想。

面向对象

喂!屌丝码农该找个对象了。

除去Java Python Go这三种语言底层以及语法的不同,这里以个人的理解只说说其面向对象方面的思想。 一个简单的示例:

描述人,李雷,韩梅梅,他俩都是好学生。

将用 java python go 这三种语言分别简单的描述。


Java 思想

人,是抽象的概念,可以洗衣做饭的灵长目物种,没法特指一样具体的东西,但它也有一些如性别、撒尿这类的属性和功能。

/**
 * 抽象出来的人
 */
abstract class Human {
    protected String sex;
    protected String name;

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getSex() {
        return this.sex;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    abstract void doPee(); // 抽象的方法
}

这里使用抽象类,是因为名字都是父母起的,但撒尿的方法男女不同。接下来是具象人这个抽象的概念了。这里就固话性别属性并且具体定义撒尿的方式。

/** * 具象的男性 */ class Male extends Human { public Male() { this.sex = “男”; }

    /**
     * 实现的方法
     */
    public void doPee() {
        System.out.println(this.name + " " + this.sex + "站着撒尿.");
    }
}

/**
 * 具象的女性
 */
class Female extends Human {
    public Female() {
        this.sex = "女";
    }

    /**
     * 实现的方法
     */
    public void doPee() {
        System.out.println(this.name + " " + this.sex + "蹲着撒尿.");
    }
}

现在有男人和女人了,然后李磊和韩梅梅就要来折磨我们了

Male lilei = new Male();
lilei.setName("李磊");
System.out.println(lilei.getName() + " " + lilei.getSex() + " " + "出场");

Female hanmeimei = new Female();
hanmeimei.setName("韩梅梅");
System.out.println(hanmeimei.getName() + " " + hanmeimei.getSex() + " " + "出场");

lilei.doPee();
hanmeimei.doPee();

_________________________________________________
output: 李磊 男 出场
output: 韩梅梅 女 出场
output: 李磊 男站着撒尿.
output: 韩梅梅 女蹲着撒尿.

李磊和韩梅梅都是好学生,我们这里定义学习的接口,这里的接口就是,大家必须得死学傻学,怎么学看你自己。

/**
 * 学习接口
 */
interface Study {
    public abstract void learningEnglish();
}

上面是教育部规定的,李磊韩梅梅作为学生必须得学,男人女人都得经历的。来实现学习接口。

 class Male extends Human implements Study {
    ......
    ......

    /**
     * 实现的接口
     */
    public void learningEnglish() {
        System.out.println(this.name + ": How are you?");
    }
}

/**
 * 具象的女性
 */
class Female extends Human implements Study {
    ......
    ......

    /**
     * 实现的接口
     */
    public void learningEnglish() {
        System.out.println(this.name + ": I'm fine, thank you!");
    }
}

......
......

lilei.doPee();
hanmeimei.doPee();

lilei.learningEnglish();
hanmeimei.learningEnglish();

_________________________________________________
output: 李磊: How are you?
output: 韩梅梅: I'm fine, thank you!

java的思想大致就是这么样。很严谨,就像一个老学究,1就是1,2就是2。

这是所有的java代码

Main.java

public class Main {

    public static void main(String[] args) {

        Male lilei = new Male();
        lilei.setName("李磊");
        System.out.println(lilei.getName() + " " + lilei.getSex() + " " + "出场");

        Female hanmeimei = new Female();
        hanmeimei.setName("韩梅梅");
        System.out.println(hanmeimei.getName() + " " + hanmeimei.getSex() + " " + "出场");

        lilei.doPee();
        hanmeimei.doPee();

        lilei.learningEnglish();
        hanmeimei.learningEnglish();
    }
}

/**
 * 抽象出来的人
 */
abstract class Human {
    protected String sex;
    protected String name;

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getSex() {
        return this.sex;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    abstract void doPee(); // 抽象的方法
}

/**
 * 学习接口
 */
interface Study {
    public abstract void learningEnglish();
}

/**
 * 具象的男性
 */
class Male extends Human implements Study {
    public Male() {
        this.sex = "男";
    }

    /**
     * 实现的方法
     */
    public void doPee() {
        System.out.println(this.name + " " + this.sex + "站着撒尿.");
    }

    /**
     * 实现的接口
     */
    public void learningEnglish() {
        System.out.println(this.name + ": How are you?");
    }
}

/**
 * 具象的女性
 */
class Female extends Human implements Study {
    public Female() {
        this.sex = "女";
    }

    /**
     * 实现的方法
     */
    public void doPee() {
        System.out.println(this.name + " " + this.sex + "蹲着撒尿.");
    }

    /**
     * 实现的接口
     */
    public void learningEnglish() {
        System.out.println(this.name + ": I'm fine, thank you!");
    }
}

Python 思想

python无以言状的灵活,你就是上帝!

这里我们只要创建一个根类,其他的东西,随时随地,想加就加。

class Human:
"""
人
"""
def __init__(self):
    self.__name = ""
    self.__sex = ""

def setName(self, name):
    self.__name = name

def getName(self):
    return self.__name

def setSex(self, sex):
    self.__sex = sex

def getSex(self):
    return self.__sex

name = property(getName, setName) # 就像java中的POJO setter以及getter
sex = property(getSex, setSex) # 就像java中的POJO setter以及getter

下面就边执行边丰满它

lilei = Human()
lilei.sex = "男"
lilei.name = "李磊"
print "%s %s 出场" % (lilei.name, lilei.sex)

hanmeimei = Human()
hanmeimei.sex = "女"
hanmeimei.name = "韩梅梅"
print "%s %s 出场" % (hanmeimei.name, hanmeimei.sex)

# Pee的方法
def doPee(self, how):
print "%s %s %s撒尿" % (self.name, self.sex, how)

Human.doPee = doPee #动态绑定方法

lilei.doPee("站着")
hanmeimei.doPee("蹲着")

# 学习的方法
def doLearning(self, learn):
print "%s: %s" % (self.name, learn)

Human.doLearning = doLearning #动态绑定方法

lilei.doLearning("How are you?")
lilei.doLearning("I'm fine, thank you!")

_________________________________________________
output: 李磊 男 出场
output: 李磊韩梅梅 女 出场
output: 李磊 男 站着撒尿
output: 韩梅梅 女 蹲着撒尿
output: 李磊: How are you?
output: 李磊: I'm fine, thank you!

python中一切对象都是鸭子类型,何谓鸭子类型?只要会”嘎嘎”叫的东西都是鸭子。应用到上面场景中,只要具有学习和 撒尿方法的对象都可以看作人了。从另一方面说,我对于鸭子只关注它是否能够”嘎嘎”叫,如果能,不管是什么东西,那么它就是一只鸭子; 对于人,只关注他们是否能撒尿与学习,既能撒尿又能学习,他凭什么就不是人?

python和java就好像阴阳之替的东方玄学之余西方哲学。

这是所有的python代码

test.py:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

class Human:
"""
人
"""
def __init__(self):
    self.__name = ""
    self.__sex = ""

def setName(self, name):
    self.__name = name

def getName(self):
    return self.__name

def setSex(self, sex):
    self.__sex = sex

def getSex(self):
    return self.__sex

name = property(getName, setName) # 就像java中的POJO
sex = property(getSex, setSex) # 就像java中的POJO

if __name__ == '__main__':

lilei = Human()
lilei.sex = "男"
lilei.name = "李磊"
print "%s %s 出场" % (lilei.name, lilei.sex)

hanmeimei = Human()
hanmeimei.sex = "女"
hanmeimei.name = "韩梅梅"
print "%s %s 出场" % (hanmeimei.name, hanmeimei.sex)

# Pee的方法
def doPee(self, how):
    print "%s %s %s撒尿" % (self.name, self.sex, how)

Human.doPee = doPee #动态绑定方法

lilei.doPee("站着")
hanmeimei.doPee("蹲着")

# 学习的方法
def doLearning(self, learn):
    print "%s: %s" % (self.name, learn)

Human.doLearning = doLearning #动态绑定方法

lilei.doLearning("How are you?")
lilei.doLearning("I'm fine, thank you!")

Go 思想

面向对象之于Go,没有继承这么一说,更像是C与Python的结合体,并把鸭子类型发扬到极致。

接口(interface)就好比是一只”鸭子”,而interface结构体内包裹的方法就是这只”鸭子”所具有的功能,Go中,接口可以描述为: 具有这些功能的家伙就是这只”鸭子”

方法(func)被定义在结构(类/struct)之外,被绑定于这个结构之上,可以描述为: 这是它的功能 ,当一个struct中的一些方法都包含在某个interface中时,我们就说: 啊哈,这就是那只”鸭子”,哪怕它多长了几条腿(func),它也是啊

关于继承,没有,go中虽然内嵌很像继承但不是。继承是一脉相传,而go的内嵌表达出你中有我我中有你的情怀,需要用到某个struct的功能了,那么就对它说 你就是我的一部分

struct、interface、func 这些几乎就是Go面向对象的全部了,如此简洁。

package main

import (
    "fmt"
)

// 接口 学生
type Student interface {
    learningEnglish(string)
}

// 结构
type Human struct {
    Name string
    Sex  string
}

// 学习英语方法,绑定于Human
func (student Human) learningEnglish(learning string) {
    fmt.Printf("%s: %s\n", student.Name, learning)
}

// 结构 男人
// go没有继承这个概念,这里是嵌入
type Male struct {
    Human "嵌入字段"
}

type Female Male

// 方法, 绑定到了Human结构
func (this Human) Pee(how string) {
    fmt.Printf("%s %s %s撒尿\n", this.Name, this.Sex, how)
}

// 学习
func doLearning(learning Student, learing string) {
    learning.learningEnglish(learing)
}

// Pee
func doPee(human interface {}) {
    switch sex := human.(type){
    case Male:
        sex.Pee("站着")
    case Female:
        sex.Pee("蹲着")
    }
}

func main() {
    lilei := Male{}
    lilei.Name = "李雷"
    lilei.Sex = "男"
    fmt.Printf("%s %s 出场\n", lilei.Name, lilei.Sex)

    hanmeimei := Female{}
    hanmeimei.Name = "韩梅梅"
    hanmeimei.Sex = "女"
    fmt.Printf("%s %s 出场\n", hanmeimei.Name, hanmeimei.Sex)

    doPee(lilei)
    doPee(hanmeimei)

    doLearning(lilei, "How are you?")
    doLearning(hanmeimei, "I'm fine, thank you!")
}

摆脱C++/Java/Python等思想的桎梏,才能领略Go的魅力

[转载]Codementor为开发者提供即时的一对一在线编程指导 | 36氪

mikel阅读(724)

[转载]Codementor为开发者提供即时的一对一在线编程指导 | 36氪.

见过抓狂的程序员不,被一个棘手的编程问题卡到是他们颇为头痛的问题,可偏偏当时又四下无人,求指点是他们能想到的最浪漫的事吧。初创公司Codementor目前正在致力于解决这个问题, 该平台由导师团队为遇到问题的开发者提供一对一的在线指导,采取付费模式,Codementor 会从学员全额费用中抽取 20%—30% 的佣金。该项目尚处于内测阶段。

目前,该网站在美国、欧洲、亚洲的导师团队总计 300 人,涉及 30 多个专业方向,包括 Ruby、Python、PHP、JavaScript、CSS/HTML、 iOS、Android 等。导师们在 GitHub 和及 Stack Overflow 这些社区的代码库是 Codementor 非常看重的资源。

就交流方式而言,程序员可以跟导师通过代码 / 截屏分享、视频对话、文字沟通的方式进行沟通,Codementor 努力营造一种面对面学习的效果。Codementor 采取两种在线提问方式,一是直接在 Codementor 网站上提交问题,比如你提交了 Ruby 方面的问题,系统就会给出在线的 Ruby 方向的导师。另一种方式还在测试当中,它允许程序员
在博客中内置插件,他们直接在博客发布问题就 OK 了。

对于紧迫程度高的问题一般会在 2 个小时内得到解决,常规性问题最长解决周期则是 24 个小时。Codementor 的最终目标是让程序员的问题得到即时解决。除却解决棘手问题,Codementor 还提供在线培训,以让开者可以得到深度指导。

Codementor 采用的 5 星评价机制,每次指导或培训结束之后,学员有权对导师进行评分,为保证质量,如果导师的评分低至一定额度就会被淘汰出局。如果学员对效果不满意,Codementor 承诺全额退款。

Codementor 创始人 Weiting Liu(前 SocialPicks 骨干创始人)说,“有了 Codementor,管理人员就无须为解决一个棘手的技术问题花上几千美金了。”

[转载]那些VisualStudio隐藏的调试功能 - 微软互联网开发支持 - 博客园

mikel阅读(936)

[转载]那些VisualStudio隐藏的调试功能 – 微软互联网开发支持 – 博客园.

VisualStudio是一个强大的调试工具,里面很多隐藏功能少有人问津,但是在特定场景可以节省你很多时间,本文主要介绍一些VisualStudio调试相关的隐藏功能,欢迎大家补充。

运行到指针(Run to cursor)

大多数人用Visual Studio在调试程序的时候先在程序开始的时候设置一个断点,然后依次F10/F11到自己想要查看的逻辑。如果这个过程我们需要仔细查看每一步的变量 或者执行路径,这样做无可厚非,但是如果我们不想关心前面执行的逻辑,我们可以使用Run to cursor功能,只需要鼠标指针点到你想要执行到的那一行代码,Ctrl+F10,程序直接停在了鼠标指针的那行代码。

条件断点(Conditional Breakpoint)

断点大家都会用,条件断点相信对于经常调试的也不陌生,使用方法如下图,

看上面这个右键菜单,Hit Count估计很多人也再用,用它来指定在第几次hit到这个断点的时候断下来,

接下来就更高级一些,Filter,相信很多人在调试多线程程序的时候都遇到过被其他线程干扰吧,好不容易断下 来,一步一步F10,忽然间另外一个线程又把前面断点hit了,刚才我跳的线程是哪个?想找到就难了。接下来就需要Filter来出场了。通过 Filter我们可以过滤需要break的机器/进程/线程。

接下来就是When Hit选项了,这个估计很多人用过它来跟踪变量,上图,带过。

Export, 导出断点的功能用的就更少了,其实有些场景断点导出可以让你少费很多话。比如你在某段代码发现一个别人的bug,你可以将断点导出为xml,然后将它attach到bug上,bug owner直接找到对应版本导入断点,运行程序就可以了。

数据提示(Data Tips)

调试的时候将鼠标放在变量名上来查看关心的数据,我们都是这么做的,但是如果一段逻辑需要反复执行,例如调试某段算法,你可以多点一下鼠标,将这个变量钉在代码旁边,这样比去watch窗口看要少转很多眼珠哦。

另外这些data tip也是可以导入和导出的。

查看反汇编代码

查看反汇编代码可以说是一个VisualStudio里面的一个隐藏功能,这个功能很少有人会注意到,但是对于我们想要学习汇编语言或者理解一些特定的编译器行为有很大的帮助。这个功能将汇编语言和源代码参照显示,理解起来容易许多。

使用该功能很简单,以我们在windbg u/uf/ub命令介绍中的程序代码qsort.c为例,在VisualStudio里面打开程序,设置断点,直接通过VisualStudio运行程序,或者attach到已经运行的程序中,当断点被触发后,右键然后选择go to disassembly,

反汇编效果如下,接下来再看swap方法的汇编代码,是不是很容易理解了?