Quantcast
Channel: IT社区推荐资讯 - ITIndex.net
Viewing all 15843 articles
Browse latest View live

深度搜索

$
0
0

译者: HorseHour原文地址: streamhacker.com

当我们准备发布 Weotta时,我们已经为如何描述它犯了难。我们处理大数据吗?是的。我们使用了机器学习和自然语言处理吗?是的。可以叫它搜索引擎吗?当然。但是,我们想总和要大于部分。

我们最终觉得“深度搜索”是对我们工作最贴切的描述,它是一个超越了基本文本搜索的复杂搜索系统的简洁描述。无需赘言,不管怎么看,我们都不是这个领域唯一的一家公司;谷歌和很多其他公司都在对深度搜索的各个方面进行研究。但是还没有人创造出一个与我们的产品十分相像的深度搜索系统。我们的搜索技术可以处理各种标准文本搜索引擎无法理解的日常查询。

基本搜索

文本搜索引擎,如 SphinxLucene/Solr,均使用了 分面过滤技术(注1):每篇文档都有一组“字段”(注2),通常表示成一个XML格式的文件,且各个字段都建立索引。给定一个搜索查询词以及可选的侧面选择参数,系统可以从文档集合迅速检索到目标文档和字段(建议读者阅读《 信息检索导论》了解具体的实现细节)。

在文本索引时,通常可以指定建立索引的字段,每个字段都有各自的权重。比如,如果选择给文档标题字段很大的权重,而赋予文档文本字段的权值较小,则标题中含搜索词的文档,要比只在文本字段包含此搜索词的文档得到更高的分值。

为了检索建立索引的文档,你可以使用类似于SQL检索语句的搜索检索字符串。通常,在搜索语句中存在特殊的语法以控制搜索引擎决定检索哪些文档时的行为。比如,你可以明确哪些单词是必须的,哪些单词是可选的,或单词相距多远。

现在,所有这些对于程序员和技术用户都不成问题,但对于一般消费者,它并不理想。他们甚至不想知道是否存在特殊语法,更别提使用了。谢天谢地, 深度搜索检索引擎卓越的检索词解析和自然语言理解能力使特殊语法成为多余。

分面提供了过滤搜索结果的方法。分面搜索可以在字段中寻找一个具体的值,或者更复杂的如确定日期、时间范围或确定与一个给定点的距离。通常,分面不影响文档的分值,但是会减少返回的文档数目。由于分面搜索通常会启动一个搜索/浏览接口的组合,也称“分面导航”。一个基本的搜索系统,若提供分面搜索,一般都是通过复选框、下拉列表或相似控件实现。 eBay就是一个完美的例子,它提供许多分面以深入挖掘和过滤搜索结果。相比而言,深度搜索系统将分面搜索移至后台进行。

这些文本搜索引擎很强大,但在深度搜索的背景下,实际上只是一种别样的数据库。文本搜索与深度搜索均使用索引优化检索过程。文本搜索使用特殊的格式化查询字串与分面说明检索数据,而非使用SQL执行检索。虽说SQL数据库经过优化可以存储基于列或基于行的数据,但是文本搜索引擎经过优化,可以使用 倒排索引(注3)存储普通文本数据。不管哪一种方法,从开发人员的角度来看,均属于底层数据存储方法,都有最适合的使用场景。

高级搜索

虽然高级搜索系统在最底层使用一个文本搜索引擎,但是会集成一些额外的排名信号。一个突出的例子就是谷歌的 PageRank算法,它组合了文本搜索、关键词相关性、网站权威度及许多其它便于对搜索结果排序的信号。基本的文本搜索引擎仅使用单个文档的信息和文档集合的统计信息,高级搜索系统还考虑譬如信用、流行度和链接强度等外部信号。比如 亚马逊允许用户按照平均评分或流行度对结果排序。但是这还算不上深度搜索,因为它只是在控制搜索结果的排序方面更强一些,对数据或检索语句还没有更深的了解。

深度搜索

我相信深度搜索满足如下四个基本要求:

  1. 简单的搜索输入。它意味着深度搜索具有对检索语句的 自然语言理解(NLU)能力,使得系统底层能够明白应该调用哪项侧面选择。
  2. 多类目搜索。如果用户只搜索一样东西,搜索系统相对比较简单。但是如果搜索中包含多个变量,用户也没有给出明确的侧面选择,就需要深度搜索根据NLU技术确定用户在搜索什么,以及如何搜索到它。深度搜索还要能够高效地、自动地将多个数据集融合到一个系统。
  3. 特征工程以实现深度数据理解。与流行观点不同,只有大数据还不够。你拥有海量数据并不定说你就掌握了能够洞察数据的方法。我们可以拿冰山打个很好的比方:用户看到的只是冰山一角,而冰山的大部分却藏在水面下。这里数据是冰山,特征工程则是解决如何让水下冰山现形,展示给用户,使其看到最佳搜索结果。
  4. 情景理解。你对用户了解的越多,则你就掌握了更多调整搜索结果的知识。情景理解就意味着要知道用户的地理位置,他们过去的搜索历史,或者他们显性的偏好信息。情景是王!

当今许多搜索系统不符合这些要求的任何一条。有些只是实现了一条或两条,但是很少同时符合所有要求。 Siri根据设备情景,并使用NLU技术理解检索语句。但是,Siri并非真正地进行搜索,而是将检索请求转发给另外一个应用或搜索引擎执行。谷歌与Weotta均符合所有要求,但是实现、方法及应用范围不同。

如何搭建一个深度搜索系统呢?深度搜索与简单文本搜索相同,都存在两个重要环节:索引和查询。下图是从深度搜索角度对两者的一个概括。

深度索引

深度搜索需要对数据的深度理解:它是什么,它怎么样,它对什么有益以及如何将其转换成机器可以理解的一种格式。这里举几个例子:

  • 位置要有地址和地理方位点信息
  • 产品要有重量和尺寸信息
  • 电影要有演员和导演信息

我们一得到底层数据结构,则立即将其转化为适于文本和侧面索引的文档结构。但是,深度搜索也需要特征工程发挥作用的深层知识和理解。我们必须仔细思考,用户可能执行何种搜索以及他们对搜索结果期望的质量如何。然后,我们还须确定如何将其转化为可索引的文档特征。

关于这种想法,我们这里给出两个例子。

假设有一家卖鸡翅的饭店。那么,鸡翅怎么样?有多少人喜欢有多少人不喜欢?它卖的鸡翅是本城最好吃的吗?诸如此类的问题可以通过一项基于目录的 情感分析技术回答。

一场演唱会可能只是一次性事件,但是乐队以前的演出内容可能不同于今日。人们是否喜欢以前的演出?乐队粉丝呈现什么样的人口分布?演唱会会场如何?要回答这些问题,可能需要组合多个数据集,以建立乐队在不同会场演出间的交叉联系。

深度索引就是回答这类问题,将答案转化成适于排名和(或)过滤搜索结果的过程。这可能会涉及到应用数据科学、线性回归或情感分析。由于问题及其答案有赖于数据特征、用户所需结果类型,目前还没有特定的方法。但是,我们可以使用适当的技术,从而获得对数据前所未有的理解。比如,我们可以使用 潜在情感分析技术,发掘数据隐含特征,从而可以处理基本文本索引不可能处理的检索语句。实现对数据的深入理解,自然水到渠成。引用 佩德罗·多明格斯在《 机器学习那些事(注4)》一文中的原话:

“机器学习初学者常常会惊奇地发现在一个机器学习项目中,真正用于机器学习的时间少得可怜。但是,当你考虑到数据收集、集成、清洗和预处理何等耗时,特征设计要经历一轮一轮不断试错,就会释然了。”

“项目70%的时间用于特征工程,20%的时间则耗费在为算法确定一个合适的、全面的度量标准,而只有10%的时间用在算法选择和调优。”

特征工程的一个主要部分是获取更多数据及质量更好的数据。我们需要大量的多样化的数据集得到必要的上下文信息。Weotta处理的数据,包括用户的地理信息、人口特征、兴趣点(Point Of Interest,POI)信息和位置数据库,以及社交网络。但是,我们还需要深度理解如何集成和关联数据,应用哪种机器学习算法,最重要的是,需要理解哪些问题提及到它以及可以回答哪些问题。所有这些都需要设计出一个可以自动实现的集成系统。谷歌研究主管 彼特·诺维格说:“我们只是拥有更多的数据,还没有设计出更好的算法。”

在Weotta,我们相信高质量数据是最重要的,因此投入大量精力滤除噪声数据以抽取有意义的信号。对于任何重要的特征工程,其大部分工作实际上就是数据清洗。毕竟, 投入的是垃圾,产出的也是垃圾(注5)。

我们还需要一个自动流程以实现连续学习。当数据进来时集成以后,系统应当自动改善。佩德罗·多明格斯说:“机器学习不是一个创建数据集和启动学习器的一次性过程,它是一个不断启动学习器、分析结果、修改数据和(或)学习器的循环过程。”

在此过程,人也是重要的一部分。在几乎每个层面上,我们必须都能够将人的知识和经验融合到数据管道。这种恰到好处的平衡与人机组合,决定了深度搜索系统的真正潜能和适应变化的能力。

深度查询

虽然我们已经获得深度数据驱动的深度索引,还需有效地使用它。简单的文本查询是不够的。为了得到正确的结果,我们需要准确领悟用户的搜索意图。它涉及到查询解析和自然语言理解技术。

在Weotta,我们已经投入大量时间,细化查询解析以处理如“哪一家餐厅适合我的周年纪念日”或“本周末哪有音乐会演出,我约了人”之类的查询语句。其他搜索系统的查询解析能力存在差别:Siri可识别单词 Call加一个名字,而谷歌知识图谱却可以识别维基百科上几乎所有的实体。

如果我们已经解析查询词,并知晓搜索意图,下一步就是检索结果。由于我们实现的是多类目搜索,因此需要查询多个索引。在这一点上,自然语言理解能力尤为可贵,因为我们需要知道每个索引支持的查询参数类型,从而系统可以对查询词进行智能切分。

但是,当我们检索不同类型的信息时,那么如何将其组织到一个结果集合?怎么对不同类的事物进行排名呢?这些都是接口设计和用户体验方面的重要问题。谷歌使用结果页面的不同区块显示不同类型的结果,如谷歌地图和 知识图谱

我们认为Weotta使用的卡片展示有很大意义。我们在移动端使用一个栈,在电脑端则使用五张以上排成一排的卡片显示结果。为何这样做呢?这种表示方法从视觉效果上来看,可以让用户每次重点浏览少数几条结果,并允许我们显示多类目结果。这样,人们可以搜索晚餐饮品与电影,而看到三类不同的搜索结果,所有结果均混到一起。

还记得前面提到的侧面选择吗?在深度搜索中,虽然侧面选择对用户隐藏不可见,但是它们对于查询引擎仍然重要。根据检索词,查询解析器使用自然语言理解技术,而非依赖显式复选框决定使用哪个侧面选择。这种决定也可以由数据和产品的性质来驱动。在Weotta中,当我们知道一个检索语句涉及到食物时,我们使用一个侧面选择将结果限定于餐馆方面的条目。谷歌却不同,虽然他们或许知道一个检索语句中包含食品方面的单词,由于他们的数据是如此的丰富庞大,他们不能或者不愿为显示何种类型搜索结果做出清晰的决策,所以人们常常看到混在一起的搜索结果。比如,我试着用谷歌搜索“寿司”,除了一个网页列表,我还看到一个本地餐厅的长列表、一张地图和一个知识图谱方盒。由于Weotta专注于本地搜索并且理解用户,我们知道你正在寻找“寿司店”,这就是我们为你提供的服务。使用Weotta的深度搜索,用户可以搜索更为具体的对象,搜到“可以吃到滨地寿司的餐厅”相关结果。

深度查询语句理解的另外一个关键因素是“情景”:谁在搜索?他们在哪?现在什么时间?天气怎样?他们过去搜索了什么?他们的亲人朋友是谁?他们给出的显性偏好是什么?他们的隐形偏好是什么?

这些问题的答案会对搜索结果产生重大影响。如果我们知道一个人在纽约,那么我们就不会将其他地方的信息或发生在其他地方的事显示给他/她。如果外边正在下雨,我们会显示室内活动或周边地方相关结果。如果我们知道一个人讨厌垃圾食品,就不会显示麦当劳的结果给他/她。

所谓“爱屋及乌”,朋友喜欢什么你可能也会跟着喜欢。它可能不是一个强信号,但是几乎每个人都看重“ 社会认同”。此外,人们常与朋友和家人一起做事,如果将他们的偏好都考虑进来,我们也许能够找到更多的相关结果。事实上,如果你使用脸谱账号注册Weotta,就可以搜索到你的朋友喜欢的地方或事件。

总结

深度搜索系统从如下几个方面超越基本的文本搜索和高级搜索:

  1. 没有显性的侧面选择
  2. 多类目搜索
  3. 深度特征工程
  4. 情景

为了实现这些要求,我们需要利用自然语言理解、机器学习和大数据技术。实现时需要做的工作,比想象的要多得多,但好处也不言而喻:你可以通过一个简单的接口进行自然语言查询,并可搜索到更相关更加个性化的搜索结果。


备注

  1. 分面过滤(Faceted Filtering),又称分面搜索(Faceted Search)。所谓分面(Facet)实际上就是事物的多维属性,如一部电影的导演、演员、类型等分面。分面搜索通过事物的多维属性对不断筛选、过滤搜索结果的一种搜索方法,可视为搜索和浏览的结合。
  2. 字段(Field)方便文档(如网页等)的存储和索引,比如在全文检索引擎Lucene中,将文档划分成标题、正文、摘要等字段,并且可以设置各个字段的存储、索引状态,还可以设置每个字段的权重,称作Boost,以方便文档评分与排名。
  3. 倒排索引(Inverted Index)是搜索引擎最重要的一个模块。搜索引擎使用分词工具将文档切分成多个词的集合(又称“词袋”),词(中文的“词语”或“单字”,英文的“单词”)是文档的基本表示单元,由文档到词袋的映射就是建立正排索引(Forward Index)的过程。我们还可以根据所有文档中的词,建立从词到文档的映射关系,这就是倒排索引。在用户提交检索语句后,经过分词处理后,由词定位所有出现该词的文档,并使用相关的排名算法对文档进行排名。
  4. 《机器学习那些事》( A Few Useful Things to Know about Machine Learning)中文译名借鉴刘知远的 翻译版本,感谢译者的贡献。但是,本文对佩德罗·多明格斯在《机器学习那些事》中的表述文字是本文译者的独立工作。
  5. 投入的是垃圾,产出的也是垃圾(garbage in, garbage out),常译作“垃圾进垃圾出”是一个常见的计算机术语,模仿“先进先出”(FIFO)的翻译。本文译者直接使用本意,方便多数读者理解。

@车品觉:大数据如何落地

$
0
0

@车品觉:大数据如何落地

大数据的应用既不便宜,也存在一定的缺陷,更未能充分提升商业的价值,反而大数据其实更需要企业家、产品经理等管理精英们的创造性思维,用数据的力量做出确切的关联和相互参照,使大数据能真确地产生物有所值的商业效应。

自从舍恩伯格的《大数据时代》畅销以来,“大数据”赢得了难以想象的关注度。但同时,从实务的角度来看又有一点难以落地的感觉。这其中的原因,在于很多公司仍然没有建立起数据的收集到应用的基础设施包括工具和人才配置,尤其是在实战层面上未对大数据有较为客观和理智的认知,吹捧它的人认为它无所不能,在各种场合反复讲解一些高大上的案例,而质疑它的人则认定现有结构化数据就能说明关键问题,从而对其不以为意。事实上,大数据的应用既不便宜,也存在一定的缺陷,更未能充分提升商业的价值,反而大数据其实更需要企业家、产品经理等管理精英们的创造性思维,用数据的力量做出确切的关联和相互参照,使大数据能真确地产生物有所值的商业效应。

不要迷信大数据

几乎每个礼拜,我都要面试很多数据科学家,以及不少从业者。例如,在招聘时,我问应聘者的第一个问题一般都是“在你心里什么是大数据”。回答显示,原来业内的认知分歧丝毫不比外行少——至少有一半受访者或应聘者对“大数据”这个概念根本就不以为然,而是更关注有价值的数据、数据能产生什么价值。换言之,在部分人看来,“大数据”本身就是一个伪概念。我问的第二个问题是,目前为止,你做得最好的大数据案例是什么?他们的回答都有个共同点,就是用大数据来处理数据的稀缺性。比如,北京的空气质量监测站是有限的,其数据对于监测站附近范围的质量呈现是比较准确的,但其余地区的质量数据是非常稀缺的。换言之,大数据能帮我们增加未知部分的准确度、精确度。

有很多人讨论大数据与小数据的关系。其实,这个问题衍生自大数据如何落地。应该说,大数据可以说明商业运营者找到大致的方向,但真正落地到商业操作,反而不如小数据更有用、更有效。比如,很多运营者宣称自己的注册用户是多少量级的,但是 1 亿个注册用户的基础数据,不如一千万个活跃用户完整的行为数据更具有价值。对于初创企业进行客户探索、发现和验证时,几百个甚至几十个顾客、用户的完整数据比你得到千万级数据更有价值。也许正是因为数据量虽大,但每个数据单元都出现了断裂或遗漏,导致大数据的价值难以被挖掘出来。

因此,应用大数据的能力之一就是把数据变小的本领。在构建数据模型时,你需要的样本其实不是千万,甚至不是面面俱到的数据,而是比较敏感的数据指标。这对数据收集和分析人员是巨大的挑战。实际上,大数据的应用和落地,也要以数据的细分为基础。例如某电商顾客的真实性别就不一定与购物的性别偏向一致;再比如,关键词搜索量,看北京、南京各多少,而不是笼统地说增长了多少。当我们用放大镜细查大数据时,会发现有不少的“断链”和数据欠完整。从某种意义上说,大数据没有真正的全面数据,差别只在于你放大镜的倍数。即使基于大数据进行决策,也仍然有猜测和赌博的成分在其中。所以,我反而主张,大数据和小数据应该可以互为作用, 而非比较两者谁更强。

目前,大数据应用里有个怪现象,就是有什么数据就收集什么数据,至于将来有什么用,一概不知,或者抱着“先收集再说,将来总有用”。我的建议是,从问题、愿景导向来收集数据。一方面,数据的收集、存储备份等成本都不低,另一方面,数据的价值也可能衰减。

其次,在我看来,以用户为核心的 KPI 能实现与客户的行为点对点连通,是未来发展的大趋势。传统的用户价值是以利润贡献为核心指标来衡量的,而在大数据时代,客户关系的管理可能就不一样了。例如,我要知道一个客户一个月内到淘宝多少次,不管他是否购买,要看他与我们公司的关系到底怎么样。同学举行婚礼,礼金重才是好哥们?显然不是这样的。一个礼拜,用户花在视频网站、微博等等的时间是多少。未来竞争的是用户的注意力。在大数据的创新下我们是否可以更容易得知你得到了多少的用户注意力呢。

公司要建立起数据收集系统,更重要的是要建立起跟踪数据质量的监控,而且一些关键数据要寻找多个源头,一方面确保“鸡蛋不在一个篮子”,另一方面要相互比对、印证。对于实际运营的企业来说,数据必须有连贯性,而且要确保数据的真实性,因为如果数据的收集或获取本身就错了,那么后边的分析和决策无疑就建立在沙滩之上,“根基不牢,地动山摇”。

就现状而言,大数据技术更多地用于推荐和营销,不是因为它更容易,而是因为它容错的空间更大。比如,推荐系统给出了顾客不喜欢的推荐,大不了重新推荐,但一旦上升到直接解决问题层面,其容错空间就大大缩小了。例如,利用大数据技术来观测空气质量,错了也不会有大的影响,然而如果把这个指数和某个商业运营挂钩,就不是小事了。更何况如果数据是用在一部无人驾驶的汽车上,不准确地运用数据的后果更是不堪设想。人们很喜欢谈论沃尔玛“啤酒与尿布”的故事,但是其相关性只发生在周五下班后,而且一年后这个关联不再出现了,因此,需要数据部门的不断跟踪,不能一条经验法则走到黑。尤其是对数据的精确性要求较高时,数据的持续跟踪与多源比对就显得非常重要。也正是这个原因,导致大数据的应用还停留在比较肤浅的层次或者压根就飘在空中。

作为创新的赛马场

有人认定大数据具有前景,于是试图利用先前收集的数据开创新的事业或业务,但目前为止我还没有看到特别成功的例子。相对而言,在拥有大数据的公司之内应用大数据比没有大数据的公司可能要容易一些。其优势是,他们对数据比较熟悉,知道其中的数据定义和数据搜集中的难点和局限性,从而比外部合作者用得要好。当然创新是否容易被旧有文化所限制, 又另作别论。阿里金融的成功,是在游离母体与靠近母体间找到了一个动态的平衡,克服了外来数据所带来的困扰。例如,产品设计改版使得数据变化了,但数据生产方却未必有告知的义务。因此,数据使用者要监控数据源是否稳定。这也与数据公司的既有文化和业务范畴有关,一家善于构筑堡垒的公司即使有无可比拟的数据资源,很可能宁愿等着数据价值的衰减,也不愿意将其有效利用。

其次,应用大数据开创新业务的能力问题,许多业务运营者可能搜集了大量的数据,但能否挖掘出“原业务”以外的创新性业务,到目前为止仍然是一个巨大的挑战。商业创新有时候表现为不可思议的关联,但总体而言,由于这种突破性的关联带来创新业务的概率是非常小的。

传统企业怎么办

到目前为止,我们在谈论大数据的时候,在根本上忽略了一点,很多企业本身是有其架构的,不会因为大数据就立即变得不一样了。很多公司连信息(information)都未打通,是堵塞、零散的,更不要说大数据的应用了。大数据作为一种新的运营理念和方法体系,要想嵌入到公司里,必然要经历一个新事物在旧公司的所有困难。比如,想要的数据无法采集,很多公司口口声声说“以客户为中心”,但关于客户的数据要回流到公司核心决策里却不容易,其统计口径与企业 KPI 不一致。这些虽然与今天我们所说的大数据没有关系,是数据化,却是大数据的基础。如果在一家公司里,想要看的数据没搜集,或流动不顺畅,却被大数据所迷惑,那是本末倒置。

但这不是说,传统企业可以对大数据应用置若罔闻。对当下的企业来说,要反躬自问,有没有一些数据,今天不搜集,将来会后悔?如果这些数据被对手搜集到,会怎么样?要做到这一点,就要对公司一年后、两年后或半年内的方向非常清楚,或者至少有个概念。实际上,我们的互联网上充斥很多与企业相关的信息或数据,但未得到足够的重视,这主要是观念问题,而不是能力问题。

今天人们所说的信息技术(IT),其实越来越趋向于数据化,商业智能要把销售数据、营销数据和消费者数据打通,而不是各自孤立。传统企业高管应该重视数据的关联应用,至少不能只满足于财务报告的数据,不要容忍人力资源部连主动离职率与服务水平都关联不起来洞察。要有步骤地构建起数据的搜集系统,培训对数据高度敏感的人员。当然,从一种有效的策略来说,先把既有的数据用好,比盲目推进大数据要明智得多。你要重新定义你的数据框架来解决存在的问题。比如,很多企业都开启了公司微博,其测定效果是转发多少、评论多少。但实际上,你要细分你的数据,进一步厘清谁、什么样的转发和评论才是有价值的,还要和相似的公司微博进行对比。

传统企业究竟是建立起自己的独立的搜集系统,还是使用别人提供的数据?我认为要兼有,既要有侧重地独自搜集,也要多源化地获取数据,尽力排除各种数据在搜集过程中形成的偏差,这既是一个技术问题,需要数据人员付出艰辛的努力,也是一个战略问题,需要回到前文所述的小数据问题。

本文来源: 阿里商业评论作者:车品觉,《决战大数据》作者、阿里巴巴集团副总裁、数据委员会会长。

Facebook 员工去一趟非洲 然后他们的Android app 就变快了

$
0
0

Facebook 一位名为 Alex Sourov 的工程师最近跟我们分享了一段真人真事。他们一队包括了几位产品经理和工程师的队伍早前去了非洲考察(没有注明哪些 / 哪个非洲国家),不过考察的目标并不是名胜,而是自家的 Android 版 Facebook app。想了解为什么的话,请继续阅读吧。

他们指出 Facebook 的目标并不只是那些用到高阶手机和高速网络的人,而是将 Facebook 带给所有人,把“余下的 50 亿人”连线。所以,他们买了几部不同的 Android 手机来做一个 Facebook app 大测试,至于这些手机是在哪里买,型号是什么我们并不清楚,只知道它们缺乏内置储存空间,理应是一些非洲人常用的低端手机吧。

他们发现在非洲打开 Android 版 Facebook app 时,因为硬件限制,再加上网络带宽狭窄,所以资料载入得很慢,app 也常常停止运作。结果,他们用了 Facebook app 40 分钟就烧光他们当月的所有数据了!这个经验使得他们大悟,所以在返回基地之后,他们决定要将 Android 版 Facebook app 的运作表现改善。

为此他们做了几个改进,例如他们发现单核装置的 Facebook 开动时间很长,是因为太多东西会在启动那刻载入了,所以他们将某些东西的载入次序延后,某些东西甚至会在要用时才开始载入。另外,他们决定将图片格式转为 Google 的 WebP,相对 JPEG,下载 WebP 时所用的数据少了 25%-30%,而相对 PNG 则为 80%。图片策略二,就是针对着装置萤幕的解像度而下载相同解像度版本的图片,而不是将全解像度的原图下载,当要放大图片时才会下载高解像度的版本。

最后,相对年初的版本,Facebook 现在已经将他们 Android app 的档案大小减去 65% 之多,他们指出这个版本的更新其实已经推出,即使大家不在非洲也应下载来试试吧。

来源: Engadget中国

 


© 推荐 for 互联网的那点事. | 猛击下载: iPhone客户端猛击下载: Android客户端

前端架构那些事儿

$
0
0

  在谈前端架构之前,需要先探讨一下不同人群对前端产生的困惑。前端这个职业最近几年才逐渐被认可,之前一直是低端的代名词,所以多数高手很不屑搞这个。之前的很多项目,人们对前端这块的要求也只是能用就行,所以很少会在上面去细致、深入地建立一套完善体系。而多数产品的技术经理也会是后端出身的,往往对前端的认识还停留在Java Struts那个原始的MVC模型上,或者首先想到的就是GWT和JSF,这是从后端角度出发的一种视角。用这类思维方式做出来的产品,一般用户体验都不会很好。

  另一方面,从界面层上手的人群,他对用户体验这方面会把控得比较好,但通常缺架构意识,或者说是软件工程的意识。在界面层比较复杂的情况下,很可能会有失控的趋势。对整个系统结构的认知程度通常不够深入,也缺乏设计模式等方面的知识。

  开发人员会有一些困惑:

  • 创建项目的时候,一般没有人作前端的技术选型

  • 拿到项目之后,没有直接可复制的基础版本

  习惯于引用第三方组件

  • 赶功能,需要某个组件或者特效
  • 上网搜到一个合适的,加进来
  • 它还依赖一些别的库
  • 文件大还是次要的
  • 可能会产生冲突,样式也不一致

  开发经理也会有一些困惑:

  • 协作过程感觉有问题

  • 前端人员写原始界面,包含静态界面和特效
  • 开发人员接着改,加逻辑
  • 发现有问题要返工了
  • 在谁的代码基础上继续改?如何合并?

  2014年了,为什么还有这么多人工环节?

  • 能自动单元测试吗?
  • 能自动发布打包吗?

  用户会对这些事情感到烦恼:

  长得丑

  • 界面老土
  • 风格不一致

  速度慢

  • 加载慢
  • 渲染慢
  • 执行慢

  出错

  架构的本质是什么?其实也是一种管理。通常我们所说的管理,都是指对于任务和人员的管理,而架构管的是机器和代码。比如说,机器的部署属于运维的物理架构,SOA属于服务架构,那么,前端的架构指什么呢?

  长期以来,前端所处的位置是比较偏应用层,而且是很薄的一层,而架构又要求深度和广度,所以之前在前端里面做架构,好比在小水塘里游泳,稍微扑腾两下就到处碰壁。但最近这几年来,前端的范围被大大拓展了,所以这一层逐渐变得大有可为。

  怎样去理解架构呢?在早期的文字MUD游戏里,有这么一句话:“你感觉哪里不对,但是又说不上来。”在我们开发和使用软件系统的过程中,或多或少会遇到这样的感觉,有这种感觉就说明架构方面可能有些问题。

  在狭义的前端领域,架构要处理的很重要的事情是组件的集成。由于JavaScript本身缺乏命名空间这样的机制,多数框架都倾向于自己搞一套,所以这方面的碎片化是很严重的。如果一个公司的实力不足以自研所有用到的组件,就会一直面临这方面的问题。

  比如说,在做某个功能的过程中,发现需要一个组件,时间来不及做,就到网上搜了个,加到代码里面,先运行起来再说。一不小心,等功能做完的时候,已经引入了无数种组件了,有很多代码是重叠的,可能有的还有冲突,外观也不一致。

  环顾四周的大型互联网公司,基本上都有自己的前端框架,比如阿里的Kissy和Arale,腾讯的JX,百度的Tangram,360的QWrap等,为什么?因为要整合别的框架,并且在此基础上发展适合自己的组件库,代价非常大,初期没办法的时候只能凑合,长期来说,所有代码都可控的意义非常重要。

  那么,是不是一套框架可以包打天下呢,这个真的很难。对于不同的产品形态,如果想要用一套框架去适应,有的会偏轻,有的又偏重,有的要兼容低端浏览器,有的又不要,很难取舍。

  常见的前端产品形态包括:

  • 内容型Web站点 侧重渲染方面的优化,前端逻辑比重小
  • 操作型B/S系统 以数据和逻辑为中心,界面较规整
  • 内嵌Web的本地应用 要处理缓存和一些本地接口,包括PC客户端和移动端

  另外有Web游戏,因为跟我们的企业形态关系不大,而且也比较独特,所以不包含在内。这三种产品的前端框架要处理的事情显然是不太一样的,所以可以细分成2-3种项目模板,整理出对应的种子项目,供同类产品初始化用。

  最近我们经常在前端领域听说两个词:全端、全栈。

  全端的意思是,原来的只做在浏览器中运行的Web程序不够,还要做各种终端,包括iOS,Android等本地应用,甚至PC桌面应用。

  为什么广义的前端应当包含本地应用呢?因为现在的本地应用,基于很多考虑,都变成了混合应用,也就是说,开发这个应用的技术,既包含原生的代码,也包含了嵌入的HTML5代码。这么一来,就造成了开发本地应用的人技能要求较广,能够根据产品的场景,合理选择每个功能应当使用的技术。

  现在有一些PC端的混合应用开发技术,比如node-webkit和hex,前者的典型应用是Intel® XDK,后者的典型应用是有道词典,此外,豌豆荚的PC客户端也是采用类似技术的,也有一些产品是用的qt-webkit。这类技术可以方便做跨平台,极大减少开发工作量。

  所以,我们可以看到,在很多公司,开发安卓、iOS应用的人员跟Web前端的处于同一个团队中,这很大程度上就是考虑到这种情况。

  全栈的意思是,除了只做在浏览器中运行的代码,还写一些服务端的代码,这个需求又是从哪里来的呢?

  这个需求其实来自优化。我们要优化一个系统的前端部分,有这么一些事情可以做:

  • HTML结构的优化,减少DOM树的层次等等
  • CSS渲染性能的优化,批量写入DOM变更之类
  • 资源文件的优化,比如小图片的合并,图像格式的处理,图标字体的使用等
  • JavaScript逻辑的优化,模块化,异步加载,性能优化
  • 加载字节量的优化,主要是分摊的策略
  • HTTP请求的优化

  这里面,除了前三条,其他都可能跟后端有些关系,尤其是最后一条。但是前端的人没法去优化后端的东西,这是不同的协作环节,所以就很麻烦。

  那么,如果有了全栈,这个问题可以怎么解决呢?

  比如说,我们要做最原始的小文件合并,可以在服务器做一些配置,把多个合并成一个请求,比如天猫的某个url:

   http://g.tbcdn.cn/kissy/k/1.4.1/??dom/base-min.js,event-min.js,event/dom/base-min.js,event/base-min.js,event/dom/touch-min.js,event/dom/shake-min.js,event/dom/focusin-min.js,event/custom-min.js,cookie-min.js?t=1.js

  这个就很明显是多个文件合并而成的,9个小文件的请求,合并成了一个64k的文件请求。

  这种简单的事情可以在静态代理服务器上配置出来,更复杂的就比较难了,需要一定的服务端逻辑。比如说,我们有多个ajax请求,请求不同的服务,每个请求的数据量都非常少,但因为请求数很多,可能会影响加载性能,如果能把它们在服务端就合并成一个就好了。但这个优化是前端发起的,传统模式下,他的职责范围有限,优化不到服务端去,而这多个服务很可能是跨产品模块的,想要合并,放在哪个后端团队都很怪异。

  这可真难办,就像老虎追猴子,猴子上了树,老虎只能在下面干瞪眼。但是如果我们能让老虎上树,这就不是个问题了。如果有这么一层NodeJS,这一层完全由前端程序员控制,他就可以在这个地方做这种合并,非常的合理。

  除此之外,我们常常会用到HTML模板,但使用它的最佳位置是随着产品的场景而不同的,可能某个地方在前端更好,可能某个地方在后端好些。到底放在哪合适,只有前端开发人员才会知道,如果前端开发人员不能参与一部分后端代码的开发,优化工作也还是做不彻底。有NodeJS之后会怎样呢,因为不管前端模板还是后端模板,都是JavaScript的,可以使用同一套库,这样在做调整的时候不会有代码迁移的烦恼,直接把模板换地方即可。

  现在,也有很多业务场景有实时通信的需求,目前来说最合适的方案是Socket.io,它默认使用NodeJS来当服务端,这也是NodeJS的一个重要使用场景。

  这样,前端开发人员也部分参与了运行在服务端的代码,他的工作范围从原先客户端浏览器,向后拓展了一个薄层,所以就有了全栈的称呼。至于说这个称呼还继续扩展,一个前端开发人员从视觉到交互到静态HTML到JavaScript包办的情况,这个就有些过头了。

  以上这些,主要解决的都是代码层面的事情。另外有一个方面,也是需要关注,但却常常不能引起重视的,那就是前端的工程化问题。

  早期为什么没有这些问题?因为那时候前端很简单,复杂度不高,现在整个很复杂了,就带来了很多管理问题。比如说整个系统的前端都组件化了之后,HTML会拆分成各种模板,JavaScript会拆分成各种模块,而CSS也通过LESS或者SASS这种方式,变成了一种编译式的语言。

  这时候,我们考虑一个所谓的组件,它就比较麻烦了。它可能是一个或者多个HTML模板,加上一个或者多个JavaScript模块,再包含CSS中的一部分构成的,而前两者都可能有依赖项,三个部分也都要避免与其他组件的冲突。

  这些东西都需要管理,并且提供一种比较好的方案去维护。在JavaScript被模块化之后,也可以通过单元测试来控制它们的质量,并且把这个过程自动化,每次版本有变更之前,保证它们最基本的正确性。最终,需要有一种自动化的发布机制,把这几类代码提取,打包合并,压缩,发布。

  这个主题展开可以讲很多,所以我们不在本次分享中涉及。在我之前的几篇文章中,也阐述过观点。

  目前这方面研究最深入的是之前百度FIS团队的张云龙,他的几篇文章在 这里,强烈推荐阅读。

   后记:

  这篇文章是我入职苏宁之后第一次公开分享,目标受众主要是后端出身的技术经理,目的是让这个群体能有更多的前端意识。现在公司的项目基本都有前端模块,但人员专职程度较低,水平也参差不齐。苏宁的战略口号之一是提升用户体验,从产品角度看,用户体验的提升并非是UI做几个图,搞一些花哨效果就可以了,它是一个系统工程,涉及从用户习惯调研、产品设计、前端开发、甚至后端服务等一系列环节,需要从易用度、观感、加载性能、流畅度等各方面共同提升。

  这些东西都需要从全局角度作规划,从源头控制起,否则只能是头疼医头,脚痛医脚。为此,基础技术中心会逐步整合几套适合不同场景的基础前端框架,作为种子项目供今后的技术选型使用。此外,还会从前端开发的各种主题组织一些技术分享,并且逐步形成一套制度化,流程化的培训体系。

4000块入苹果本本不是梦,官翻 MacBook Air 4288元起

$
0
0

macbook air

Apple 官方在线商店今天新上架了两款翻新的 MacBook Air,最低配的版本只要4288元,搭配11.6吋屏幕、1.7GHz 双核心 i5 处理器,4GB 内存和 64 GB 闪存。稍高配一点的售价4788元,也是11.6吋屏幕和1.7GHz 双核处理器,只是闪存升级到了128GB。

虽然说最低配的64GB 闪存确实对于长期依赖 Mac 的不太够用,但考虑到比 Mac mini 还便宜的价格,学生党用来学习 iOS 开发应该是非常好的选择。这应该是 MacBook 系列官翻产品的最低价,果迷们不要错过。

苹果官方翻新产品都经过苹果严格的质量检测,在质量、性能、售后服务方面都和全新产品的标准完全一样,唯一的风险就是外观可能有轻微使用痕迹或划痕。事实上根据小编了解的情况这种情况基本没有出现过也大概不会出现。此外,苹果的官方翻新产品基本都更换了全新的屏幕和电池。如果你想更加详细的了解苹果的翻新产品,请 点击这里

访问: Apple 官方在线商店(翻新 Mac 专区)

图片优化的那些工具

$
0
0

图片作为页面的一个主要因素,它的大小直接影响了页面的加载速度,这一点在移动端尤显突出。

怎么让图片的大小更小?除了选择合适的格式(jpeg、gif、png),我们还可以利用网上的应用(如smushit、tinypng、imagemin、imageOptim)对图片进行压缩。在这里我想给大家介绍一下上述应用主要使用到了哪些命令行工具以及它们的使用方法。

imageoptim

Jpegtran

JPEG的压缩工具有jpegtran和jpegoptim,这两款工具的压缩效果几乎没有区别,在这里我们推荐使用jpegtran,相比后者,jpegtran可以进行progressive编码,使图片渐进式的展现,先显示模糊的图片,再逐步清晰。

推荐命令行参数:

jpegtran –copy none –optimize -progressive -outfile out.jpg in.jpg

想知道这些参数的具体作用,可使用命令“jpegtran –h”了解,下同。

 

Gifsicle

Gif动画可使用gifsicle来优化,它会剥离不同帧中重复的像素来优化gif动画,对于单帧gif我们推荐还是使用png8来替代。

推荐命令行参数:

gifsicle –interlace -O3 –careful –no-comments –no-names –same-delay –same-loopcount –no-warnings -o out.gif in.gif

 

pngcrush、optipng、pngout

PNG压缩可分为无损压缩和有损压缩,以上三款可以说是现在比较主流的无损压缩工具了。从ImageOptim的压缩效果可以看出,optipng和pngcrush对于色彩比较单一、大小比较小的图片压缩效果好于pngout,而对于色彩比较丰富、透明渐变的图片来说pngout的压缩比明显更高。另外,经测试,Google的PageSpeed上提供的可压缩比是按照optipng给出的。

imageoptim_1

imageoptim_2

推荐命令行参数:

pngcrush -brute -rem alla -nofilecheck -bail -blacken -reduce -cc in.png out.png

optipng -strip all -quiet -clobber -o3 -i0 in.png -out out.png

pngout -k1 -r -v in.png out.png

 

pngquant、pngnq

两款PNG的有损压缩工具,基本都能将图片压缩掉40%以上,它们会将PNG转换成alpha透明的PNG8,由于PNG8最多支持256色,所以内容丰富的图片压缩后会看出些许差异,但属于可接受范围内,而纯色图片基本能保持原图的质量。另外,这种alpha透明的PNG8图片在IE6以上及其他标准浏览器可以显示正常的alpha透明度,在IE6中则会忽略掉有alpha透明度的颜色,作为全透明处理(边缘稍有锯齿但影响不大),而不像png32那样alpha透明区域在IE6下显示灰色。

推荐命令行参数:

pngnq –s 1 –d outdir/ in.png

pngquant -s1 –o out.png in.png

PS:pngquant的-s是speed参数,可选值1-10,默认为3,在经过多图测试后发现1的压缩比和效果都是最佳的,其他的参数或多或少存在缺陷,这里推荐选1。

 

总结

如果您已经学会如何使用这些命令行软件对自己的图片进行压缩优化,那么恭喜您,您的图片瘦身成功。如果您觉得命令行一行一行的压缩图片太麻烦,那么除了去使用文章开头所说到的那几款应用外,感兴趣的同学也可以整合它们去开发一套自己的应用,利用php的exec、nodejs的child_process.exec(cmd, [options], callback)等等方法执行shell命令,再配上一些交互,一款好用的图片优化应用就此诞生。最后希望这篇文章对大家有所帮助。

成为“快速工作达人”的7个信条

$
0
0

译者: 诣斐君原文地址: shuchi.php.co.jp

        自己也知道这是必须要做的工作,然而,就是不想动手去做。结果,工作不断堆积起来,今天的一天就这样结束了……一定有很多公司职员有着这样的烦恼吧。

       对此,《THE21》杂志在2014年1月期中制作了特刊,以“快速着手工作的人与拖延工作的人何处不同”为题,采访了五位快速工作达人。

照片从左往右为(敬称省略):

山本真司(经营顾问/立命馆大学经营研究生院客座教授)
戸塚隆将(シーネクストバートナーズCnext paterners)股份公司代表
吉田穂波(医生 医学博士)
川邊健太郎(雅虎股份有限公司副总监)
出口治明(life net生命保险有限公司 董事长)

        他们五位分别从商人、公司经营者、经营顾问、母亲等角度讲述了如何提高工作速度的方法,这些方法中也存在着不少共同要素。

        接下来,是我们精心总结出的“快速完成工作,告别拖延”的7大信条。



最大限度活用碎片时间
有以下情况的人要注意
· 以1小时为单位粗略制定计划表

· 在路上总是发呆

· 空闲时间频频刷网上的新闻

       会议和会议之间间隔的10分钟,去见客户路上的15分钟……像这样的时间,我们都觉得什么也做不了,不知不觉就发着呆度过了。这样的情况很多,但是,吉田穂波指出,恰恰这种时间,才宝贵的像金山。比如,写上计划书的名字,日期这种事情,利用这点间隙时间完成是绰绰有余的。这样一来,还能有这样一种效果“这项工作不是从零开始的,减少了阻碍,心情也变得轻松了。”类似的,山本真司也提倡“以15分钟为一个时间单位”,利用手机等移动工具,调整环境,利用缝隙时间也能完成工作。

        在你每天的工作中,难道没有利用“缝隙时间”就能完成的工作吗?我建议你重新考虑一遍。



把提早下班制度化
有以下情况的人要注意

· 一味加班而经常感到疲惫困倦的人

· 每天,不特意决定下班时间而开始工作的人

· 总是在意周围人的眼光,在公司留到最后的

        lifenet生命保险董事长出口治明指出,日本人大量加班是“日本国力下降”的大问题。事实上,受采访的五位几乎都指出了,张弛无度的长时间工作会削弱集中力这一点。

       因此,山本真司这样说“把定时下班回家制度化,这样的方法会十分有效。不过,也要需要注意,员工们因为不得不遵守规定而产生压力这样的副作用。”另一方面,没有信心管理自己的人,吉田穂波建议“快到结束时间不要工作”这也很有效。另外,从领导的立场出发,也有必要像出门所说的那样采取“禁止加班”的措施。不论怎样,重要的是,在工作之前要在建立“今天几点做完工作”这样的目标而非“工作做完之后再回家”的想法。



把握判断基轴,制定优先顺序

有以下情况的人要注意

· 到公司上班之后开始看邮件,回过神来已经下午了

· “那件事也必须要做!”立即陷入了恐慌状态

· 明明有想做的事情,但是游手好闲就这样过完一天

        每天都被眼前的工作追赶着,却不知道到底做什么好然后陷入慌张……这类人大多数是“没有判断事物轻重缓急的基准”的。比如,雅虎副总监川邊健太郎就指出,“只有制定好行动方针,下定决心后工作速度才能提高。”迷惑时有可以返回的地点,才能做出快速的判断。

       另外,戸塚隆将也用“优先度”和“完成所需时间”的矩形图来判断工作,制定优先顺序。这样一来,有限顺序就因人而异了。不过,还是有必要再次思考“我是怎样确定工作的优先顺序”这一行动指南针,然后不断重复着对自己说,不断写下来,让它成为自己的一部分,以提高自己的判断力水准。



动机管理

♢有以下情况的人要注意

· 经常加班,睡眠时间总是不规则

· 到公司之后到开启状态要花好几个小时

· 昨天明明很有干劲,今天完全没有进取之心

        意外的,“干劲”是个十分重要的问题。我们正是因为觉得累了,厌烦了,所以才容易拖延工作。因此,首先我们管理好自己的身体状况。戸塚隆将说,在高盛公司时的自己的上司不管多忙都会在规定的时间回去,戸塚氏自自己也是,无论多忙都会注意保证一定的睡眠时间。

        另一方面,身体上虽然没有问题,但是也存在怎么也打不起精神,拿不出干劲的情况。这种时候,吉田 穂波推荐这样做,“回忆一下自己在什么样的时候会有做事的情绪。”不同的人,会有“被别人表扬的时候”“进行着积极的话题的时候”不一样的回答。不过正是因为他们知道这点,才能管理自己的动机情绪。而且,最早提出“工作是很快乐的事”的就是川邊健太郎。确实,如果忘了这一点,再勉强自己也提不起干劲。



逼迫自己制定停下来的时间

♢有一下情况的人要注意

· 星期六也一定会有某方面的工作。剩余的休息日只是睡觉

· 只是处理眼前的工作,不知不觉就太阳落山了

· 因为珍惜时间,讨厌和别人闲谈

        所谓“快速工作法”很容易让人理解为“珍惜1分1秒,都用来工作”,但是令人想不到的是,更多的人指出,重要的是“逼迫自己制定停下来的时间”。

       例如,山本真司会把每周的几个小时固定为“什么也不做,只是思考的时间”,据说戸塚隆将也会在休息日里设定这样的时间。

       雅虎的川邊健太郎也是,不管多忙也不会忘记重视花在自己兴趣上的时间。而且,据说正是在这种“强迫自己发呆的时间”里,自己能产生许多好想法。

        并且,就像出口治明所指出的那样,在那些时间里进行自我提高,自我完善的活动的话,长期坚持就能使自己的工作能力上升。


早早安排工作

♢有以下情况定的人要注意

· to do list?(要做的事列表)那是菜鸟才做的事

· 总是不到截止日期提不起干劲

· 不知为何总是担心下周的工作而无法集中眼前的工作

       工作列表什么的,总容易让人觉得是新人才做的事情。不过戸塚隆将指出,世界的精英里也有写工作列表的人,在回家前写好明天该做的事务列表的人也有很多。

       确实,预先在前一天安排好工作的话,第二天就能很快着手开始工作。

        在此之上,山本真司建议,对于大项目,可以提早一个月“安排计划,细分工作”。这样,一点点推进细分了的工作,心理上也会有轻松的效果。

        需做事情列表和工作计划能让你“脑中的工作备忘录增加”。脑袋思路清晰才能提高注意力,提升工作速度。牢牢记住这句话吧。



不要全部都一人承担

♢有以下情况的人要注意

· “自己的工作自己做完”是我的自尊心。

· 摆脱别人会给对方添麻烦

· 上司不能总比员工办事不利

       总是说“我好忙我好忙”的人,其实都是自己承担着不必要的工作而非常感动痛苦。说起来,有责任感,口碑好;有时可能会给周围人添麻烦,这也是一个问题,特别是如果某些立场上来说,受影响的范围就更加大了。

       吉田穂波氏说,当自己舍弃“把抚养孩子摆脱给别人是多么荒唐的事”这样错误的自尊的瞬间,所有的一切都理顺了。另外,出口治明也说道“当时新人的时候,就向上司彻底的询问工作的优先顺序比较好。”确实,这样对自己对上司都减少了浪费的时间。

        另一方面,山本真司从领导的角度,倡导“讲出来”。也就是说,公司的老人和领导不要虚张声势,坦诚的说出“我也不清楚。”这样就能逃出承担不必要事物的恶习。无谓的自尊是百害无一利。

angularjs与服务器交互

$
0
0

真正的应用需要和真实的服务器进行交互,移动应用和新兴的Chrome桌面应用可能是个例外,但是对于此外的所有应用来说,无论你是想把数据持久化到云端,还是需要与其他用户进行实时交互,都需要让应用与服务器进行交互。

为了实现这一点,Angular提供了一个叫做$http的服务。它提供了一个可扩展的抽象方法列表,使得与服务器的交互更加容易。它支持HTTP、JSONP和CORS方式。它还包含了安全性支持,避免JSON格式的脆弱性和XSRF。它让你可以轻松地转换请求和响应数据,甚至还实现了简单的缓存。

例如,我们打算让购物站点从服务器上获取商品信息,而不是从内存假数据获取。如何编写服务端代码已经超越了本书的范畴,所以,我们仅仅来想象一下,比方说我们已经创建了一个服务器,当查询/products 路径时,它会以JSON格式返回一个商品列表。

返回的响应示例如下:
[
  {
    "id": 0,
    "title": "Paint pots",
    "description": "Pots full of paint",
    "price": 3.95
  },
  {
    "id": 1,
    "title": "Polka dots",
    "description": "Dots with that polka groove",
    "price": 12.95
  },
  {
    "id": 2,
    "title": "Pebbles",
    "description": "Just little rocks, really",
    "price": 6.95
  }
  ...etc...
]

我们可以像下面这样编写查询代码:
function ShoppingController($scope, $http) {
  $http.get('/products').success(function(data, status, headers, config) {
    $scope.items = data;
  });
}

然后在模板中这样使用它:
<body ng-controller="ShoppingController">
    <h1>Shop!</h1>
    <table>
      <tr ng-repeat="item in items">
        <td>{{item.title}}</td>
        <td>{{item.description}}</td>
        <td>{{item.price | currency}}</td>
      </tr>
    </table>
  </div>
</body>

正如我们前面讲过的,从长远来看,让服务来代理与服务器交互的工作对我们有好处,这个服务可以被多个控制器共享。

来自《AngularJS开发下一代Web应用》一书 

在线版在 https://github.com/edagarli/AngularJSWeb

作者:www19940501a 发表于2014-6-23 23:24:43 原文链接
阅读:126 评论:0 查看评论

[转][转]Golang适合高并发场景的原因分析

$
0
0


来源: http://blog.csdn.net/ghj1976/article/details/27996095

作者: 蝈蝈俊



典型的两个现实案例:

我们先看两个用Go做消息推送的案例实际处理能力。


360消息推送的数据:

16台机器,标配:24个硬件线程,64GB内存 
Linux Kernel 2.6.32 x86_64 
单机80万并发连接,load 0.2~0.4,CPU 总使用率 7%~10%,内存占用20GB (res) 
目前接入的产品约1280万在线用户 
2分钟一次GC,停顿2秒 (1.0.3 的 GC 不给力,直接升级到 tip,再次吃螃蟹) 
15亿个心跳包/天,占大多数。

 

京东云消息推送系统

(团队人数:4) 
单机并发tcp连接数峰值118w 
内存占用23G(Res) 
Load 0.7左右 
心跳包 4k/s 
gc时间2-3.x s


C10K问题

为什么可以支撑这么高并发的请求呢?我们先从C10K问题说起:2001年左右的时候,有一个叫Dan Kegel的人在网上提出:现在的硬件应该能够让一台机器支持10000个并发的client。然后他讨论了用不同的方式实现大规模并发服务的技术。

http://www.kegel.com/c10k.html (英文版)

http://www.oschina.net/translate/c10k (中文翻译版) 
http://www.cnblogs.com/fll/archive/2008/05/17/1201540.html

当然, 现在C10K 已经不是问题了, 任何一个普通的程序员, 都能利用手边的语言和库, 轻松地写出 C10K 的服务器. 这既得益于软件的进步, 也得益于硬件性能的提高,现在应该扩展讨论的是应该是C10M问题了。

参考资料:

千万级并发实现的秘密:内核不是解决方案,而是问题所在! 
http://www.csdn.net/article/2013-05-16/2815317-The-Secret-to-10M-Concurrent-Connections


Coroutine模型 和 非阻塞/异步IO(callback)

不论线程还是进程,都不可能一个连接创建一个,相应的成本太大,多进程和多线程都有资源耗费比较大的问题,所以在高并发量的服务器端使用并不多。解决方案是一个线程或者进程处理多个连接,更具体的现在比较主流的是:Coroutine模型 和 非阻塞/异步IO(callback),在分析这两个之前,我们先看看多进程和多线程的情况。


多进程

这种模型在linux下面的服务程序广泛采用,比如大名鼎鼎的apache。

下图说明了Apache的生命周期(prefork模式)。主进程负责监听和管理连接,而具体的业务处理都会交给子进程来处理。

1234514831_ddvip_588

这种架构的最大的好处是隔离性,子进程万一crash并不会影响到父进程。缺点就是对系统的负担过重,想像一下如果有上万的连接,会需要多少进程来处理。所以这种模型比较合适那种不需要太多并发量的服务器程序。另外,进程间的通讯效率也是一个瓶颈之一,大部分会采用share memory等技术来减低通讯开销。

apache的处理能力,下面有几篇文章:

2008年时的数据: http://www.blogjava.net/daniel-tu/archive/2008/12/29/248883.html

http://wenku.baidu.com/view/c527582a453610661ed9f40f.html


Apache的问题

Apache的问题在于服务器的性能会随着连接数的增多而变差 
关键点:性能和可扩展性并不是一回事。当人们谈论规模时,他们往往是在谈论性能,但是规模和性能是不同的,比如Apache。 
持续几秒的短期连接,比如快速事务,如果每秒处理1000个事务,只有约1000个并发连接到服务器。 
事务延长到10秒,要维持每秒1000个事务,必须打开1万个并发连接。这种情况下:尽管你不顾DoS攻击,Apache也会性能陡降;同时大量的下载操作也会使Apache崩溃。 
如果每秒处理的连接从5千增加到1万,你会怎么做?比方说,你升级硬件并且提高处理器速度到原来的2倍。发生了什么?你得到两倍的性能,但你没有得到两倍的处理规模。每秒处理的连接可能只达到了6000。你继续提高速度,情况也没有改善。甚至16倍的性能时,仍然不能处理1万个并发连接。所以说性能和可扩展性是不一样的。 
问题在于Apache会创建一个CGI进程,然后关闭,这个步骤并没有扩展。 
为什么呢?内核使用的O(N^2)算法使服务器无法处理1万个并发连接。 
内核中的两个基本问题: 
连接数=线程数/进程数。当一个数据包进来,内核会遍历其所有进程以决定由哪个进程来处理这个数据包。 
连接数=选择数/轮询次数(单线程)。同样的可扩展性问题,每个包都要走一遭列表上所有的socket。 
解决方法:改进内核使其在常数时间内查找。 
使线程切换时间与线程数量无关。 
使用一个新的可扩展epoll()/IOCompletionPort常数时间去做socket查询。

参考: http://www.csdn.net/article/2013-05-16/2815317-The-Secret-to-10M-Concurrent-Connections

 


多线程


这种模型在windows下面比较常见。它使用一个线程来处理一个client。他的好处是编程简单,最重要的是你会有一个清晰连续顺序的work flow。简单意味着不容易出错。

这种模型的问题就是太多的线程会减低软件的运行效率。

 

线程和进程的成本

普通的线程,需要消耗1M的堆栈 
http://www.cnblogs.com/PurpleTide/archive/2010/11/12/1875763.html

多进程和多线程的优缺点...  
http://blog.163.com/ymguan@yeah/blog/static/140072872201147832740/

我们知道,操作系统的最小调度单元是“线程”,要执行任何一段代码,都必须落实到“线程”上。可惜线程太重,资源占用太高,频繁创建销毁会带来比较严重的性能问题,于是又诞生出线程池之类的常见使用模式。也是类似的原因,“阻塞”一个线程往往不是一个好主意,因为线程虽然暂停了,但是它所占用的资源还在。线程的暂停和继续对于调度器都会带来压力,而且线程越多,调度时的开销便越大,这其中的平衡很难把握。

针对这个问题,有两类架构解决它:基于callback和coroutine的架构。

 

Callback- 非阻塞/异步IO


这种架构的特点是使用非阻塞的IO,这样服务器就可以持续运转,而不需要等待,可以使用很少的线程,即使只有一个也可以。需要定期的任务可以采取定时器来触发。把这种架构发挥到极致的就是node.js,一个用javascript来写服务器端程序的框架。在node.js中,所有的io都是non-block的,可以设置回调。

举个例子来说明一下。 
传统的写法:

 var file = open(‘my.txt’);
 var data = file.read(); //block
 sleep(1);
 print(data); //block

node.js的写法:

 fs.open(‘my.txt’,function(err,data){
    setTimeout(1000,function(){
       console.log(data);
    }
 }); //non-block

这种架构的好处是performance会比较好,缺点是编程复杂,把以前连续的流程切成了很多片段。另外也不能充分发挥多核的能力。

 

Coroutine-协程

coroutine本质上是一种轻量级的thread,它的开销会比使用thread少很多。多个coroutine可以按照次序在一个thread里面执行,一个coroutine如果处于block状态,可以交出执行权,让其他的coroutine继续执行。

非阻塞I/O模型协程(Coroutines)使得开发者可以采用阻塞式的开发风格,却能够实现非阻塞I/O的效果隐式事件调度,

简单来说:协程十分 轻量,可以在一个进程中执行有数以十万计的协程,依旧保持高性能。

进程、线程、协程的关系和区别:

  • 进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。
  • 线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。
  • 协程和线程一样共享堆,不共享栈,协程由程序员在协程的代码里显示调度。

堆和栈的区别请参看: http://www.cnblogs.com/ghj1976/p/3623037.html

协程和线程的区别是:协程避免了无意义的调度,由此可以提高性能,但也因此,程序员必须自己承担调度的责任。

执行协程只需要极少的栈内存(大概是4~5KB),默认情况下,线程栈的大小为1MB。

goroutine就是一段代码,一个函数入口,以及在堆上为其分配的一个堆栈。所以它非常廉价,我们可以很轻松的创建上万个goroutine,但它们并不是被操作系统所调度执行。

Google go语言对coroutine使用了语言级别的支持,使用关键字go来启动一个coroutine(从这个关键字可以看出Go语言对coroutine的重视),结合chan(类似于message queue的概念)来实现coroutine的通讯,实现了Go的理念 ”Do not communicate by sharing memory; instead, share memory by communicating.”。

 


http://my.oschina.net/Obahua/blog/144549

goroutine 的一个主要特性就是它们的消耗;创建它们的初始内存成本很低廉(与需要 1 至 8MB 内存的传统 POSIX 线程形成鲜明对比)以及根据需要动态增长和缩减占用的资源。这使得 goroutine 会从 4096 字节的初始栈内存占用开始按需增长或缩减内存占用,而无需担心资源的耗尽。

为了实现这个目标,链接器(5l、6l 和 8l)会在每个函数前插入一个序文,这个序文会在函数被调用之前检查判断当前的资源是否满足调用该函数的需求(备注 1)。如果不满足,则调用 runtime.morestack 来分配新的栈页面(备注 2),从函数的调用者那里拷贝函数的参数,然后将控制权返回给调用者。此时,已经可以安全地调用该函数了。当函数执行完毕,事情并没有就此结束,函数的返回参数又被拷贝至调用者的栈结构中,然后释放无用的栈空间。

通过这个过程,有效地实现了栈内存的无限使用。假设你并不是不断地在两个栈之间往返,通俗地讲叫栈分割,则代价是十分低廉的。

 

简单来说:Go语言通过系统的线程来多路派遣这些函数的执行,使得每个用go关键字执行的函数可以运行成为一个单位协程。当一个协程阻塞的时候,调度器就会自动把其他协程安排到另外的线程中去执行,从而实现了程序无等待并行化运行。而且调度的开销非常小,一颗CPU调度的规模不下于每秒百万次,这使得我们能够创建大量的goroutine,从而可以很轻松地编写高并发程序,达到我们想要的目的。

 

Coroutine模型 和 非阻塞/异步IO(callback)性能对比

从性能角度来说,callback的典型node.js和golang的性能测试结果,两者差不多,参考下面测试数据:

http://www.cnblogs.com/QLeelulu/archive/2012/08/12/2635261.html

不过从代码可读性角度来说,callback确实有点不太好。

 

 

 

参考资料: 
风格之争:Coroutine模型 vs 非阻塞/异步IO(callback) 
http://blog.csdn.net/kjfcpua/article/details/15809703

Goroutine(协程)为何能处理大并发?
  http://www.cnblogs.com/ghj1976/p/3642513.html
python Eventlet http://www.360doc.com/content/14/0522/00/8504707_379786818.shtml
为什么我认为goroutine和channel是把别的平台上类库的功能内置在语言里
  http://blog.zhaojie.me/2013/04/why-channel-and-goroutine-in-golang-are-buildin-libraries-for-other-platforms.html
Go-简洁的并发
  http://www.yankay.com/go-clear-concurreny/
GOROUTINE性能测试
  http://www.kankanews.com/ICkengine/archives/115285.shtml
Golang特性介绍
  http://mryufeng.iteye.com/blog/576968/
并发编程
  http://book.2cto.com/201301/14436.html


作者:heiyeshuwu 发表于2014-6-23 19:41:47 原文链接
阅读:50 评论:0 查看评论

[翻译]谈谈当今移动端设计者必备素质

$
0
0

mobile1

移动端一直以来都有自己的一套规则制约。同时,这也是一个高速发展的平台,随着新技术和功能的推陈出新。我们不能再像我们做海报和网页那样设计移动端。那么如今的移动设计者需要怎样的技能和思维模式呢?

挑战和约束

每个载体都有其局限性。即使是移动平台—设计者梦想中最理想的画板之一,都有其必须被遵循的特点。

设备的多元化

如今有不计其数的智能手机和平板电脑,每一种有不同的屏幕大小,像素密度,和物理输入(更不用说屏幕旋转)。这意味着我们不能只考虑iPhone 5 屏幕大小然后设计适配它。在移动网页端,响应式设计让我们不必大费周折地设计匹配,就能使设计适应不同屏幕。本地移动设计缺少流动性,因此我们需要考虑设 计对于不同屏幕大小的适配,并记录不同变化对布局的影响。

操作系统多元化

如今,我们有3个主流的移动端操作系 统,Android,IOS和Windows OS。每种操作系统都有其独有的接口标准,外部输入和设计规范,更别说系统版本之间的升级和变更。其中Android系统更加复杂,不同的安卓设备会受到 设备制造商的限制,比如不同终端商的UI设计是不同的,硬件架构和处理能力也不尽相同。(更不用说运营商提供的后续升级)

虽说系统多元化的到来不至于使设计工作迥然相异,但是确实会影响到用户对操作系统在用户体验上的期望值。举例说吧,大多数用户对于安卓系统体验习惯于TouchWiz(三星用户界面)或Sense(HTC界面) 。

性能

应用程序设计的方式可以影响系统耗电量。换句话说,我们的设计可以使我们的用户电量消耗殆尽。某些不必要的视觉效果或动画需要大量的图形运算处理;一个大量 Javascript Web页面会比较耗电。我们新买的设备可能运行APP非常流畅,2年后的老设备就会相应迟缓。这些例子只是来说明,移动设计师需要更了解他们的设计对于系统资源占用以及APP性能的影响。

mobile3

开发成本的考量

很酷的新APP并不意味着它很容易实现。我们设计APP的方式可以直接导致我们的应用能否按时发布。如果我们不清楚地理解我们的设计决策的开发成本,那基本上是在给开发人员徒增负担,并为以后的摩擦埋下隐患。

新技能的学习

我们中的许多人作为设计师在某领域已接受专业的培训,但在数字设计领域才刚起步。我们从比较客观的从以往的经验来看一下(有人直接从火狐导出HTML 吧?),并且这种有争议的方法依然在学校传授。随着移动端的发展其中的差异性越来越大,带来了我们当前的语言,几乎所有的工具和方法的不足,所以是时候改变我们的心态了。

移动平台并非白板

HTML也不是画布。你不能像你设计海报一样随意布局。我想用Photoshop也不能帮助我们改变,因为我们一直用它来设计海报和插图和润饰照片二十多年。我们仍然“画”我们的接口,而屏幕尺寸多样化和移动的动态交互特性都要求我们用一种不同的方法设计。

mobile

最佳界面思考并开始思考交互

我们开始认识到界面式的呈现并不会影响到移动端的设计。感谢Facebook和Yahoo天气为我们展示了不同的设计方式,让我们明白设计应该更专注于交互而不是静态展示。
交互,一次惊艳的视觉体验,正成为移动用户体验核心。他们不仅让接口本身变得生动友好,他们本身也是一个接口元素。交互能够建立APP与用户沟通的桥梁并表达动作,空间,转变以及一系列通信方式。这让纯静态的展示相形见拙。

把设计师的身份放下

你不需要独一无二或原创,尤其是只是为了“独特性”而重新设计一个已知接口的时候。往往坚持原本UI元素和模式是让应用程序按时完成是最明智之举。比起从头开始设计你的UI组件,专注于建立一个简单、有效的界面和创建品牌更有价值。

寻找灵感,现有的APP会比设计类网站更好

许多设计师喜欢去Behance或Dribbble上为他们的下一个移动项目寻找灵感。当然你会找到绝佳艺术的网站,但如果你不是一个经验丰富的移动设计师,这些模型可能会误导人。很多人只是创建模板但从未实现,而且他们会误导你相信每次都能为用户定制的UI。
真正的灵感来自于成功的应用。你会发现设计让产品稳步增长。他们的接口交互已经被现实世界检测过,而且你确认这些可以被复制。

学习新技能

对于平台的学习

就像你作为一个不错的网页设计师需要了解HTML / CSS是一样,你需要了解移动应用程序的底层结构,和他们是完全不同的网页。例如,他们并非像HTML / CSS一样呈现流内容,这会改变我们考虑布局的方式。你将没有神奇的CSS继承(至少不能像那样开箱即用)从页面中分离标记。甚至连标记的概念都没。

你需要阅读一些开发人员来的阅读手册,了解移动应用程序架构,编译和发布。理解一个移动设备是如何工作的以及哪些比较消耗电池。甚至你可能需要学习一些代码基础,作为长期回报:学习开发语言后,你的设计工作会更具效率和可行性。

mobile4

学习移动端的各种元件

这里有一个清单:位置服务(Wi-Fi和GPS),蓝牙,蓝牙低功耗,灯,前后摄像头、麦克风、陀螺仪、加速度计、振动器、指纹扫描仪,眼球跟踪、语音识别,人脸识别,压力检测,这样的技术不胜枚举。每一个新技术都为全新APP的实现打开了大门。而你的职责是成为一个走在科技尖端的设计者。

学习你能用原生的组件做到什么

原生的UI组件实际上给了很多自由定制的空间,但是你需要知道如何使用它们。如果你能做到让你的UI在原生组件上做出的一点调整,开发人员会感谢你为他们节省大量的开发时间。

了解移动端的工作流

了解移动端SDK,集成并运行。了解移动框架,如RubyMotion Xamarin或Titanium。熟悉IDEs,以及图片资源位于一个移动项目位置,他们应该如何命名等。

了解移动端的用户界面模式

三大移动平台上有相似之处而差异在于对移动交互设计诠释。他们的用户期望从它们展示不同的东西。作为一个移动设计师,你应该完全意识到这些差异,能够检测到它们。
不要只关注一个移动平台。尝试所有三个,或者每天至少使用Android和iOS坚持6个月。我做到了,太棒了—你对每个平台的深刻理解将避免你盲目使用它们。而且多尝试切换的好处是:成为一个平台专注的粉丝并不利于移动设计者。

对UI解释说明的文档

因为界面并不能直观呈现所有业务,你需要文档说明不同的状态状态,交互,和动画以及如何应用对数据和环境。注释你的原型,提供动画实例,并为策划设备旋转。

在项目设计阶段学习UX

现代设计师应该是一个战略设计师。所以你的目标,并非仅仅创造美感,是投入到设计团队了解了产品的一切。优先快速原型为了得到早期的预见的用户想要什么。细节的艺术创作工作放到后面去做。确保所有设计与核心价值满足用户的需求。

在项目实现阶段持续关注UX

你不能光顾着给开发人员原型而忘记用户体验,因为大多数的图形需求将出现在开发阶段。新的交互和状态变化,需要新的图形资源。你需要实时响应,所以把你的椅子放在开发人员旁边并准备随时进入设计工作。

Mobile Web的一些小贴士

对响应设计负责

对于移动Web,响应设计并非一刀切的万能方案。在某些情况下能行得通,有时则不可取。你的责任是知道哪些情况移动端可用专用解决方案,哪些情况维护一个独立的代码库去做一些响应调整。即使你是“传统”的网络设计,也得优雅地计划你的页面布局,让它适应不同的屏幕尺寸。并去考量资源的大小:华丽的全屏1M背景图片会让你的用户在使用移动蜂窝数据访问时浪费金钱。

谨慎使用CSS和JS

诚然,CSS 动画、 渐变、 转换和阴影卓越而且非常易于实现。并且视觉效果很赞,还有一帮很酷的技术人员在开发,对吧?但这些元素在移动端都会对电量造成负面影响。使用越逼真生动的实现,我们的设备就会越不流畅而且越耗电。

CSS3 选择器可以控制在低端的设备上的性能影响。尽可能使用ID和 Classes,并保持你的元素选择器低版本。 如果你用#submit替代.main .container .form > div .submit,那也是个好办法。

选择合适的工具

  • Sketch(移动开发的工具箱)。可以说是继承了 Adobe Fireworks,目前在移动端表现抢眼。
  • LiveViewSketch Mirror是能够在虚拟设备上映射你产品的工具。要知道很多东西再实际设备上效果会不一样,你能够运用它们轻松测试尺寸,交互和控制
  • Origami (by Facebook)Quartz Composer都是移动端的快速原型工具,能够让你在无需代码的情况下快速建立一个UI原型,并且为你带来一些逻辑思考和编程使用的大致了解。
  • PaintCode能够直接将UI和矢量图形直接导出成Objective-C的神器.
  • 基于Web的原型软件。有很多:  Balsamiq Mockups, Axure, UXPin, Moqups, Proto.io
  • Flinto能够创建交互原型,并把他们实际安装到你的iPhone中,模拟真实应用。(利用 Safari 的添加到主屏幕功能)。
  • ImageOptim能够为你无损压缩 PNG,JPG 文件。
  • 版本控制软件,最好是 Git or Mercurial. 即时提交你的资源和改动到远程存储库,会比邮件一个Zip去给开发人员好的多。

所有这一切即将过时

不完全肯定,但移动技术发展的步伐令人难以置信的快速。很快我们将面临将可穿戴设备、智能设备和传感器和我们的移动应用互联的挑战。每天都有新的挑战和创新出来。所以,如果可以,保持求知欲,灵活思维,好奇心将会让作为设计师的你不会被时代所淘汰。

本文由人人都是产品经理 小核桃 翻译,转载请注明并保存本文链接

原文:http://uxmag.com/articles/what-does-it-take-to-be-a-mobile-designer-today


(关注更多人人都是产品经理观点,参与微信互动(微信搜索“人人都是产品经理”或“woshipm”)

PostgreSQL数据库完美备份恢复

$
0
0
PostgreSQL自带一个客户端pgAdmin,里面有个备份,恢复选项,也能对数据库进行备份 恢复(还原),但最近发现数据库慢慢庞大的时候,经常出错,备份的文件过程中出错的几率那是相当大,手动调节灰常有限。所以一直寻找完美的备份恢复方案。



梦里寻他千百度,伊人却在灯火阑珊处...其实PostgreSQL内置不少的工具,寻找的备份恢复方案就在其中:pg_dump,psql。这两个指令在数据库的安装目录下,比如我自己本地安装的,路径形如:C:\Program Files\PostgreSQL\9.0\;然后进入到bin文件夹,会看到不少的exe文件,这就是PostgreSQL内置的工具了。里面会找到pg_dump.exe,psql.exe两个文件。我们怎么用他们?



用法:

备份数据库,指令如下:
pg_dump -h 164.82.233.54 -U postgres databasename > C:\databasename.bak

开始-运行-cmd 弹出dos控制台;然后 在控制台里,进入PostgreSQL安装目录bin下:

cd C:\Program Files\PostgreSQL\9.0\bin

最后执行备份指令:
pg_dump -h 164.82.233.54 -U postgres databasename > C:\databasename.bak

指令解释:如上命令,pg_dump 是备份数据库指令,164.82.233.54是数据库的ip地址(必须保证数据库允许外部访问的权限哦~),当然本地的数据库ip写 localhost;postgres 是数据库的用户名;databasename 是数据库名。> 意思是导出到C:\databasename.bak文件里,如果没有写路径,单单写databasename.bak文件名,那么备份文件会保存在C:\Program Files\PostgreSQL\9.0\bin 文件夹里。



恢复数据库,指令如下:
psql -h localhost -U postgres -d databasename <  C:\databasename.bak

指令解释:如上命令,psql是恢复数据库命令,localhost是要恢复到哪个数据库的地址,当然你可以写上ip地址,也就是说能远程恢复(必须保证数据库允许外部访问的权限哦~);postgres 就是要恢复到哪个数据库的用户;databasename 是要恢复到哪个数据库。<  的意思是把C:\databasename.bak文件导入到指定的数据库里。

以上所有的是针对windows而言的,如果在linux下,会不会有效?





在linux里依然有效。有一个值得注意的是:如果直接进入PostgreSQL的安装目录bin下,执行命令,可能会出现 找不到pg_dump,psql的现象,我们在可以这样:

备份:
/opt/PostgreSQL/9.0/bin/pg_dump -h 164.82.233.54 -U postgres databasename > databasename.bak

恢复:
/opt/PostgreSQL/9.0/bin/psql -h localhost -U postgres -d databasename < databasename.bak

好了就写这么多了。
转自:http://www.2goo.info/blog/panjj/other/2011/05/02/516

已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



如何解决TIME_WAIT过多的解决办法(附Socket中的TIME_WAIT状态详解)

$
0
0

linux和windows下TIME_WAIT过多的解决办法

如果使用了nginx代理,那么系统TIME_WAIT的数量会变得比较多,这是由于nginx代理使用了短链接的方式和后端交互的原因,使得nginx和后端的ESTABLISHED变得很少而TIME_WAIT很多。这不但发生在安装nginx的代理服务器上,而且也会使后端的app服务器上有大量的TIME_WAIT。查阅TIME_WAIT资料,发现这个状态很多也没什么大问题,但可能因为它占用了系统过多的端口,导致后续的请求无法获取端口而造成障碍。

虽然TIME_WAIT会造成一些问题,但是要完全枪毙掉它也是不正当的,虽然看起来这么做没什么错。具体可看这篇文档:

http://hi.baidu.com/tim_bi/blog/item/35b005d784ca91d5a044df1d.html

所以目前看来最好的办法是让每个TIME_WAIT早点过期。

在linux上可以这么配置:

#让TIME_WAIT状态可以重用,这样即使TIME_WAIT占满了所有端口,也不会拒绝新的请求造成障碍
echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
#让TIME_WAIT尽快回收,我也不知是多久,观察大概是一秒钟
echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle

很多文档都会建议两个参数都配置上,但是我发现只用修改tcp_tw_recycle就可以解决问题的了,TIME_WAIT重用TCP协议本身就是不建议打开的。

不能重用端口可能会造成系统的某些服务无法启动,比如要重启一个系统监控的软件,它用了40000端口,而这个端口在软件重启过程中刚好被使用了,就可能会重启失败的。linux默认考虑到了这个问题,有这么个设定:

#查看系统本地可用端口极限值
cat /proc/sys/net/ipv4/ip_local_port_range

用这条命令会返回两个数字,默认是:32768 61000,说明这台机器本地能向外连接61000-32768=28232个连接,注意是本地向外连接,不是这台机器的所有连接,不会影响这台机器的80端口的对外连接数。但这个数字会影响到代理服务器(nginx)对app服务器的最大连接数,因为nginx对app是用的异步传输,所以这个环节的连接速度很快,所以堆积的连接就很少。假如nginx对app服务器之间的带宽出了问题或是app服务器有问题,那么可能使连接堆积起来,这时可以通过设定nginx的代理超时时间,来使连接尽快释放掉,一般来说极少能用到28232个连接。

因为有软件使用了40000端口监听,常常出错的话,可以通过设定ip_local_port_range的最小值来解决:

echo "40001 61000" > /proc/sys/net/ipv4/ip_local_port_range

但是这么做很显然把系统可用端口数减少了,这时可以把ip_local_port_range的最大值往上调,但是好习惯是使用不超过32768的端口来侦听服务,另外也不必要去修改ip_local_port_range数值成1024 65535之类的,意义不大。

因为使用了nginx代理,在windows下也会造成大量TIME_WAIT,当然windows也可以调整:

在注册表(regedit)的HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters上添加一个DWORD类型的值TcpTimedWaitDelay,值就是秒数,即可。

windows默认是重用TIME_WAIT,我现在还不知道怎么改成不重用的,本地端口也没查到是什么值,但这些都关系不大,都可以按系统默认运作。

------------------------------------------------------------------------------------------------------------------------
TIME_WAIT状态

根据TCP协议,主动发起关闭的一方,会进入TIME_WAIT状态,持续2*MSL(Max Segment Lifetime),缺省为240秒,在这个post中简洁的介绍了为什么需要这个状态。

值得一说的是,对于基于TCP的HTTP协议,关闭TCP连接的是Server端,这样,Server端会进入TIME_WAIT状态,可想而知,对于访问量大的Web Server,会存在大量的TIME_WAIT状态,假如server一秒钟接收1000个请求,那么就会积压240*1000=240,000个TIME_WAIT的记录,维护这些状态给Server带来负担。当然现代操作系统都会用快速的查找算法来管理这些TIME_WAIT,所以对于新的TCP连接请求,判断是否hit中一个TIME_WAIT不会太费时间,但是有这么多状态要维护总是不好。

HTTP协议1.1版规定default行为是Keep-Alive,也就是会重用TCP连接传输多个request/response,一个主要原因就是发现了这个问题。还有一个方法减缓TIME_WAIT压力就是把系统的2*MSL时间减少,因为240秒的时间实在是忒长了点,对于Windows,修改注册表,在HKEY_LOCAL_MACHINE\ SYSTEM\CurrentControlSet\Services\ Tcpip\Parameters上添加一个DWORD类型的值TcpTimedWaitDelay,一般认为不要少于60,不然可能会有麻烦。

对于大型的服务,一台server搞不定,需要一个LB(Load Balancer)把流量分配到若干后端服务器上,如果这个LB是以NAT方式工作的话,可能会带来问题。假如所有从LB到后端Server的IP包的source address都是一样的(LB的对内地址),那么LB到后端Server的TCP连接会受限制,因为频繁的TCP连接建立和关闭,会在server上留下TIME_WAIT状态,而且这些状态对应的remote address都是LB的,LB的source port撑死也就60000多个(2^16=65536,1~1023是保留端口,还有一些其他端口缺省也不会用),每个LB上的端口一旦进入Server的TIME_WAIT黑名单,就有240秒不能再用来建立和Server的连接,这样LB和Server最多也就能支持300个左右的连接。如果没有LB,不会有这个问题,因为这样server看到的remote address是internet上广阔无垠的集合,对每个address,60000多个port实在是够用了。

一开始我觉得用上LB会很大程度上限制TCP的连接数,但是实验表明没这回事,LB后面的一台Windows Server 2003每秒处理请求数照样达到了600个,难道TIME_WAIT状态没起作用?用Net Monitor和netstat观察后发现,Server和LB的XXXX端口之间的连接进入TIME_WAIT状态后,再来一个LB的XXXX端口的SYN包,Server照样接收处理了,而是想像的那样被drop掉了。翻书,从书堆里面找出覆满尘土的大学时代买的《UNIX Network Programming, Volume 1, Second Edition: Networking APIs: Sockets and XTI》,中间提到一句,对于BSD-derived实现,只要SYN的sequence number比上一次关闭时的最大sequence number还要大,那么TIME_WAIT状态一样接受这个SYN,难不成Windows也算BSD-derived?有了这点线索和关键字(BSD),找到这个post,在NT4.0的时候,还是和BSD-derived不一样的,不过Windows Server 2003已经是NT5.2了,也许有点差别了。

做个试验,用Socket API编一个Client端,每次都Bind到本地一个端口比如2345,重复的建立TCP连接往一个Server发送Keep-Alive=false的HTTP请求,Windows的实现让sequence number不断的增长,所以虽然Server对于Client的2345端口连接保持TIME_WAIT状态,但是总是能够接受新的请求,不会拒绝。那如果SYN的Sequence Number变小会怎么样呢?同样用Socket API,不过这次用Raw IP,发送一个小sequence number的SYN包过去,Net Monitor里面看到,这个SYN被Server接收后如泥牛如海,一点反应没有,被drop掉了。

按照书上的说法,BSD-derived和Windows Server 2003的做法有安全隐患,不过至少这样至少不会出现TIME_WAIT阻止TCP请求的问题,当然,客户端要配合,保证不同TCP连接的sequence number要上涨不要下降。

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

Socket中的TIME_WAIT状态
在高并发短连接的server端,当server处理完client的请求后立刻closesocket此时会出现time_wait状态然后如果client再并发2000个连接,此时部分连接就连接不上了,用linger强制关闭可以解决此问题,但是linger会导致数据丢失,linger值为0时是强制关闭,无论并发多少多能正常连接上,如果非0会发生部分连接不上的情况!(可调用setsockopt设置套接字的linger延时标志,同时将延时时间设置为0。)TCP/IP的RFC文档。TIME_WAIT是TCP连接断开时必定会出现的状态。
是无法避免掉的,这是TCP协议实现的一部分。
在WINDOWS下,可以修改注册表让这个时间变短一些
time_wait的时间为2msl,默认为4min.
你可以通过改变这个变量:
TcpTimedWaitDelay
把它缩短到30s TCP要保证在所有可能的情况下使得所有的数据都能够被投递。当你关闭一个socket时,主动关闭一端的socket将进入TIME_WAIT状态,而被动关闭一方则转入CLOSED状态,这的确能够保证所有的数据都被传输。当一个socket关闭的时候,是通过两端互发信息的四次握手过程完成的,当一端调用close()时,就说明本端没有数据再要发送了。这好似看来在握手完成以后,socket就都应该处于关闭CLOSED状态了。但这有两个问题,首先,我们没有任何机制保证最后的一个ACK能够正常传输,第二,网络上仍然有可能有残余的数据包(wandering duplicates),我们也必须能够正常处理。
通过正确的状态机,我们知道双方的关闭过程如下


假设最后一个ACK丢失了,服务器会重发它发送的最后一个FIN,所以客户端必须维持一个状态信息,以便能够重发ACK;如果不维持这种状态,客户端在接收到FIN后将会响应一个RST,服务器端接收到RST后会认为这是一个错误。如果TCP协议能够正常完成必要的操作而终止双方的数据流传输,就必须完全正确的传输四次握手的四个节,不能有任何的丢失。这就是为什么socket在关闭后,仍然处于 TIME_WAIT状态,因为他要等待以便重发ACK。

如果目前连接的通信双方都已经调用了close(),假定双方都到达CLOSED状态,而没有TIME_WAIT状态时,就会出现如下的情况。现在有一个新的连接被建立起来,使用的IP地址与端口与先前的完全相同,后建立的连接又称作是原先连接的一个化身。还假定原先的连接中有数据报残存于网络之中,这样新的连接收到的数据报中有可能是先前连接的数据报。为了防止这一点,TCP不允许从处于TIME_WAIT状态的socket建立一个连接。处于TIME_WAIT状态的socket在等待两倍的MSL时间以后(之所以是两倍的MSL,是由于MSL是一个数据报在网络中单向发出到认定丢失的时间,一个数据报有可能在发送图中或是其响应过程中成为残余数据报,确认一个数据报及其响应的丢弃的需要两倍的MSL),将会转变为CLOSED状态。这就意味着,一个成功建立的连接,必然使得先前网络中残余的数据报都丢失了。

由于TIME_WAIT状态所带来的相关问题,我们可以通过设置SO_LINGER标志来避免socket进入TIME_WAIT状态,这可以通过发送RST而取代正常的TCP四次握手的终止方式。但这并不是一个很好的主意,TIME_WAIT对于我们来说往往是有利的。

客户端与服务器端建立TCP/IP连接后关闭SOCKET后,服务器端连接的端口
状态为TIME_WAIT 是不是所有执行主动关闭的socket都会进入TIME_WAIT状态呢?
有没有什么情况使主动关闭的socket直接进入CLOSED状态呢? 主动关闭的一方在发送最后一个 ack 后
就会进入 TIME_WAIT 状态 停留2MSL(max segment lifetime)时间
这个是TCP/IP必不可少的,也就是“解决”不了的。

也就是TCP/IP设计者本来是这么设计的
主要有两个原因
1。防止上一次连接中的包,迷路后重新出现,影响新连接
   (经过2MSL,上一次连接中所有的重复包都会消失)
2。可靠的关闭TCP连接
   在主动关闭方发送的最后一个 ack(fin) ,有可能丢失,这时被动方会重新发
   fin, 如果这时主动方处于 CLOSED 状态 ,就会响应 rst 而不是 ack。所以
   主动方要处于 TIME_WAIT 状态,而不能是 CLOSED 。

TIME_WAIT 并不会占用很大资源的,除非受到攻击。

还有,如果一方 send 或 recv 超时,就会直接进入 CLOSED 状态

socket-faq中的这一段讲的也很好,摘录如下:
2.7. Please explain the TIME_WAIT state.

Remember that TCP guarantees all data transmitted will be delivered,
if at all possible. When you close a socket, the server goes into a
TIME_WAIT state, just to be really really sure that all the data has
gone through. When a socket is closed, both sides agree by sending
messages to each other that they will send no more data. This, it
seemed to me was good enough, and after the handshaking is done, the
socket should be closed. The problem is two-fold. First, there is no
way to be sure that the last ack was communicated successfully.
Second, there may be "wandering duplicates" left on the net that must
be dealt with if they are delivered.

Andrew Gierth (andrew@erlenstar.demon.co.uk) helped to explain the
closing sequence in the following usenet posting:

Assume that a connection is in ESTABLISHED state, and the client is
about to do an orderly release. The client's sequence no. is Sc, and
the server's is Ss. Client Server
====== ======
ESTABLISHED ESTABLISHED
(client closes)
ESTABLISHED ESTABLISHED
------->>
FIN_WAIT_1
<<--------
FIN_WAIT_2 CLOSE_WAIT
<<-------- (server closes)
LAST_ACK
, ------->>
TIME_WAIT CLOSED
(2*msl elapses...)
CLOSED

Note: the +1 on the sequence numbers is because the FIN counts as one
byte of data. (The above diagram is equivalent to fig. 13 from RFC
793).

Now consider what happens if the last of those packets is dropped in
the network. The client has done with the connection; it has no more
data or control info to send, and never will have. But the server does
not know whether the client received all the data correctly; that's
what the last ACK segment is for. Now the server may or may not care
whether the client got the data, but that is not an issue for TCP; TCP
is a reliable rotocol, and must distinguish between an orderly
connection close where all data is transferred, and a connection abort
where data may or may not have been lost.

So, if that last packet is dropped, the server will retransmit it (it
is, after all, an unacknowledged segment) and will expect to see a
suitable ACK segment in reply. If the client went straight to CLOSED,
the only possible response to that retransmit would be a RST, which
would indicate to the server that data had been lost, when in fact it
had not been.

(Bear in mind that the server's FIN segment may, additionally, contain
data.)

DISCLAIMER: This is my interpretation of the RFCs (I have read all the
TCP-related ones I could find), but I have not attempted to examine
implementation source code or trace actual connections in order to
verify it. I am satisfied that the logic is correct, though.

More commentarty from Vic:

The second issue was addressed by Richard Stevens (rstevens@noao.edu,
author of "Unix Network Programming", see ``1.5 Where can I get source
code for the book [book title]?''). I have put together quotes from
some of his postings and email which explain this. I have brought
together paragraphs from different postings, and have made as few
changes as possible.

From Richard Stevens (rstevens@noao.edu):

If the duration of the TIME_WAIT state were just to handle TCP's full-
duplex close, then the time would be much smaller, and it would be
some function of the current RTO (retransmission timeout), not the MSL
(the packet lifetime).

A couple of points about the TIME_WAIT state.

o The end that sends the first FIN goes into the TIME_WAIT state,
because that is the end that sends the final ACK. If the other
end's FIN is lost, or if the final ACK is lost, having the end that
sends the first FIN maintain state about the connection guarantees
that it has enough information to retransmit the final ACK.

o Realize that TCP sequence numbers wrap around after 2**32 bytes
have been transferred. Assume a connection between A.1500 (host A,
port 1500) and B.2000. During the connection one segment is lost
and retransmitted. But the segment is not really lost, it is held
by some intermediate router and then re-injected into the network.
(This is called a "wandering duplicate".) But in the time between
the packet being lost & retransmitted, and then reappearing, the
connection is closed (without any problems) and then another
connection is established between the same host, same port (that
is, A.1500 and B.2000; this is called another "incarnation" of the
connection). But the sequence numbers chosen for the new
incarnation just happen to overlap with the sequence number of the
wandering duplicate that is about to reappear. (This is indeed
possible, given the way sequence numbers are chosen for TCP
connections.) Bingo, you are about to deliver the data from the
wandering duplicate (the previous incarnation of the connection) to
the new incarnation of the connection. To avoid this, you do not
allow the same incarnation of the connection to be reestablished
until the TIME_WAIT state terminates.

Even the TIME_WAIT state doesn't complete solve the second problem,
given what is called TIME_WAIT assassination. RFC 1337 has more
details.

o The reason that the duration of the TIME_WAIT state is 2*MSL is
that the maximum amount of time a packet can wander around a
network is assumed to be MSL seconds. The factor of 2 is for the
round-trip. The recommended value for MSL is 120 seconds, but
Berkeley-derived implementations normally use 30 seconds instead.
This means a TIME_WAIT delay between 1 and 4 minutes. Solaris 2.x
does indeed use the recommended MSL of 120 seconds.

A wandering duplicate is a packet that appeared to be lost and was
retransmitted. But it wasn't really lost ... some router had
problems, held on to the packet for a while (order of seconds, could
be a minute if the TTL is large enough) and then re-injects the packet
back into the network. But by the time it reappears, the application
that sent it originally has already retransmitted the data contained
in that packet.

Because of these potential problems with TIME_WAIT assassinations, one
should not avoid the TIME_WAIT state by setting the SO_LINGER option
to send an RST instead of the normal TCP connection termination
(FIN/ACK/FIN/ACK). The TIME_WAIT state is there for a reason; it's
your friend and it's there to help you :-)

I have a long discussion of just this topic in my just-released
"TCP/IP Illustrated, Volume 3". The TIME_WAIT state is indeed, one of
the most misunderstood features of TCP.

I'm currently rewriting "Unix Network Programming" (see ``1.5 Where
can I get source code for the book [book title]?''). and will include
lots more on this topic, as it is often confusing and misunderstood.

An additional note from Andrew:

Closing a socket: if SO_LINGER has not been called on a socket, then
close() is not supposed to discard data. This is true on SVR4.2 (and,
apparently, on all non-SVR4 systems) but apparently not on SVR4; the
use of either shutdown() or SO_LINGER seems to be required to
guarantee delivery of all data.

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

讨厌的 Socket TIME_WAIT 问题

netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'

会得到类似下面的结果,具体数字会有所不同:

    LAST_ACK 1
    SYN_RECV 14
    ESTABLISHED 79
    FIN_WAIT1 28
    FIN_WAIT2 3
    CLOSING 5
    TIME_WAIT 1669

状态:描述
CLOSED:无连接是活动的或正在进行
LISTEN:服务器在等待进入呼叫
SYN_RECV:一个连接请求已经到达,等待确认
SYN_SENT:应用已经开始,打开一个连接
ESTABLISHED:正常数据传输状态
FIN_WAIT1:应用说它已经完成
FIN_WAIT2:另一边已同意释放
ITMED_WAIT:等待所有分组死掉
CLOSING:两边同时尝试关闭
TIME_WAIT:另一边已初始化一个释放
LAST_ACK:等待所有分组死掉

也就是说,这条命令可以把当前系统的网络连接状态分类汇总。

下面解释一下为啥要这样写:

一个简单的管道符连接了netstat和awk命令。

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

每个TCP报文在网络内的最长时间,就称为MSL(Maximum Segment Lifetime),它的作用和IP数据包的TTL类似。

RFC793指出,MSL的值是2分钟,但是在实际的实现中,常用的值有以下三种:30秒,1分钟,2分钟。

注意一个问题,进入TIME_WAIT状态的一般情况下是客户端,大多数服务器端一般执行被动关闭,不会进入TIME_WAIT状态,当在服务

器端关闭某个服务再重新启动时,它是会进入TIME_WAIT状态的。

举例:
1.客户端连接服务器的80服务,这时客户端会启用一个本地的端口访问服务器的80,访问完成后关闭此连接,立刻再次访问服务器的

80,这时客户端会启用另一个本地的端口,而不是刚才使用的那个本地端口。原因就是刚才的那个连接还处于TIME_WAIT状态。
2.客户端连接服务器的80服务,这时服务器关闭80端口,立即再次重启80端口的服务,这时可能不会成功启动,原因也是服务器的连

接还处于TIME_WAIT状态。


检查net.ipv4.tcp_tw当前值,将当前的值更改为1分钟:
[root@aaa1 ~]# sysctl -a|grep net.ipv4.tcp_tw
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_tw_recycle = 0
[root@aaa1 ~]#

vi /etc/sysctl
增加或修改net.ipv4.tcp_tw值:
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1

使内核参数生效:
[root@aaa1 ~]# sysctl -p

[root@aaa1 ~]# sysctl -a|grep net.ipv4.tcp_tw
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1

用netstat再观察正常


这里解决问题的关键是如何能够重复利用time_wait的值,我们可以设置时检查一下time和wait的值
#sysctl -a | grep time | grep wait
net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait = 120
net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait = 60
net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait = 120

问一下TIME_WAIT有什么问题,是闲置而且内存不回收吗?

是的,这样的现象实际是正常的,有时和访问量大有关,设置这两个参数: reuse是表示是否允许重新应用处于TIME-WAIT状态的

socket用于新的TCP连接; recyse是加速TIME-WAIT sockets回收

Q: 我正在写一个unix server程序,不是daemon,经常需要在命令行上重启它,绝大
多数时候工作正常,但是某些时候会报告"bind: address in use",于是重启失
败。

A: Andrew Gierth
server程序总是应该在调用bind()之前设置SO_REUSEADDR套接字选项。至于
TIME_WAIT状态,你无法避免,那是TCP协议的一部分。

Q: 如何避免等待60秒之后才能重启服务

A: Erik Max Francis

使用setsockopt,比如

--------------------------------------------------------------------------
int option = 1;

if ( setsockopt ( masterSocket, SOL_SOCKET, SO_REUSEADDR, &option,
sizeof( option ) ) < 0 )
{
die( "setsockopt" );
}
--------------------------------------------------------------------------

Q: 编写 TCP/SOCK_STREAM 服务程序时,SO_REUSEADDR到底什么意思?

A: 这个套接字选项通知内核,如果端口忙,但TCP状态位于 TIME_WAIT ,可以重用
端口。如果端口忙,而TCP状态位于其他状态,重用端口时依旧得到一个错误信息,
指明"地址已经使用中"。如果你的服务程序停止后想立即重启,而新套接字依旧
使用同一端口,此时 SO_REUSEADDR 选项非常有用。必须意识到,此时任何非期
望数据到达,都可能导致服务程序反应混乱,不过这只是一种可能,事实上很不
可能。

一个套接字由相关五元组构成,协议、本地地址、本地端口、远程地址、远程端
口。SO_REUSEADDR 仅仅表示可以重用本地本地地址、本地端口,整个相关五元组
还是唯一确定的。所以,重启后的服务程序有可能收到非期望数据。必须慎重使
用 SO_REUSEADDR 选项。

Q: 在客户机/服务器编程中(TCP/SOCK_STREAM),如何理解TCP自动机 TIME_WAIT 状
态?

A: W. Richard Stevens <1999年逝世,享年49岁>

下面我来解释一下 TIME_WAIT 状态,这些在<>
中2.6节解释很清楚了。

MSL(最大分段生存期)指明TCP报文在Internet上最长生存时间,每个具体的TCP实现
都必须选择一个确定的MSL值。RFC 1122建议是2分钟,但BSD传统实现采用了30秒。

TIME_WAIT 状态最大保持时间是2 * MSL,也就是1-4分钟。

IP头部有一个TTL,最大值255。尽管TTL的单位不是秒(根本和时间无关),我们仍需
假设,TTL为255的TCP报文在Internet上生存时间不能超过MSL。

TCP报文在传送过程中可能因为路由故障被迫缓冲延迟、选择非最优路径等等,结果
发送方TCP机制开始超时重传。前一个TCP报文可以称为"漫游TCP重复报文",后一个
TCP报文可以称为"超时重传TCP重复报文",作为面向连接的可靠协议,TCP实现必须
正确处理这种重复报文,因为二者可能最终都到达。

一个通常的TCP连接终止可以用图描述如下:

client server
FIN M
close -----------------> (被动关闭)
ACK M+1
<-----------------
FIN N
<----------------- close
ACK N+1
----------------->

为什么需要 TIME_WAIT 状态?

假设最终的ACK丢失,server将重发FIN,client必须维护TCP状态信息以便可以重发
最终的ACK,否则会发送RST,结果server认为发生错误。TCP实现必须可靠地终止连
接的两个方向(全双工关闭),client必须进入 TIME_WAIT 状态,因为client可能面
临重发最终ACK的情形。

{
scz 2001-08-31 13:28

先调用close()的一方会进入TIME_WAIT状态
}

此外,考虑一种情况,TCP实现可能面临先后两个同样的相关五元组。如果前一个连
接处在 TIME_WAIT 状态,而允许另一个拥有相同相关五元组的连接出现,可能处理
TCP报文时,两个连接互相干扰。使用 SO_REUSEADDR 选项就需要考虑这种情况。

为什么 TIME_WAIT 状态需要保持 2MSL 这么长的时间?

如果 TIME_WAIT 状态保持时间不足够长(比如小于2MSL),第一个连接就正常终止了。
第二个拥有相同相关五元组的连接出现,而第一个连接的重复报文到达,干扰了第二
个连接。TCP实现必须防止某个连接的重复报文在连接终止后出现,所以让TIME_WAIT
状态保持时间足够长(2MSL),连接相应方向上的TCP报文要么完全响应完毕,要么被
丢弃。建立第二个连接的时候,不会混淆。

A: 小四

在Solaris 7下有内核参数对应 TIME_WAIT 状态保持时间

# ndd -get /dev/tcp tcp_time_wait_interval
240000
# ndd -set /dev/tcp tcp_time_wait_interval 1000

缺省设置是240000ms,也就是4分钟。如果用ndd修改这个值,最小只能设置到1000ms,
也就是1秒。显然内核做了限制,需要Kernel Hacking。

# echo "tcp_param_arr/W 0t0" | adb -kw /dev/ksyms /dev/mem
physmem 3b72
tcp_param_arr: 0x3e8 = 0x0
# ndd -set /dev/tcp tcp_time_wait_interval 0

我不知道这样做有什么灾难性后果,参看<>的声明。

Q: TIME_WAIT 状态保持时间为0会有什么灾难性后果?在普遍的现实应用中,好象也
就是服务器不稳定点,不见得有什么灾难性后果吧?

D: rain@bbs.whnet.edu.cn

Linux 内核源码 /usr/src/linux/include/net/tcp.h 中

#define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to successfully
* close the socket, about 60 seconds */

最好不要改为0,改成1。端口分配是从上一次分配的端口号+1开始分配的,所以一般
不会有什么问题。端口分配算法在tcp_ipv4.c中tcp_v4_get_port中。


已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



Android WebView的坑总结

$
0
0

       最近把做好的iPad HybridApp向Android迁移,碰到的坑太多了,让我这个折腾过Android接近4年的老鸟都头疼!现在把前人遇到的都列出来,再慢慢解决自己的,目前已经解决了android键盘覆盖问题,下面最棘手的问题就是屏幕高度的适配问题了!本文会不断更新

1、 Andrid4.1事件穿透BUG 原因不明



2、 Android2.X 中文不支持粗体


3、 目前发现的WEBVIEW尺寸宽度有320、 360、 400等多个尺寸 


该分辨率或许和屏幕尺寸有关
                                    目前测试结果
320-640分辨率-》320
720分辨率 –》360
800 分辨率 –》400

难道是手机宽度的一半?

屏幕密度的的问题啊 !!!



4、 原尺寸图片放到WEBVIEW里会显得很模糊,建议采用大图进行缩小 
比如 需要为300*100大小的图片,请使用600*200的来进行缩小


5、 ANDROID 2.X  TEXTAREA|INPUT等空间可能会出现移位的情况,原因也许与position:fix有关


6、 text-overflow:ellipsis;(字符串CSS截取)功能BUG:截取长度会把margin-left一起计算进去,导致含有margin-left的容器被截取内容过多。


7、 使用translate3d的位移会导致position:fixed的内置元素一起移动。此BUG更恶心的是,在IPHONE里会直接移掉,可在ANDROID里显示不会移动,但如果有事件的话,事件的可点击区域会位移。估计是ANDROID尝试修复没修复好。


8、 WEBVIEW内存限制12M(目前此问题尚未出现)


9、 ANDROID2.X不支持BOX-SHADOW


10、 不支持MASK


11、 支持CALC,使用时请注意防止被LESS预编译
  width:~"-webkit-calc(100% - 100px)";
margin: 0px 50px;

通过此方法可以很容易实现浮动元素居中,而不用去计算TOP LEFT 


12、android4.4 好像不支持target-densitydpi=device-dpi,Android4.3 支持



作者:offbye 发表于2014-6-24 14:13:20 原文链接
阅读:0 评论:0 查看评论

数据库表的拆分

$
0
0

下面来分析一下:

  一、时间结构

  如果业务系统对时效性较高,比如新闻发布系统的文章表,可以把数据库设计成时间结构,按时间分有几种结构:

  1) 平板式

  表类似:

  article_200901

  article_200902

  article_200903

  用年来分还是用月可自定,但用日期的话表就太多了,也没这必要。一般建议是按月分就可以。

  这种分法,其难处在于,假设我要列20条数据,结果这三张表里都有2条,那么业务上很有可能要求读三次表。如果时间长了,有几十张表,而每张表是0条,那不就是要读完整个系统的表才行么?另外这个结构,要作分页是比较难实现的。

  主键:在这个系统中,主键是13位带毫秒的时间戳,不要用自动编号,否则难以通过主键定位到表,也可以在查询时带上时间,但比较烦琐。

  2) 归档式

  表类似:

  article_old

  article_new

  为了解决平板式的缺点,可以采用时间归档式设计,可以看到这个系统只有两张表。一张是旧文章表,一张是新文章表,新文章表放2个月的信息,每天定期把2个月中的最早一天的文章归入旧表中。这样一方面可以解决性能问题,因为一般新闻发布系统读取的都是新的内容,旧的内容读取少;第二可以委婉地解决功能问题,比如平板式所说的问题,在归档式中最多也只需要读2张表就完成了。

  归档式的缺点在于旧表容量还是相对比较大,如果业务允许,可对旧表中的超旧内容进行再归档或直接清理掉。

  二、版块结构

  如果按照文章的所属版块进行拆表,比如新闻、体育版块拆表,一方面可以使每个表数据量分离,另一方面是各版块之间相互影响可降到最低。假如新闻版块的数据表损坏或需要维护,并不会影响到体育版块的正常工作,从而降低了风险。版块结构同时常用于bbs这样的系统。

  板块结构也有几种分法:

  1) 对应式

  对于版块数量不多,而且较为固定的形式,就直接对应就好。比如新闻版块,可以分出新闻的目录表,新闻的文章表等。

  news_category

  news_article

  sports_category

  sports_article

  可看到每一个版块都对应着一组相同的表结构,好处就是一目了然。在功能上,因为版块之间还是有一些隔阂,所以需要联合查询的需求不多,开发上比时间结构的方式要轻松。

  主键:依旧要考虑的,在这个系统中,主键是版块+时间戳,单纯的时间戳或自动编号也能用,查询时要记得带上版块用于定位表。

  2) 冷热式

  对应式的缺点是,如果版块数量很大而且不确定,那要分出的表数量就太多了。举个例子:百度贴吧,如果按一个词条一个表设计,那得有多少张表呢?

  用这样的方式吧。

  tieba_汽车

  tieba_飞机

  tieba_火箭

  tieba__unite

  这个表汽车、火箭表是属于热门表,定义为新建的版块放在unite表里面,待到其超过一万张主贴的时候才开对应表结构。因为在贴吧这种系统中,冷门版块肯定比热门版块多得多,这些冷门版块通常只有几张帖子,为它们开表也太浪费了;同时热门版块数量和访问量等,又比冷门版块多得多,非常有特点。

  unite表还可以扩展成哈希表,利用词条的md5编码,可以分成n张表,我算了一下,md5前一位可分36张表,两位即是1296张表,足够了。

  tieba_unite_ab

  tieba_unite_ac

  …

  三、哈希结构

  哈希结构通常用于博客之类的基于用户的场合,在博客这样的系统里有几个特点,1是用户数量非常多,2是每个用户发的文章数量都较少,3是用户发文章不定期,4是每个用户发得不多,但总量仍非常之大。基于这些特点,用以上所说的任何一种分表方式都不合适,一没有固定的时效不宜用时间拆,二用户很多,而且还偏偏都是冷门,所以也不宜用版块(用户)拆。

  哈希结构在上面有所提及,既然按每个用户不好直接拆,那就把一群用户归进一个表好了。

  blog_aa

  blog_ab

  blog_ac

  …

  如上所说,md5取前两位哈希可以达到1296张表,如果觉得不够,那就再加一位,总数可达46656张表,还不够?

  表的数量太多,要创建这些表也是挺麻烦的,可以考虑在程序里往数据库insert之前,多执行一句判断表存在与否并创建表的语句,很实用,消耗也并不很大。

  主键:依旧要考虑的,在这个系统中,主键是用户ID+时间戳,单纯的时间戳或自动编号也能用,但查询时要记得带上用户名用于定位表。

  四、总分结构

  以上的这些结构,根据每个业务系统,能想出的估计还有很多。不过现在互联网业务越来越复杂了,有些时候,单一的拆分法还不能实现需求,需要几种拆分方案一起实施,多管齐下,这时候其中的逻辑会让人绕晕。我就开发过一个系统,仅仅是将哈希结构和时间结构混着一用,觉得逻辑就相当复杂。

  所以,除了拆表之外,按最原始的单库单表,再建一个总表,是非常有利的架构。在这个架构中,每次往数据库会写入两倍数据,读取主要依赖拆表提升性能,总表用于实现拆表后难以实现的功能并且用于每天的定时备份;另外总表和分表还相互是一个完整的备份,任何一个分表损坏或数据不正常,都可以从总表中读到正确的数据并恢复,反之亦然。

  在总分结构中,让人感到质疑的是总表的性能和可维护性。我的方案是总表可采用相对能保证稳定的一些服务软件和架构,例如oracle,或lvs+ pgpool+PostgreSQL,重点保证数据稳定;相对的,分表就用轻量级的mysql,重点在于速度。能够对总分表各采用不同的软件和方案,也是总分结构的一大特点。



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



高性能消息系统——Kafka

$
0
0

 

什么是Kafka?
引用官方原文: “Kafka is a distributed, partitioned, replicated commit log service.”
它提供了一个非常特殊的消息机制,不同于传统的mq。
官网:https://kafka.apache.org
它与传统的mq区别?

    更快!单机上万TPS
    传统的MQ,消息被消化掉后会被mq删除,而kafka中消息被消化后不会被删除,而是到配置的expire时间后,才删除
    传统的MQ,消息的Offset是由MQ维护,而kafka中消息的Offset是由客户端自己维护
    分布式,把写入压力均摊到各个节点。可以通过增加节点降低压力

基本术语
为方便理解,我用对比传统MQ的方式阐述这些基本术语。
Producer
Consumer
这两个与传统的MQ一样,不解释了
Topic
Kafka中的topic其实对应传统MQ的channel,即消息管道,例如同一业务用同一根管道
Broker
集群中的KafkaServer,用来提供Partition服务
Partition
假如说传统的MQ,传输消息的通道(channel)是一条双车道公路,那么Kafka中,Topic就是一个N车道的高速公路。每个车道都可以行车,而每个车道就是Partition。

    一个Topic中可以有一个或多个partition。
    一个Broker上可以跑一个或多个Partition。集群中尽量保证partition的均匀分布,例如定义了一个有3个partition的topic,而只有两个broker,那么一个broker上跑两个partition,而另一个是1个。但是如果有3个broker,必然是3个broker上各跑一个partition。
    Partition中严格按照消息进入的顺序排序
    一个从Producer发送来的消息,只会进入Topic的某一个Partition(除非特殊实现Producer要求消息进入所有Partition)
    Consumer可以自己决定从哪个Partition读取数据

Offset
单个Partition中的消息的顺序ID,例如第一个进入的Offset为0,第二个为1,以此类推。传统的MQ,Offset是由MQ自己维护,而kafka是由client维护

Replica
Kafka从0.8版本开始,支持消息的HA,通过消息复制的方式。在创建时,我们可以指定一个topic有几个partition,以及每个partition有几个复制。复制的过程有同步和异步两种,根据性能需要选取。正常情况下,写和读都是访问leader,只有当leader挂掉或者手动要求重新选举,kafka会从几个复制中选举新的leader。
Kafka会统计replica与leader的同步情况。当一个replica与leader数据相差不大,会被认为是一个"in-sync" replica。只有"in-sync" replica才有资格参与重新选举。

ConsumerGroup
一个或多个Consumer构成一个ConsumerGroup,一个消息应该只能被同一个ConsumerGroup中的一个Consumer消化掉,但是可以同时发送到不同ConsumerGroup。
通常的做法,一个Consumer去对应一个Partition。
传统MQ中有queuing(消息)和publish-subscribe(订阅)模式,Kafka中也支持:

    当所有Consumer具有相同的ConsumerGroup时,该ConsumerGroup中只有一个Consumer能收到消息,就是queuing模式
    当所有Consumer具有不同的ConsumerGroup时,每个ConsumerGroup会收到相同的消息,就是publish-subscribe模式

基本交互原理
每个Topic被创建后,在zookeeper上存放有其metadata,包含其分区信息、replica信息、LogAndOffset等
默认路径/brokers/topics/<topic_id>/partitions/<partition_index>/state
Producer可以通过zookeeper获得topic的broker信息,从而得知需要往哪写数据。
Consumer也从zookeeper上获得该信息,从而得知要监听哪个partition。


基本CLI操作
1. 创建Topic
./kafka-create-topic.sh --zookeeper 10.1.110.21:2181 --replica 2 --partition 3 --topic test
2. 查看Topic信息
./kafka-list-topic.sh --topic test --zookeeper 10.1.110.24:2181
3. 增加Partition
./kafka-add-partitions.sh --partition 4 --topic test --zookeeper 10.1.110.24:2181
更多命令参见:https://cwiki.apache.org/confluence/display/KAFKA/Replication+tools


创建一个Producer
Kafka提供了java api,Producer特别的简单,举传输byte[] 为例
[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

    Properties p = new Properties(); 
    props.put("metadata.broker.list", "10.1.110.21:9092"); 
    ProducerConfig config = new ProducerConfig(props); 
    Producer producer = new Producer<String, byte[]>(config); 
    producer.send(byte[] msg); 


更具体的参见:https://cwiki.apache.org/confluence/display/KAFKA/0.8.0+Producer+Example

创建一个Consumer
Kafka提供了两种java的Consumer API:High Level Consumer和Simple Consumer
看上去前者似乎要更牛B一点,事实上,前者做了更多的封装,比后者要Simple的多……
具体例子我就不写了,参见
High Level Consumer: https://cwiki.apache.org/confluence/display/KAFKA/Consumer+Group+Example
Simple Consumer: https://cwiki.apache.org/confluence/display/KAFKA/0.8.0+SimpleConsumer+Example

 

快速学习:http://kafka.apache.org/07/quickstart.html





已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐




LCD开发之汉字显示

$
0
0

一、LCD显示原理

利用液晶制成的显示器称为LCD,依据驱动方式可分为静态驱动、简单矩阵驱动以及 主动矩阵驱动3种。其中,简单矩阵型又可再细分扭转向列型(TN)和超扭转式向列型(STN)两种,而主动矩阵型则以薄膜式晶体管型( TFT)为主流。

一块LCD 屏显示图像不但需要 LCD驱动器,还需要有相应的 LCD控制器。通常 LCD 驱动器会以 COF/COG的形式与LCD 玻璃基板制作在一起,而 LCD 控制器则由外部电路来实现。许多MCU 内部直接集成了LCD 控制器,通过LCD控制器可以方便地控制 STN 和 TFT 屏。

TFT屏是目前入式系统应用的主流,下图给出了TFT屏的典型时序。时序图中的VCLK、HSYNC 和 VSYNC 分别为像素时钟信号(用于锁存图像数据的像素时钟)、行同步信号和帧同步信号,VDEN 为数据有效标志信号,VD 为图像的数据信号。


作为帧同步信号的 VSYNC,每发出一个脉冲,都意味着新的一屏图像数据开始发送。而作为行同步信号的 HSYNC,每发出一个脉冲都表明新的一行图像资料开始发送。在帧同步以及行同步的头尾都必须留有回扫时间。

下图给出了 LCD 控制器中应该设置的 TFT屏的参数,其中的上边界和下边界即为帧切换的回扫时间,左边界和右边界即为行切换的回扫时间,水平同步和垂直同步分别是行和帧同步本身需要的时间。 xres 和 yres 则分别是屏幕的水平和垂直分辨率,常见的嵌入式设备的 LCD 分辨率主要为 320*240、640*480 等。


二、帧缓冲

1、基本概念

帧缓冲(framebuffer)是 Linux 系统为显示设备提供的一个接口,它将显示缓冲区抽象,屏蔽图像硬件的底层差异,允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。对于帧缓冲设备而言,只要在显示缓冲区中与显示点对应的区域写入颜色值,对应的颜色会自动在屏幕上显示。

帧缓冲设备为标准字符设备,主设备号为29,对应于/dev/fb%d 设备文件。帧缓冲驱动的应用非常广泛,在Linux的桌面系统中,X window服务器就是利用帧缓冲进行窗口的绘制。嵌入式系统中的Qt/Embedded等图形用户界面环境也基于帧缓冲而设计。另外,通过帧缓冲可支持汉字点阵的显示,因此帧缓冲也成为Linux汉化的可行方案。

2、显示缓冲区与显示点      

在帧缓冲设备中,对屏幕显示点的操作通过读写显示缓冲区来完成,在不同的色彩模式下,显示缓冲区和屏幕上的显示点有不同的对应关系。下表分别是8位色和16 位色时显示缓冲区与显示点的对应关系:


3、Linux 帧缓冲相关数据结构与函数

1)fb_info 结构体

帧缓冲设备最关键的一个数据结构体是fb_info 结构体,它包括了关于帧缓冲设备属性和操作的完整描述,这个结构体定义在/include/linux/fb.h中,代码如下所示:


该结构体记录了帧缓冲设备的全部信息,包括设备的设置参数、状态以及操作函数指针。每一个帧缓冲设备都必须对应一个fb_info。

2)fb_ops结构体


fb_ops 的fb_check_var()成员函数用于检查可以修改的屏幕参数并调整到合适的值,而 fb_set_par()则使得用户设置的屏幕参数在硬件上有效。

3)fb_var_screeninfo和 fb_fix_screeninfo 结构体

fb_var_screeninfo记录用户可修改的显示控制器参数,包括屏幕分辨率和每个像素点的比特数。fb_var_screeninfo 中的 xres 定义屏幕一行有多少个点, yres 定义屏幕一列有多少个点,bits_per_pixel 定义每个点用多少个字节表示。而 fb_fix_screeninfo 中记录用户不能修改的显示控制器的参数,如屏幕缓冲区的物理地址、长度。当对帧缓冲设备进行映射操作的时候,就是从 fb_fix_screeninfo 中取得缓冲区物理地址的。上述数据成员都需要在驱动程序中初始化和设置。

fb_var_screeninfo和 fb_fix_screeninfo 结构体的定义在/include/linux/fb.h中,代码分别如下:



fb_fix_screeninfo结构体定义中第8 行的 visual 记录屏幕使用的色彩模式,在 Linux 系统中,支持的色彩模式包括如下几种。

●  Monochrome(FB_VISUAL_MONO01、FB_VISUAL_MONO10),每个像素是黑或白。

●  Pseudo color ( FB_VISUAL_PSEUDOCOLOR 、FB_VISUAL_ST ATIC_PSEUDOCOLOR),即伪彩色,采用索引颜色显示。

●  T rue color(FB_VISUAL_TRUECOLOR),真彩色,分成红、绿、蓝三基色。

●  Direct color(FB_VISUAL_DIRECTCOLOR),每个像素颜色也是有红、绿、

蓝组成,不过每个颜色值是个索引,需要查表。

●  Grayscale displays,灰度显示,红、绿、蓝的值都一样。

4)文件操作结构体

作为一种字符设备,帧缓冲设备的文件结构体定义在/linux/drivers/vedio/fbmem.c文件中,代码如下:


帧缓冲设备驱动的文件操作接口函数已经在fbmem.c 中被统一实现,一般不需要由驱动工程师再编写。

5)注册与注销帧缓冲设备

Linux 内核提供了register_framebuf fer()和 unregister_framebu销帧缓冲设备,这两个函数都接受fb_info指针为参数,原型为:


对于register_framebuffer()函数而言,如果注册的帧缓冲设备数超过了 FB_MAX(目前定义为 32),则函数返回-ENXIO,注册成功则返回 0。

三、Linux 帧缓冲设备驱动结构

Linux 帧缓冲设备驱动的主要结构如下图所示,帧缓冲设备提供给用户空间的file_operations 结构体由fbmem.c 中的file_operations 提供,而特定帧缓冲设备fb_info结构体的注册、注销以及其中成员的维护,尤其是fb_ops中成员函数的实现则由对应的 xxxfb.c 文件实现,fb_ops 中的成员函数最终会操作 LCD 控制器硬件寄存器。


四、帧缓冲设备的用户空间访问

通过/dev/fbns,应用程序可进行的针对帧缓冲设备的操作主要有如下几种。

●  读/写 dev/fbn:相当于读/写屏幕缓冲区。例如用cp  /dev/fb0 tmp 命令可将当前屏幕的内容复制到一个文件中,而命令cp  tmp  > /dev/fb0  则将图形文件tmp 显示在屏幕上。

●  映射操作:对于帧缓冲设备,可通过mmap()映射操作将屏幕缓冲区的物理地址映射到用户空间的一段虚拟地址中,之后用户就可以通过读/写这段虚拟地址访问屏幕缓冲区,在屏幕上绘图。而且若干个进程可以映射到同一个显示缓冲区。实际上,使用帧缓冲设备的应用程序都是通过映射操作来显示图形的。

● I/O 控制:对于帧缓冲设备,对设备文件的ioctl()操作可读取/设置显示设备及屏幕的参数,如分辨率、显示颜色数、屏幕大小等。

在应用程序中,操作/dev/fbn 的一般步骤如下。

(1)打开/dev/fbn 设备文件;

(2)用 ioctl()操作取得当前显示屏幕的参数,如屏幕分辨率、每个像素点的比特数和偏移;根据屏幕参数可计算屏幕缓冲区的大小;

(3)将屏幕缓冲区映射到用户空间;

(4)映射后就可以直接读/写屏幕缓冲区,进行绘图和图片显示了。

例子:

功能:在LCD屏幕上显示红色汉字“赵”。

源码如下:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>

int main()
{
       int fbfd=0;
       struct fb_var_screeninfo vinfo;
       unsigned long screensize=0;
       char *fbp=0;
       int x=0,y=0;
       fbfd=open("/dev/fb0",O_RDWR);  //打开帧缓冲设备
       if(!fbfd){
              printf("error\n");
              exit(1);
       }
       if(ioctl(fbfd,FBIOGET_VSCREENINFO,&vinfo)){  //获取屏幕可变参数
              printf("error\n");
              exit(1);
       }
       //打印屏幕可变参数
       printf("%dx%d,%dbpp\n",vinfo.xres,vinfo.yres,vinfo.bits_per_pixel);
       screensize=vinfo.xres*vinfo.yres* vinfo.bits_per_pixel/2;  //缓冲区字节大小
       fbp=(char *)mmap(0,screensize,PROT_READ|PROT_WRITE,MAP_SHARED,fbfd,0);//映射
       if((int)fbp==-1){
              printf("error\n");
              exit(4);
       }   
	   memset(fbp,0,screensize); //清屏
	   char hz[16][2]={
	   0x08, 0x00, 0x08, 0x00, 0x08, 0x04, 0x7E, 0x84, 0x08, 0x48, 0x08, 0x28, 0xFF, 0x10, 0x08, 0x10,
	   0x28, 0x28, 0x2F, 0x28, 0x28, 0x44, 0x28, 0x84, 0x58, 0x00, 0x48, 0x00, 0x87, 0xFE, 0x00, 0x00,                                                                                  
	}; //16*16字模库中提取的“赵”字对应的字符数组
       int i,j,k;
       for(j=0;j<16;j++){
       		for(i=0;i<2;i++){
        		for(k=0;k<8;k++){
                	if(hz[j][i]&(0x80>>k))
						*((unsigned short *)(fbp + j*vinfo.xres*2 + i*16 + k*2))=0xf100;
				}
	    	}
	   }     	
       munmap(fbp,screensize);
       close(fbfd);
       return 0;
}

ps:0xf100即对应16位:1111 1000 0000 0000,查看16位色时显示缓冲区与显示点的对应关系表,可以得出此像素点对应红色。

参考资料:《Linux设备驱动开发详解》

2014年6月23日星期一22时54分

作者:suaoyang 发表于2014-6-23 22:50:10 原文链接
阅读:39 评论:0 查看评论

工作后的我,是怎样学习英语的

$
0
0

最近看到连岳老师的一篇文章,其中写道:“学好英语,无法好到当工作语言,至少基本的听说读写要过关,英语现在是世界语言,资讯及观点的富矿区,而且是一门不需要审核的语言,它是翅膀,想飞就得有。”对这句话真是深有感触的。读书的时候学了那么多年英语,毕业后也没有放松过。在一天天的工作中,英语的重要性慢慢显现出来了。现在分享一些学习英语的经验给大家吧。希望对大家有用。 

1,下班之后看一段美剧,学口语。

口语是说出来的,跟读模仿是最行之有效的方法之一。美剧中的对话都是生活常用语,是练习口语的最好材料。通过跟读模仿,不仅能了解美国的文化,又能学会词语的使用环境。跟读模仿要大声放纵的朗读,要放得开(当然,对内敛型的学习者来说,按自己的方式模仿未尝不可)。跟读或者模仿时遇到到不会的单词凭印象或感觉先读出来,不要停下来研究这样影响练习口语的连贯性。《老友记》、《越狱》、《绝望主妇》等等是我看过一遍又一遍的,很适合练习口语。 

2.上班路上练习听力

说到练习听力,tingroom必须要介绍,听力资料非常多,考四六级的时候很有帮助,还有新概念英语、VOA、牛津听力等等各种听力资料,四六级听力真题这些适合考试的时候用,不过有点枯燥,只有在大学考级的时候总听,现在工作了偶尔去看看。需要考级的小伙伴们可以去看一下,www.tingroom.com.不得不吐一下槽,网站页面真是不好看,对于美观性要求非常高的我来说,看在听力资料丰富的情况下,只能忍了….%>_<% 

3.闲暇时间也可以利用起来。

在工作中累了或者睡觉前的时候,我会看一篇有趣的英语资讯类型的短文来放松下,,顺便也可以了解下逗比的国家又发生了啥逗比的事儿。我订阅了一个微信公众号:BEEleanor。这个账号每天会分享一些英语资讯啊,新闻趣事啊,定时会有一些主题英语啊等等,比如最近就分享过世界杯英语什么的。话说,看头像好像还是夏洛克的粉丝…在这样轻松幽默语境下,学英语还是很有趣的….我就把它当做闲暇时候获取英语新闻资讯,小八卦的一个账号吧…对于学习地道的英语还是很有帮助的。 

4,周末练习写作。

英语写作也是很重要的,有网友推荐了www.mylot.com这个网站,是国外网赚网站,语言是英语,类似与论坛,里面的人都很积极热心,因为发帖回帖都能挣钱(但是很少)一般是零点几美分,所以几乎是任何话题都有人回答。我是看过网友分享过“有时候我有字典解决不了的问题,就到这个上问老外,一般都能得到回答,只是有些问题老外也不知道,不过最好不要以挣钱为目的,因为需要攒到10美金才能取出,我的到现在才4元多点美金,而且需要类似与支付宝之类的东西,挺麻烦的”。确实是很不错的。主要是在这里可以和英/美国人就各种话题交流。

好了,以上就是本人学习英语的一些方法,和能够跟大家分享的一些资源了。英语还是贵在坚持的。只要一点一滴积累起来,总会有一口的惊艳的英语的。 

对于我来说,英语是一种不死的欲望,是疲惫生活的英雄梦想。



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



Xen 虚拟机的 NAT 网络配置

$
0
0

我们使用 Xen 虚拟机的时候一般都是用桥接(bridging)的方式把虚拟机(domU)直接暴露在网络上,就像网络上单独的一台服务器一样,这种方式简单好用,不用在 dom0 做任何的端口转发也不用任何 iptable 规则。不过除了 bridging 以外,Xen 还支持 routing 和 NAT 的方式配置虚拟机网络。比如我们想在一台物理服务器上安装5个虚拟机,这5个虚拟机能彼此访问也可以访问外网,但是外网不能直接访问这5个虚拟机,或者我们只有一个公网 IP 地址,但是需要5个虚拟机都能上网,这时候就可以用到 Xen 的 NAT 模式。

首先确认系统的网络配置干净,上面没有复杂的网络设置,也没有以前配置留下来的网络桥接,因为 Xen 自带的脚本 network-nat 不是那么聪明,无法在复杂一点的网络设置里面正确配置。

修改 Xen 的配置文件,确认下面几项配置后重启 xend,必要的话重启系统:

# vi /etc/xen/xend-config.sxp
...
#(network-script network-bridge)
(network-script network-nat)
...
#(vif-script vif-bridge)
#(vif-script     vif-route)
(vif-script     vif-nat)
...

# /etc/init.d/xend restart
Stopping xend daemon:                                      [  OK  ]
Starting xend daemon:                                      [  OK  ]

修改虚拟机 domU 的配置文件,加上或者修改 vif 这行配上对应的内部网 IP 地址,这个内部网 IP 是自己随意设定的:

# vi /etc/xen/domu01
...
vif = [ "ip=10.0.0.1" ]
...

启动虚拟机后修改网络配置,如果虚拟机是 Ubuntu 的话,网络配置在 /etc/network/interfaces,修改后重启:

# vi /etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
address 10.0.0.1
gateway 10.0.0.254
netmask 255.255.255.0

# reboot

本来还需要在 dom0 设定内核转发的(echo 1 > /proc/sys/net/ipv4/ip_forward),还记得上面修改 xend-config.sxp 时碰到的脚本 network-nat 吗?是的,那个脚本已经帮我们设置好 NAT 转发了,我们不用再添足了,也不用自己设置 iptable 规则了~

# vi /etc/xen/scripts/network-nat
...
op_start() {
        echo 1 >/proc/sys/net/ipv4/ip_forward
        iptables -t nat -A POSTROUTING -o ${netdev} -j MASQUERADE
        [ "$dhcp" != 'no' ] && dhcp_start
}
...

mysql主从复制

$
0
0


从库的配置,mysql5.5不支持配置文件的配置了,问了数据库的人,用命令行指定

如下

参考
http://hi.baidu.com/hero0524/item/5280630bbf0ad7eb3599028f


修改从库的配置
#default-storage-engine = InnoDB
#修改
default-storage-engine = blackhole

server-id = 11215004
#新增
replicate-do-db = test

log-bin = mysql-bin
#新增
binlog_format = row

★★★★★★★★★★★★★★★★★
在主库
show master status
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 | 2615 | | | 
+------------------+----------+--------------+------------------+

记录master_log_file和master_log_pos
在从库 ,
5004:
change master to
master_host='10.73.11.21',master_user='databus',master_password='databus', master_port=5000, master_log_file='mysql-bin.000001',master_log_pos=2615;

5005:
change master to master_host='10.73.11.21',master_user='databus',master_password='databus', master_port=5001, master_log_file='mysql-bin.000003',master_log_pos=389;
5006:
change master to master_host='10.73.11.21',master_user='databus',master_password='databus', master_port=5002, master_log_file='mysql-bin.000003',master_log_pos=389;
5007:
change master to master_host='10.73.11.21',master_user='databus',master_password='databus', master_port=5003, master_log_file='mysql-bin.000003',master_log_pos=389;

start slave;

show slave status\G;

注意一定要是
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

查看Relay_Log_File: relay-bin.000002
在slave目录 tailf relay-bin.000002

在主库
CREATE TABLE test(i INT, c CHAR(10));
INSERT INTO test VALUES(1,'record one1111'),(2,'record 11111');

观察从库的log

★★★★★★★★★★


已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



来看看美国青少年是如何使用手机的

$
0
0

最受中学生欢迎的社交网络、应用和网站是什么?据市场研究公司Niche在7000多名中学生中进行的一项调查显示,用户最活跃的社交网络是Instagram,每日用户数量最多的是Facebook,使用最广泛的是YouTube。

来看看美国青少年是如何使用手机的

来看看美国青少年是如何使用手机的

然而每天使用率最高的应用或网站却是短信息。中学生每天使用短信息的次数几乎是他们打电话的次数的3倍。

来看看美国青少年是如何使用手机的

上周,PayPal总裁大卫马克斯(David Marcus)跳槽去Facebook担任短讯团队的主管。业内人士猜测,这或许暗示着Facebook Messaging将成为一个在用户间发送资金的商业网络。

这样解读马克斯的跳槽行为或许太简单了,短讯是一个无所不包的网络。它与身份有关,它与社交有关,它与目的有关,它还跟地理位置有关。它是最纯粹的社交网络,我们甚至都不愿将这种单纯的社交工具看作是一个网络。

调查还发现,Pandora很少会象技术作者所关注的其他应用那样成为用户关注的焦点。这或许是因为Pandora总是待在幕后,或者说充当其他行为的背景。

实际上,使用Pandora的青少年用户比使用Instagram、Snapchat、iTunes或Netflix的青少年用户更多。从第二张图可以看出,在每日使用量上面,Pandora虽然不如Instagram和Snapchat。但仍然超过了Twitter、电话和iTunes。

有人或许会说这是因为青少年喜欢听音乐,但是这种做法仍然解释不了为什么Pandora的每日用户数量几乎是Spotify的4倍,是Beats的5倍,是Rdio的6倍多,因为后面三款应用或服务也都能为用户提供音乐内容。

这项调查的结果还可以说明为什么数字出版商会特别青睐Facebook和其他的社交媒体,因为即便是最受青少年欢迎的网站BuzzFeed在每日访客数量上也远远低于任何社交网络或应用。

调查显示,73%的青少年从不看BuzzFeed,84%的青少年从不看Reddit,96%的青少年从不看Mashable。对于青少年来说,Facebook就是看新闻和了解天下大事的地方。

由于消费者关注的焦点已经从网页转移到各种移动应用上,因此数字出版商目前面临的最重要的挑战就是让它们的内容能够共享。

Viewing all 15843 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>