上个月,JavaEye创始人范凯robbin的一篇博客《对.NET系统架构改造的一点经验和教训》引起了大讨论,里面提到了京东“去.Net化”、“CSDN去.Net化”之类的词刺激到了一些人的神经,有的人在评论中破口大骂“.Net最牛逼,.Net搞不好是你技术不行”,有的人则骂“.Net就是垃圾,上不了大台面”。有些朋友还在微博上at我,问我“杨老师,.net是不是不行了,听说大网站都‘去.Net化’了”、“杨老师,关于‘去.Net化’你怎么看?”,所以我还是来谈谈所谓的“去.Net化”吧。
        其实只要认真看robbin的文章,就会知道他并不是在说“去.Net化”而是在说“怎样搭建合适的网站框架”。注意看这段话:

  • 数据层放弃SQL Server数据库和存储过程,全部迁移到Linux平台上的MySQL数据库上;

  • 缓存不再依赖.net自身提供的缓存机制,迁移到部署在Linux平台上的分布式的Redis上;

  • 服务之间的调用,避免使用.net自身专有协议,改成Restful的HTTP Web API调用;

  • 静态资源请求,不再让IIS自己处理,分离到Linux平台上的nginx去处理;

  • 需要读取的文件系统,也改成访问Linux平台上的分布式文件系统;

  • 部署.net代码的Windows服务器放在LVS后面,用LVS做负载均衡和故障切换;


   简单说来,就是单纯让.net做应用层的编程语言和框架,其他都交给Linux平台的开源解决方案。而.net框架单纯做应用层,无论ASP.net MVC的开发效率,还是.net CLR虚拟机的运行效率都非常好,目前我们单台Windows服务器上跑几百万的动态请求毫无压力,而且应用层架构是可以横向扩展的:如果请求负载非常高,只需要添加更多Windows服务器即可。总之,做到了扬长避短。


 熟悉大型互联网技术架构的人应该很容易的发现,这个重构过程其实就是一个“让合适的东西干合适的事情”这样一项工作:

  • 把过多业务逻辑写到存储过程中必然导致数据库服务器压力的增大,而且不利于负载均衡,因此去“存储过程”是必要的;

  • SQLServer实现集群的能力很差,用MYSQL之类的数据库是一个不错的选择;

  • 缓存还是用.Net内置的InProc缓存机制对于高并发的网站来讲是一个灾难,用Redis之类分布式缓存来代替是必然的过程;

  • 使用.Net Remoting之类的私有协议不利于异构系统集成,改成webservice、REST也是必须的;

  • 静态文件的请求也经过IIS有点太劳烦IIS了,扔给nginx才更合适;

  • Windows服务器的文件系统很不灵活,换成更加灵活的Linux下的分布式文件系统是聪明的;

  • 采用LVS、nginx之类做负载均衡也是最合适的。


         其实任何一个大型互联网基本都是这样一个架构:前端使用nginx等做负载均衡,使用Redis、memcached等做分布式缓存,使用数据库集群进行读写分离之类的优化,使用分布式文件系统处理图片等静态文件。         请问,使用PHP、Java等做web服务器开发的大型互联网,哪个使用JSP内置的Session对象做Session的,不都要换用redis吗?哪个把图片和php放到一个服务器的,不都放到文件服务器中吗?哪个一个apache服务器就可以扛起来的,不都是nginx之类的挡在前面做负载均衡的吗?  怎么不说“去php化”、“去java化”呢?要知道redis、memcached、ngix之类的可都不是java、php写的呀,一个java项目竟然用其他语言写的东西,难道不丢面子?
            其实一个大型的系统中,根据项目的不同特点来组合搭配不同的产品、组件是一个必然的过程,去了解一下这些系统中“混搭”是常见的现象。单一产品中提供能的功能只能满足普通项目的需求,要想满足复杂的项目,必须把这些产品中提供的一些傻瓜化的简单组件用更专业的组件来替换,就像做小项目php中的Session足够了,但是大项目必须用c/c++开发的memcached来替换。

        我前阵子我发了一个帖子《【分享】.Net有哪些大型项目、大型网站的案例?》 ,这个帖子中提到的.Net技术的大型网站绝大部分都是“混搭结构”的(这些网站中至少有10个有传智播客.Net培训班的学生,我都跟他们交流过他们的技术架构)。很奇怪的一件事情是,在Java、PHP社区中经常可以看到讨论这些“架构”的文章,但是在.Net社区中则很少见到有人分享这些东西。希望.Net社区中的技术大牛们以后能把这些经验多多分享,让更多的人能够了解这些技术并且在项目中应用这些技术,提升.Net社区讨论技术的层次,不要让.Net社区的人总是在讨论一些很初级的问题,最起码不要只是为了不同网页头尾统一就使用又笨又重的MasterPage(其实用一下shtml就可以了)、不要讨论个三层架构就认为是架构师了、不要弄个代码生成器就是高科技了……咱们也要真正的拥抱Best Practice、拥抱混搭。

        不希望这个博文又成为不同语言相互***的月经贴,希望大家讨论一些真正有用的东西。



统计《ASP.Net特供视频教程》总长度

虽然传智播客的.net课程体系已经是国内最好的,但是我总感觉还有很大的改进空间,应该能让同学们学的更轻松、更透彻。我借鉴JavaPHP的课程体系,并且和企业中的软件工程师、传智播客的任课老师交流探讨,经过半年多时间我研究出一套新的“HttpHandler+模板引擎”课程体系,录制了这套新的《传智播客ASP.net特供视频教程2014版》(下载地址:51cto.comsubject/tegongnet/index.html

这套视频教程是专门为自学的同学录制的,自学的同学时间都不像在传智播客脱产学习的同学那样有大块的时间,碎片的时间比较多,所以这次的视频一般都是10-20 分钟一段的“短视频”,一段视频讲一个知识点。看着网上同学们对这套视频的赞美我心里很高兴,忽然想统计一下这套视频一共多长时间,由于视频文件很多,一共72 个,挨个打开进行累加不是程序员应该想起的办法。所以就打算写一个程序来完成这件事,最核心的问题就是“获得一个视频文件的时长”。ffmpeg 是一个专业的音频视频处理开源技术,借助于它可以完成视频转码、视频截图、视频提取等工作,ffmepg 也提供了获取视频长度的方法,不过想想只是获取视频长度这么一件事就要动用ffmpeg 有点“杀鸡用牛刀”的感觉,所以就上网搜寻是否有其他获得视频文件长度的方法,很快就找到了这样一篇文章《 C#获取视频文件播放时长 》,使用下面的代码就可以获得视频文件的长度:
public string GetMediaTimeLen(string path)
{
  try
   {
      Shell32.Shell shell = new Shell32.ShellClass();
      Shell32.Folder folder = shell.NameSpace(path.Substring(0,path.LastIndexOf("\\")));
      Shell32.FolderItem folderitem =
                                    folder.ParseName(path.Substring(path.LastIndexOf("\\")+ 1));
      if (Environment.OSVersion.Version.Major >= 6)
      {
          return folder.GetDetailsOf(folderitem, 27);
      }
      else
      {
          return folder.GetDetailsOf(folderitem, 21);
      }
   }
  catch (Exception ex)
   {
      return null;
   }
}
把这段代码放到VS 中编译,发现找不到Shell32.Shell 等类,原来还需要手动引入Shell32 这个Com 组件,太麻烦。我想到借助于C# 中的dynamic 新特性可以简化Com 组件调用,就把代码改写成如下:
public static string GetMediaTimeLen(stringpath)
{
  System.Type objType =System.Type.GetTypeFromProgID("Shell.Application");
  dynamic shell = System.Activator.CreateInstance(objType);
  // 文件路径
  dynamic folder = shell.NameSpace(path.Substring(0,path.LastIndexOf("\\")));
  // 文件名称
  dynamic folderitem = folder.ParseName(path.Substring(path.LastIndexOf("\\")+ 1));
  if (Environment.OSVersion.Version.Major >= 6)
   {
      return folder.GetDetailsOf(folderitem, 27);
   }
  else
   {
      return folder.GetDetailsOf(folderitem, 21);
   }
}
接下来的程序就很简单了,遍历文件夹下所有的.wmv 文件,然后把每个文件的时长累加即可:
string[] files =System.IO.Directory.GetFiles(@"F:\ 视频教程\2013 年底asp.net 公开课\ 剪辑后","*.wmv", System.IO.SearchOption.AllDirectories);
TimeSpan tsTotal = TimeSpan.Zero;
foreach (string file in files)
{
  string len = GetMediaTimeLen(file);
  TimeSpan tsLen = TimeSpan.Parse(len);
  tsTotal += tsLen;
}
Console.WriteLine(tsTotal);
程序运行了一会就得到了结果“16:27:35 ”!
ASP.Net 零基础到学生熟悉 ASP.Net 的本质、会使用 ASP.Net 实现增删改查程序、掌握 Cookie/Session 的原理、掌握 AJAX 到最后使用 ASP.Net 开发一个企业网站系统,只用了 16 个小时,这种自豪感瞬间爆棚!