手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 注册 | 登陆
浏览模式: 标准 | 列表Tag:web

WEB异步?

网上闲逛的时候看到两篇文章,有点小意思。一个是mikespook 写的关于Web编程异步模型的白日梦,还有一个是【FarmVille(美版开心农场)谈架构:所有模块都是一个可降级的服务】,都谈到了异步。

贴上上面两篇文章,这样可以做一个比较。

先来:【关于WEB编辑异步模型的白日梦】

在地铁上被前前后后那些特种男女逼到车角,无奈。又想起早上那个白日梦,遂上网搜索了一番。得老赵的佳作一篇《F# 与ASP.NET(1):基于事件的异步模式与异步Action》。之前看过,由于对微软无爱,未能 细品。今日一读,如醍醐灌顶,豁然开朗。

遂整理思路如下,以待后用。

在说异步模型之前,先说说最常见的同步模型吧。例如下面的 PHP 代码:

PHP代码
  1. // 获取数据  
  2. $userInfo = getUserInfo();  
  3. $newsList = getNewsList();  
  4. $topRateNewsList = getNewsList('DESC `rate`');  
  5. // 创建模板,绑定变量  
  6. $tmp = CreateTemplate();  
  7. $tmp->bind('userInfo'$userInfo);  
  8. $tmp->bind('newsList'$newsList);  
  9. $tmp->bind('topRateNewsList'$topRateNewsList);  
  10. // 渲染模板,输出  
  11. $tmp->render();  
  12. echo $tmp;  

在这段代码中,所有调用都是顺序的。也就是说,如果 getUserInfo($userId) 没有返回用户信息的话,getNewsList(5) 永远都不会被调用。实际情况,可能是用户信息是从用户库取数据,新闻是从新闻库取数据。假设新闻库运行良好,而由于某种原因用户库宕机了,那么这次请求也 就废掉了。故障也从一个库的宕机扩散到整个站点。

现在,我白日做梦的创建一种新语言 go-php,引入 go-lang 的关键字 go 到 php 中:

PHP代码
  1. // 创建一个数据通道  
  2. $chan = CreateChan();  
  3. // 获取数据,并放到数据通道上去  
  4. go getUserInfo($chan);  
  5. go getNewsList($chan);  
  6. $params = array('DESC `rate`');  
  7. go getNewsList($chan$params);  
  8. // 创建模板  
  9. $tmp = CreateTemplate();  
  10. // 从通道上取数据  
  11. while($d = $chan->read()) {  
  12.     if ($d['error']) {  
  13.         // 数据有错误 ……处理一下吧  
  14.     } else {  
  15.         $tmp->bind($d['key'], $d['data']);  
  16.     }  
  17. }  
  18. // 渲染模板,输出  
  19. $tmp->render();  
  20. echo $tmp;  

 

好了,这其实不是什么新奇创造,这只是一个二段式异步调用(Begin/End)。这有点像大宗采购,采购商并 不一件一件的商品进行采购,而是拿着清单说:“好了,兄弟,这是我要的货,你们帮我找齐,放到码头406号仓库去……”,然后他就在 406 号仓库等着点货了。这段代码还可以改进,就像采购清单一样,将这个清单推到数据层,数据层把数据返回到数据通道上去。恩,应该不少人在自己的应用中使用 MQ,Memcache 甚至 pipe 实现了这种异步了吧。

再来看另外一段 go-php 代码:

PHP代码
  1. /** 
  2.  * 回调函数 
  3.  * @param $tmp 模板 
  4.  * @param $d 返回的数据 
  5.  */  
  6. function callbackBind($tmp$d) {  
  7.     if ($d['error']) {  
  8.         // 数据有错误 ……处理一下吧  
  9.     } else {  
  10.         $tmp->bind($d['key'], $d['data']);  
  11.     }  
  12. }  
  13. // 创建模板  
  14. $tmp = CreateTemplate();  
  15. // 获取数据,并设置数据回调  
  16. go getUserInfo(callbackBind, $tmp);  
  17. go getNewsList(callbackBind, $tmp);  
  18. $params = array('DESC `rate`');  
  19. go getNewsList(callbackBind, $tmp$params);  
  20. // 如果不是所有数据都回调了,则阻塞  
  21. $tmp->wait();  
  22. // 渲染模板,输出  
  23. $tmp->render();  
  24. echo $tmp;  

这就是老赵的事件回调的异步处理的 go-php 版本。这有点像渠道商订货(或者淘宝上的无货代理?):“我需要XXXX,你帮我送到XXXX去”。然后坐等,所有的内容都送到了,就收钱走人。

对于数据读取的错误,只要处理得当也不是致命的。最多在渲染页面的时候,少某块数据,用户只会奇怪:“这次怎么打开没有新闻那部分的内容了呢……刷 新一下看看……”。而不会说:“烂网站,又打不开了……”用户体验直线上升啊!

好了,梦就做到这里。相信这两种方式其实已经有实际案例了。我比较孤陋寡闻一些,了解的不多。而且有的东西,未经许可也不好多说……大家私下打听 吧。

总之呢,两种异步模型各自有各自的好处。并行的数据存取,提高 I/O 利用率是其本质。王道啊……

-----------------------------------------------------------------------------------------

开始【FarmVille(美版开心农场)谈架构:所有模块都是一个可降级的服务

所有模块都是一个可降级的服务

    For any web application, high latency kills your app and highly variable latency eventually kills your app.

    由于大型的网络应用需要依赖各种底层及内部服务,但是服务调用的高延迟是各种应用的最大问题,在竞争激烈的SNS app领域更是如此。解决此问题的方法是将所有的模块设计成一种可降级的服务,包括Memcache, Database, REST API等。将所有可能会发生大延迟的服务进行隔离。这可以通过控制调用超时时间来控制,另外还可以通过应用中的一些开关来关闭某些某些功能避免服务降级造 成的影响。

    上面这点我也有一些教训,曾碰到过由于依赖的一些模块阻塞造成服务不稳定的现象。

    1. 某Socket Server使用了ThreadPool来处理所有核心业务。

    2. 不少业务需要访问内网的一个远程的User Service(RPC)来获取用户信息。

    3. User Service需要访问数据库。

    4. 数据库有时候会变慢,一些大查询需要10秒以上才能完成。

    结果4造成3很多调用很久才能执行完,3造成2的RPC调用阻塞,2造成1的ThreadPool堵塞,ThreadPool不断有新任务 加入,但是老的任务迟迟不能完成。因此对于最终用户的表现是很多请求没有响应。部分用户认为是网络原因会手工重复提交请求,这样会造成状况并进一步恶化。上 面的问题根本是没有意识到远程服务可能会超时或失败,把远程服务RPC调用当成一个本地调用来执行。

    解决思路一:RPC增加Timeout

    解决思路二:将RPC改成异步调用。

    另一分布式大牛James Hamilton谈 到(2)上面这种做法就是他论文Designing and Deploying Internet-Scale Services中的graceful degradation mode(优雅降级)。

FarmVille其他数据

FarmVille基于LAMP架构,运行在EC2上。读写比例是3:1。使用开源工具来做运维监控,如 nagios报警,munin监控,puppet配置。另外还开发了很多内部的程序来监控Facebook DB, Memcache等。到Facebook接口的流量峰值达到3Gb/s,同时内部的cache还承担了1.5Gb/s。另外可动态调整到Facebook 与Cache之间的流量,Facebook接口变慢时,可以利用cache数据直接返回,终极目的是不管发生了那个环节的故障,能够让用户继续游戏。

小结

    尽管FarmVille公布了上面一些技术资料,凭借上面这些资料无法全部了解FarmVille的架构。但是所有模块都是一个可降级服务 的概念值得设计大规模应用的同行参考。

-------------------OVER-----------------

 

上面两篇都讲到了一个顺序执行所导致的问题,所以才想到是采用异步,瀑布型的网页架构事实上本来就会造成当一小部分没正常取出或堵塞时,影响整个网站的运行,异步是否真的必要?如果真有必要,我们的PHP在没有线程、没有进程等的处理状态下,是否能够完美实现?我这只是记录一点资料,请不要尝试与我讨论。我自己也处于迷惘中

Tags: 异步, web, rpc

郁闷:php console与web的问题

最近在做个小东西,想用PHP跑console,生成一个文件,然后由WEB去调用这个文件。可是却一直失败。

命令行下,用crontab跑,因为WEB是在Safemode下面,但我需要Exec,因此crontab调用php的时候,我就指定了phpini,类似/php -c phpinifilepath phpfilename,于是这样可以了。

但生成出来的文件被WEB调用后。一直显示是失败。郁闷了。。

纯记录,无意义

Tags: php, cli, web

Xenocode Browser Sandbox

Run any browser from the web

看了这个副标题是不是觉得很HIGH呀,试用了一下确实可以。身为一名WEB开发人员,这样的工具实在是居家旅行之必备工具啊。

看看人家的说明,多嚣张啊:

The Xenocode Browser Sandbox allows all popular Windows browsers to be run simultaneously, directly from the web.  Web designers, system administrators, and other users can now evaluate Internet Explorer 8, 7, and 6, Mozilla Firefox, Apple Safari, Opera, and Google Chrome directly from the web in a risk-free manner.  Unlike traditional software applications, Xenocode WebApps do not require any software to be installed and allow multiple application versions to run side-by-side on any version of Windows.

支持这么多的浏览器,你“建国门建国门(请参考小笑话:见过没)”。

再了解一下这家公司:

Understanding Xenocode Technology

Xenocode is a powerful virtualization technology that separates applications from the underlying operating system.  Unlike traditional hardware virtualization solutions that duplicate an entire host operating system, Xenocode's lightweight application virtualization technology emulates only core operating system features required for application execution.  Xenocode requires no setup, configuration, clients, or device drivers, insulates applications against conflicts, and runs existing applications seamlessly on Windows Vista and locked-down desktops.

Xenocode virtual applications can be deployed on the web, intranets, portable storage devices, and existing desktop management infrastructure, including Active Directory, Microsoft SMS, LANDesk Management Suite, and BMC Configuration Management.  Xenocode technology has been licensed by Novell and is available as part of Novell ZENworks Application Virtualization.

The Xenocode Virtual Application Studio authoring environment allows software developers and systems administrators to easily convert existing applications into virtual machine packages.  The Xenocode WebApp service allows Xenocode applications to be run directly from the web via a simple control that embeds directly into web sites, blogs, and other online content.

介绍了这么多,如果不贴网址,恐怕我会被人砍死吧?

来吧。这里就是:http://www.xenocode.com/browsers/

前提,您的机器上需要安装.net framework,相信大多数人应该都会有安装吧。best regards for you....

PS:有朋友说地址失效了,嗯,确实,其实,是他们换域名啦,到这里看看吧:http://spoon.net/browsers/

Tags: web, browser, sandbox, xenocode

wwwsqldesigner:a Visual web-based SQL modelling tool

看到这个的时候很吃惊,最初看到类似功能的时候是在PHPMYADMIN 3上面,想不到现在已经发展到这个地步了,实在让人大吃一“斤”呀。

WWW SQL Designer allows users to create database designs, which can be saved/loaded and exported to SQL scripts. Various databases and languages are supported. Ability to import existing database design.

About

Hi and welcome to WWW SQL Designer! This tool allows you to draw and create database schemas (E-R diagrams) directly in browser, without the need for any external programs (flash). You only need JavaScript enabled. The Designer works perfectly in Mozillas (Firefox, Seamonkey), Internet Explorers (6, 7, 8), Safari and Operas. Konqueror works, but the experience is limited.

Many database features are supported, such as keys, foreign key constraints, comments and indexes. You can either save your design (for further loading & modifications), print it or export as SQL script. It is possible to retrieve (import) schema from existing database.

WWW SQL Designer was created by Ondrej Zara and is built atop the oz.js JavaScript module. It is distributed under GNU GPL license.

网址:http://code.google.com/p/wwwsqldesigner/

我是从:http://parandroid.com/www-sql-designer-open-source-sql-based-web-creation-tools/看来的

它支持很多的数据库功能:

  • 强制外关键字
  • 注解
  • 索引

当数据库图表创建后,你可以:

  • 保存你的数据表设计或稍后修改它们
  • 打印它
  • 作为 SQL脚本导出

它甚至还可以从已存在的数据库中检索出概况图标,支持MySQL, MSSQL, SQLite 和 Web2py。感兴趣的朋友看查看DEMO.

 

 

图片附件:
大小: 18.81 K
尺寸: 430 x 188
浏览: 2420 次
点击打开新窗口浏览全图

Tags: designer, sql, web

语言包?

本文也是转摘,不过看到它的时候,我想起了discuz的URL解析,discuz在做rewrite的时候,并没有主动都对模版中的链接进行更换,而是在输出前,对于符合规则的那些链接使用rewrite的规范进行了一次批量替换。

这次我转摘的文章也是用了类似的方法,只是他又是.NET处理的,我也不翻译了。知道了原理就行了(和discuz一样,不过这种方法应该只适合做语言包)

原文:

一直以来多语言问题都是个让人头疼的问题,不是这个问题有多难,而是很繁琐,而我们目前的这个项目有点特殊,我希望最大限度的化繁为简,以下是我解决这个问题的方案。
我们的项目有这样两个前提:
1、要支持多语言但最多三种语言,一般情况下就两种语言,所以并没有随时切换语言的要求。
2、我们希望有一种可以初期不用管语言问题,之后统一翻译的方案
基于这么两点,我们提出了这样的方案:
1、初期写程序时不用关心多语言的翻译工作,只要将所有使用到中文的地方都用{}扩上
2、在数据库中Chinese会设置为唯一约束
3、所有的翻译工作会在BasePage中的Render方法中作
4、所有的页面会继承BasePage
5、翻译时会根据当前的语言设置构建以language表中Chinese做key,相应的语言为value的字典,然后查找需要翻译的字符串是不是在字典中,如果不在就生成这一行。

 
数据库设计四个字段

ID,Chinese,English,Other

BasePage源码:

C#代码
  1. using System;  
  2. using System.Data;  
  3. using System.Configuration;  
  4. using System.Linq;  
  5. using System.Web;  
  6. using System.Web.Security;  
  7. using System.Web.UI;  
  8. using System.Web.UI.HtmlControls;  
  9. using System.Web.UI.WebControls;  
  10. using System.Web.UI.WebControls.WebParts;  
  11. using System.Xml.Linq;  
  12. using System.Text.RegularExpressions;  
  13. using System.Text;  
  14. using System.Collections;  
  15. using System.Collections.Generic;  
  16. using System.IO;  
  17. using System.Diagnostics;  
  18.   
  19. /// <summary>  
  20. ///BasePage 的摘要说明  
  21. /// </summary>  
  22. public class BasePage : System.Web.UI.Page  
  23. {  
  24.     //利用Dictionary来筛选所有的多语言标签,然后做替换,可以缓存  
  25.     Dictionary<stringstring> dic;  
  26.     public BasePage()  
  27.     {  
  28.   
  29.     }  
  30.     //需要替换的标签,标签头为数字字母下划线汉字  
  31.   
  32.     static readonly Regex re = new Regex  
  33.         (@"((\{)|(\%7B))[\w\-\+\|u4e00-\u9fa5]+?((\})|(\%7D))",  
  34.         RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace);  
  35.   
  36.     //不需要替换的标签  
  37.     static readonly Regex re_nr = new  
  38.         Regex(@"<NOREPLACE>[\w\W]*?</NOREPLACE>", RegexOptions.Multiline | RegexOptions.IgnoreCase);  
  39.   
  40.     private string RenderTag(ref string content)  
  41.     {  
  42.         if (re_nr.IsMatch(content))//不需要替换标签  
  43.         {  
  44.             StringBuilder sb = new StringBuilder();  
  45.   
  46.             MatchCollection grouplist = re_nr.Matches(content);  
  47.             string[] reList = re_nr.Split(content);  
  48.   
  49.             for (int i = 0; i < grouplist.Count; i++)  
  50.             {  
  51.                 sb.Append(ReplaceTag(ref reList[i]));  
  52.                 sb.Append(grouplist[i].Value);  
  53.                 sb.Append(ReplaceTag(ref reList[i + 1]));  
  54.             }  
  55.   
  56.             content = sb.ToString();  
  57.         }  
  58.         else  
  59.         {  
  60.             content = ReplaceTag(ref content);  
  61.         }  
  62.         return content;  
  63.     }  
  64.   
  65.     private string ReplaceTag(ref string content)  
  66.     {  
  67.         //模板标签{yes},{no},{search}  
  68.         MatchCollection mc = re.Matches(content);  
  69.   
  70.         if (dic == null)  
  71.         {  
  72.             dic = LanguageManager.GetResource();  
  73.         }  
  74.   
  75.         for (int i = 0; i < mc.Count; i++)  
  76.         {  
  77.             //如果数据库中还没有此字符串  
  78.             if (!dic.ContainsKey(mc[i].Value.TrimStart('{').TrimEnd('}')))  
  79.             {  
  80.                  content = content.Replace(mc[i].Value, mc[i].Value.TrimStart('{').TrimEnd('}'));  
  81.   
  82.                 if (!dic.ContainsKey(mc[i].Value.TrimStart('{').TrimEnd('}')))  
  83.                 {  
  84.                     LanguageManager.AddLanguageString(mc[i].Value.TrimStart('{').TrimEnd('}'));  
  85.                 }  
  86.             }  
  87.             else if (dic[mc[i].Value.TrimStart('{').TrimEnd('}')] == null)  
  88.             {  
  89.                 content = content.Replace(mc[i].Value, "$$$$");  
  90.             }  
  91.             else  
  92.             {  
  93.   
  94.                 content = content.Replace(mc[i].Value, dic[mc[i].Value.TrimStart('{').TrimEnd('}')].ToString());  
  95.   
  96.   
  97.             }  
  98.         }  
  99.           
  100.         return content;  
  101.     }  
  102.     protected override void Render(HtmlTextWriter writer)  
  103.     {  
  104.   
  105.         Stopwatch stopwatch = new Stopwatch();  
  106.         stopwatch.Reset();  
  107.         stopwatch.Start();  
  108.         try  
  109.         {  
  110.             //会把页面的输出结果存储在这个StringBuilder中  
  111.             StringBuilder sb = new StringBuilder();  
  112.             StringWriter sw = new StringWriter(sb);  
  113.             HtmlTextWriter htw = new HtmlTextWriter(sw);  
  114.             base.Render(htw);  
  115.             string content = sb.ToString();  
  116.   
  117.             content = RenderTag(ref content);  
  118.   
  119.             //重新写入页面  
  120.             writer.Write(content);  
  121.   
  122.         }  
  123.         catch (Exception ex)  
  124.         {  
  125.             Response.Write(ex.ToString());  
  126.             Response.End();  
  127.         }  
  128.         finally  
  129.         {  
  130.             stopwatch.Stop();  
  131.             Response.Write("runtime:" + stopwatch.ElapsedMilliseconds.ToString() + "ms");  
  132.         }  
  133.   
  134.     }  
  135. }  
这样设计的
优点
1、初期写程序时不用关心多语言的翻译工作,只要将所有使用到中文的地方都用{}扩上
2、省去了大量命名相应文字的工作
3、直接用中文标示要显示到页面的文字,容易理解

缺点
1、如果中文是一样的翻译,而其他语言翻译却不一样时不好解决,但这种情况似乎不常见

————————END————————

缺点就是我说的,只能用来做语言包,呵呵。

Tags: web, 语言包, 数据库

Records:14123