2016年12月

编者注:本文是 2016 年 4 月 Nicole Whilte 在欧洲 GraphConnect 时所作。这儿我们快速回顾一下她所涉及的内容:

  • 图数据库推荐基础
  • 社会化推荐
  • 相似性推荐
  • 集群推荐

今天我们将要讨论的内容是数据科学和 图推荐 graph recommendations

我在 Neo4j 任职已经两年了,但实际上我已经使用 Neo4j 和 Cypher 工作三年了。当我首次发现这个特别的 图数据库 graph database 的时候,我还是一个研究生,那时候我在奥斯丁的德克萨斯大学攻读关于社交网络的统计学硕士学位。

实时推荐引擎是 Neo4j 中最广泛的用途之一,也是使它如此强大并且容易使用的原因之一。为了探索这个东西,我将通过使用示例数据集来阐述如何将统计学方法并入这些引擎中。

第一个很简单 - 将 Cypher 用于社交推荐。接下来,我们将看一看相似性推荐,这涉及到可被计算的相似性度量,最后探索的是集群推荐。

图数据库推荐基础

下面的数据集包含所有达拉斯 Fort Worth 国际机场的餐饮场所,达拉斯 Fort Worth 国际机场是美国主要的机场枢纽之一:

我们把节点标记成黄色并按照出入口和航站楼给它们的位置建模。同时我们也按照食物和饮料的主类别将地点分类,其中一些包括墨西哥食物、三明治、酒吧和烤肉。

让我们做一个简单的推荐。我们想要在机场的某一确定地点找到一种特定食物,大括号中的内容表示是的用户输入,它将进入我们的假想应用程序中。

这个英文句子表示成 Cypher 查询:

这将提取出该类别中用户所请求的所有地点、航站楼和出入口。然后我们可以计算出用户所在位置到出入口的准确距离,并以升序返回结果。再次说明,这个非常简单的 Cypher 推荐仅仅依据的是用户在机场中的位置。

社交推荐 Social Recommendations

让我们来看一下社交推荐。在我们的假想应用程序中,用户可以登录并且可以用和 Facebook 类似的方式标记自己“喜好”的地点,也可以在某地签到。

考虑位于我们所研究的第一个模型之上的数据模型,现在让我们在下面的分类中找到用户的朋友喜好的航站楼里面离出入口最近的餐饮场所:

MATCH 子句和我们第一次 Cypher 查询的 MATCH 子句相似,只是现在我们依据喜好和朋友来匹配:

前三行是完全一样的,但是现在要考虑的是那些登录的用户,我们想要通过 :FRIENDS_WITH 这一关系来找到他们的朋友。仅需通过在 Cypher 中增加一些行内容,我们现在已经把社交层面考虑到了我们的推荐引擎中。

再次说明,我们仅仅显示了用户明确请求的类别,并且这些类别中的地点与用户进入的地方是相同的航站楼。当然,我们希望按照登录并做出请求的用户来滤过这些目录,然后返回地点的名字、位置以及所在目录。我们也要显示出有多少朋友已经“喜好”那个地点以及那个地点到出入口的确切距离,然后在 RETURN 子句中同时返回所有这些内容。

相似性推荐 Similarity Recommendations

现在,让我们看一看相似性推荐引擎:

和前面的数据模型相似,用户可以标记“喜好”的地点,但是这一次他们可以用 1 到 10 的整数给地点评分。这是通过前期在 Neo4j 中增加一些属性到关系中建模实现的。

这将允许我们找到其他相似的用户,比如以上面的 Greta 和 Alice 为例,我们已经查询了他们共同喜好的地点,并且对于每一个地点,我们可以看到他们所设定的权重。大概地,我们可以通过他们的评分来确定他们之间的相似性大小。

现在我们有两个向量:

现在让我们按照 欧几里得距离 Euclidean distance 的定义来计算这两个向量之间的距离:

我们把所有的数字带入公式中计算,然后得到下面的相似度,这就是两个用户之间的“距离”:

你可以很容易地在 Cypher 中计算两个特定用户的“距离”,特别是如果他们仅仅同时“喜好”一个很小的地点子集。再次说明,这儿我们依据两个用户 Alice 和 Greta 来进行匹配,并尝试去找到他们同时“喜好”的地点:

他们都有对最后找到的地点的 :LIKES 关系,然后我们可以在 Cypher 中很容易的计算出他们之间的欧几里得距离,计算方法为他们对各个地点评分差的平方求和再开平方根。

在两个特定用户的例子中上面这个方法或许能够工作。但是,在实时情况下,当你想要通过和实时数据库中的其他用户比较,从而由一架飞机上的一个用户推断相似用户时,这个方法就不一定能够工作。不用说,至少它不能够很好的工作。

为了找到解决这个问题的好方法,我们可以预先计算好距离并存入实际关系中:

当遇到一个很大的数据集时,我们需要成批处理这件事,在这个很小的示例数据集中,我们可以按照所有用户的 迪卡尔乘积 Cartesian product 和他们共同“喜好”的地点来进行匹配。当我们使用 WHERE id(u1) < id(u2) 作为 Cypher 询问的一部分时,它只是来确定我们在左边和右边没有找到相同的对的一个技巧。

通过用户之间的欧几里得距离,我们创建了他们之间的一种关系,叫做 :DISTANCE,并且设置了一个叫做 euclidean 的欧几里得属性。理论上,我们可以也通过用户间的一些关系来存储其他相似度从而获取不同的相似度,因为在确定的环境下某些相似度可能比其他相似度更有用。

在 Neo4j 中,的确是对关系属性建模的能力使得完成像这样的事情无比简单。然而,实际上,你不会希望存储每一个可能存在的单一关系,因为你仅仅希望返回离他们“最近”的一些人。

因此你可以根据一些临界值来存入前几个,从而你不需要构建完整的连通图。这允许你完成一些像下面这样的实时的数据库查询,因为我们已经预先计算好了“距离”并存储在了关系中,在 Cypher 中,我们能够很快的攫取出数据。

在这个查询中,我们依据地点和类别来进行匹配:

再次说明,前三行是相同的,除了登录用户以外,我们找出了和他们有 :DISTANCE 关系的用户。这是我们前面查看的关系产生的作用 - 实际上,你只需要存储处于前几位的相似用户 :DISTANCE 关系,因此你不需要在 MATCH 子句中攫取大量用户。相反,我们只攫取和那些用户“喜好”的地方有 :DISTANCE 关系的用户。

这允许我们用少许几行内容表达较为复杂的模型。我们也可以攫取 :LIKES 关系并把它放入到变量中,因为后面我们将使用这些权重来评分。

在这儿重要的是,我们可以依据“距离”大小将用户按照升序进行排序,因为这是一个距离测度。同时,我们想要找到用户间的最小距离因为距离越小表明他们的相似度最大。

通过其他按照欧几里得距离大小排序好的用户,我们得到用户评分最高的三个地点并按照用户的平均评分高低来推荐这些地点。换句话说,我们先找出一个活跃用户,然后依据其他用户“喜好”的地点找出和他最相似的其他用户,接下来按照这些相似用户的平均评分把那些地点排序在结果的集合中。

本质上,我们通过把所有评分相加然后除以收集的用户数目来计算出平均分,然后按照平均评分的升序进行排序。其次,我们按照出入口距离排序。假想地,我猜测应该会有交接点,因此你可以按照出入口距离排序然后再返回名字、类别、出入口和航站楼。

集群推荐 Cluster Recommendations

我们最后要讲的一个例子是集群推荐,在 Cypher 中,这可以被想像成一个作为临时解决方案的离线计算工作流。这可能完全基于在欧洲 GraphConnect 上宣布的新方法,但是有时你必须进行一些 Cypher 2.3 版本所没有的算法逼近。

在这儿你可以使用一些统计软件,把数据从 Neo4j 取出然后放入像 Apache Spark、R 或者 Python 这样的软件中。下面是一段把数据从 Neo4j 中取出的 R 代码,运行该程序,如果正确,写下程序返回结果的给 Neo4j,可以是一个属性、节点、关系或者一个新的标签。

通过持续把程序运行结果放入到图表中,你可以在一个和我们刚刚看到的查询相似的实时查询中使用它:

下面是用 R 来完成这件事的一些示例代码,但是你可以使用任何你最喜欢的软件来做这件事,比如 Python 或 Spark。你需要做的只是登录并连接到图表。

在下面的例子中,我基于用户的相似性把他们聚合起来。每个用户作为一个观察点,然后得到他们对每一个目录评分的平均值。

假定用户对酒吧类评分的方式和一般的评分方式相似。然后我攫取出喜欢相同类别中的地点的用户名、类别名、“喜好”关系的平均权重,比如平均权重这些信息,从而我可以得到下面这样一个表格:

因为我们把每一个用户都作为一个观察点,所以我们必须巧妙的处理每一个类别中的数据,这些数据的每一个特性都是用户对该类中餐厅评分的平均权重。接下来,我们将使用这些数据来确定用户的相似性,然后我将使用 聚类 clustering 算法来确定在不同集群中的用户。

在 R 中这很直接:

在这个示例中我们使用 K-均值 k-means 聚类算法,这将使你很容易攫取集群分配。总之,我通过运行聚类算法然后分别得到每一个用户的集群分配。

Bob 和 David 在一个相同的集群中 - 他们在集群二中 - 现在我可以实时查看哪些用户被放在了相同的集群中。

接下来我把集群分配写入 CSV 文件中,然后存入图数据库:

我们只有用户和集群分配,因此 CSV 文件只有两列。 LOAD CSV 是 Cypher 中的内建语法,它允许你从一些其他文件路径或者 URL 调用 CSV ,并给它一个别名。接下来,我们将匹配图数据库中存在的用户,从 CSV 文件中攫取用户列然后合并到集群中。

我们在图表中创建了一个新的标签节点:Cluster ID, 这是由 K-平均聚类算法给出的。接下来我们创建用户和集群间的关系,通过创建这个关系,当我们想要找到在相同集群中的实际推荐用户时,就会很容易进行查询。

我们现在有了一个新的集群标签,在相同集群中的用户和那个集群存在关系。新的数据模型看起来像下面这样,它比我们前面探索的其他数据模型要更好:

现在让我们考虑下面的查询:

通过这个 Cypher 查询,我们在更远处找到了在同一个集群中的相似用户。由于这个原因,我们删除了“距离”关系:

在这个查询中,我们取出已经登录的用户,根据用户-集群关系找到他们所在的集群,找到他们附近和他们在相同集群中的用户。

我们把这些用户分配到变量 c1 中,然后我们得到其他被我取别名为 neighbor 变量的用户,这些用户和那个相同集群存在着用户-集群关系,最后我们得到这些附近用户“喜好”的地点。再次说明,我把“喜好”放入了变量 r 中,因为我们需要从关系中攫取权重来对结果进行排序。

在这个查询中,我们所做的改变是,不使用相似性距离,而是攫取在相同集群中的用户,然后对类别、航站楼以及我们所攫取的登录用户进行声明。我们收集所有的权重:来自附近用户“喜好”地点的“喜好”关系,得到的类别,确定的距离值,然后把它们按升序进行排序并返回结果。

在这些例子中,我们可以进行一个相当复杂的处理并且将其放到图数据库中,然后我们就可以使用实时算法结果-聚类算法和集群分配的结果。

我们更喜欢的工作流程是更新这些集群分配,更新频率适合你自己就可以,比如每晚一次或每小时一次。当然,你可以根据直觉来决定多久更新一次这些集群分配是可接受的。


via: https://neo4j.com/blog/real-time-recommendation-engine-data-science/

作者:Nicole White 译者:ucasFL 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

不知道多少次了,我在微信公众号后台收到询问“你们的微信文章版式是怎么做的”等问题了。其实,我本来觉得这没什么值得问的,也不值得保密,但是总是有人问,我觉得还是写一篇小文来介绍一下吧,下次有人问我,我就直接丢链接好了~

我本身不是做美工和 UI/UE 出身的,但是我们的(前)联合创始人 DeadFire 是专门做这个的,奈何他再也不可能为 Linux 中国做任何的 UE 调整了,/cry。不过我们的 UE 在他的努力之下,目前还算不错,也仅以这些样式来纪念他吧。

下面我来说说我们的微信文章版式的几个算是亮点的地方吧。

先说一个前提,Linux 中国的文章都是通过自身网站的 CMS 进行编辑的,并没有使用外部的那些第三方的微信编辑器。因此,如果你有一个可以编辑内容并形成网页的 CMS,那么以下技巧可能就比较适合你使用;如果你没有 CMS ,理论上说你手工编辑 HTML 页面也是可以的;或者,其实你可以复制我们的文章的格式到一个可视化 HTML 编辑器中,修改内容也可以。

1、代码高亮

作为技术网站,刊载的文章中出现代码是必不可少的,之前我们也用过一些代码高亮插件,但是因一些不足后来就放弃了。

目前我们使用的代码高亮插件是 Google 的 code-prettify,最初它是放在 Google Code 上的,现在也托管到了 GitHub: https://github.com/google/code-prettify

code-prettify 的优点是体积小,使用简单,而且自动识别所高亮的语言(虽然有时候识别的不对,但是其实没几个人真的在意对不对,大致能区分不同的语言成分就好了)。目前这个软件已经有比较长的时间不更新了,虽然还有 bug,不过大致上的功能没有什么问题。

使用方法很简单,首先你得在页面中引入 code-prettify 的 js 文件,然后在你要高亮代码外使用 <pre class="prettyprint">...</pre><code class="prettyprint">...</code> 标签即可。比如:

<script src="run_prettify.js"></script>
<pre class="prettyprint">class Voila {
public:
  // Voila
  static const string VOILA = "Voila";
}</pre>

然后看起来效果就是:

class Voila {
public:
  // Voila
  static const string VOILA = "Voila";
}

可能你使用了 code-prettify 之后也发现和我们的代码样式不同,其实,这只是我们使用了自己定制的一个 CSS 样式罢了,稍微研究下我们的页面代码,你就能找到这个 CSS 的,你可以根据你的喜好进行修改。

当你做好了一个可以在浏览器中满意呈现的页面之后,你只需要复制该页面内容,贴到你的微信后台的编辑器中即可。

2、英文注释标签

我们经常会发布各种英文文章的译文,但是有时候,一些词汇需要附上英文才能比较好的避免歧义。通常大家的做法都是在中文后面用括号圈上对应的英文,但是随着 HTML5 规范的普遍支持,其实还有另外一种新的标签可以更好的用于这种情况。那就是 RUBY 标签。

RUBY 是振假名的意思,用于在 HTML 中标注注音。各个浏览器对 RUBY 标签的支持程度不同,不过最基本的用法都是支持的,包括微信内的浏览器。

简单的来说,RUBY 标签的基本格式如下:<ruby>这里写中文<rt>English here<rt><ruby>,这个标签用浏览器看的效果是这样的: 这里写中文 English here

当然,实际上 RUBY 标签还许多子标签和不同的格式变体,但是一方面各个浏览器支持效果不同,另外一方面对微信浏览器而言仅支持这种基本格式。需要深入研究的同学可以自行搜索。

目前应该还没有支持 RUBY 的 CMS,所以,一般情况下你需要手工编辑你的页面的 HTML 来插入这种标签——当然,我是自己开发了一个我的 CMS 的插件。

此外, RUBY 标签也是可以嵌入链接的,这种情况也比较常见。你可以自行摸索下。

最后,RUBY 标签自然有默认的显示样式,显然,作为在意用户体验的你,肯定会给它单独调整下 CSS 的,是吧?

3、其它

实际上,除了以上两点,我们并没有特别不同的地方,不过用户体验的细节还是有所调整的,但是这些就是见仁见智的地方了,大家可以根据需要参考我们或其它一些在页面体验方面有所特长的页面进行学习。

除此以外,做了几年的微信文章发布,我还有一点点小经验可以分享给大家:

  • 不建议调整正文字号,就用默认的 16px 即可,虽然看起来比较大——但是现在移动设备分辨率越来越高了,所以较小的字号可能会让部分用户看起来比较累。当然,也可以考虑使用 14px,如果你的文章不全是密密麻麻的字的话。
  • 正文文字的颜色不要出现太多,除了黑色以外,最多有两种为宜。此外,在特殊情况下,你还可以考虑使用加粗,甚至斜体效果。
  • 中英文混排时,以及掺杂数字时,尽量在英文单词与汉字之间加个空格,关于这方面,网上有篇《中文排版指北》,会有更详细的建议,不过我认为最重要、最基本的就是这条了。
  • 文内配图,如果有可能尽量尺寸一致,最少要考虑保证图片宽度一致比较好。配图下方,必要时可以用另外一种文字样式来做图片说明。比如我们就是用斜体、灰色、下划线样式的字体作为图片说明。模糊的配图不要也罢,除非必要,用动图会显得很 low——有些老网友或许还记得 20 年前的网页上的那种 GIF 动画展览吧?
  • 题图,如果你的标题不够好,那就选张好的题图吧,如果你能有一张切题的壁纸级题图,那显然会让你的公众号订阅者更高兴一些——如果细心的话,或许你可以放上这张壁纸级题图的高分辨率原图的 URL 地址?
  • 微信后台的文章编辑器对很多 HTML 标签是不支持的,比如 DIV。所以,大家如果采用 div 布局的话,会发现桌面浏览器上看的好好的样式,复制到微信后台的编辑器中会变得惨不忍睹。这种情况下,你可以考虑用一些新的块级元素,比如 SECTION
  • 链接,微信文章仅在一些特定的情况下支持文内链接,所以,对于大部分公众号的微信文章来说,都是没办法在文内加上链接的。但是作为 Web 世界,有时候明明有链接的地方你不提供链接,你可以想象读者的怒火。这时候,我们有两种方式可以稍微补救。

    1. 对链接的文字加上特定样式(如加上下划线),以暗示此处有链接,然后在后面加个上标,比如 [1],并在文末单独对这个上标提供链接,这样需要的读者可以复制该链接访问。不过要注意的是,微信文章不支持 SUP 标签,你可以用 SPAN 标签来达成类似效果。
    2. 如果文内链接不多,链接本身也不算长,你可以用括号圈起来写上链接,不过如果链接太多,也太长时,这会影响正文阅读效果的。其实这两种方式都是仿照纸质书籍这种无法做到超链接的出版物的。
  • 对于长文章,你应该考虑在文内提供不同层次的大小标题。如果有可能,你还应该在页首提供一个目录、摘要等信息。当然,我们使用了 CMS,这种信息是自动提取生成的,可能要方便一些。

好了,大致我就总结这些,希望对大家有所帮助,如果有什么问题,请留言讨论,也欢迎大家分享自己的经验。

(题图来自:picswalls.com

我们对微服务的需求可以归纳为一个词:速度。这种更快提供功能完善且可靠的软件的需求,彻底改变了软件开发模式。毫无疑问,这个改变对软件管理,包括系统监控的方式,都产生了影响。在这篇文章里,我们将重点关注放在有效地监控产品环境中的微服务所需做出的主要改变。我们将为这一新的软件架构拟定 5 条指导性原则来调整你的监控方法。

监控是微服务控制系统的关键部分,你的软件越复杂,那么你就越难了解其性能及问题排障。鉴于软件交付发生的巨大改变,监控系统同样需要进行彻底的改造,以便在微服务环境下表现更好。下面我们将介绍监控微服务的 5 条原则,如下:

  1. 监控容器及其里面的东西。
  2. 在服务性能上做监控,而不是容器性能。
  3. 监控弹性和多地部署的服务。
  4. 监控 API。
  5. 将您的监控映射到您的组织结构。

利用这 5 条原则,你可以在向微服务前进的道路上,建立更有效的对微服务的监控。这些原则,可以让你应对随着微服务而来的技术变化和组织变化。

微服务监控的原则

1、监控容器及其里面的东西

容器因构建微服务而凸显其重要性,容器的速度、可移植性和隔离特性让开发者很容易就爱上了微服务模型。容器的好处已经写的够多了,毋庸赘述。

容器对于其外围的系统来说就像是黑盒子。这对于开发来说大有裨益,从开发环境到生产环境,甚至从开发者的笔记本到云端,为它们带来高度的可移植性。但是当运行起来后,监控和解决服务问题时,这个黑盒子让常规的方法难以奏效了,我们会想:容器里到底在运行着什么?程序和代码运行性能如何?它有什么重要的输出指标吗?从 DevOps 的视角,你需要对容器有更深的了解而不是仅仅知道有一些容器的存在。

非容器环境下衡量的典型做法,是让一个代理程序运行在主机或者虚机上的用户空间里,但这并不适用于容器。因为容器的优点是小,将各种进程分离开来,并尽可能的减少依赖关系。

而且,从规模上看,成千上万的监测代理,对即使是一个中等大小的部署都是一个昂贵的资源浪费和管理的噩梦。对于容器有两个潜在的解决方案:1)要求你的开发人员直接监控他们的代码,或者2)利用一个通用的内核级的检测方法来查看主机上的所有应用程序和容器活动。这里我们不会深入说明,但每一种方法都有其优点和缺点。

2、 利用业务流程系统提醒服务性能

理解容器容器中的运行数据并不容易,一个单一容器相比组成一个功能或服务的容器聚合,测量复杂度要低得多。

这特别适用于应用程序级别的信息,比如哪个请求拥有最短响应时间,或者哪些 URL 遇到最多的错误,但它同样也适用于架构级别的监测,比如哪个服务的容器使用 CPU 资源超过了事先分配的资源数。

越来越多的软件部署需要一个 编排系统 orchestration system ,将应用程序的逻辑规划转化到物理的容器中。常见的编排系统包括 Kubernetes、Mesosphere DC/OS 和 Docker Swarm。团队可以用一个编排系统来(1)定义微服务(2)理解部署的每个服务的当前状态。你可以认为编排系统甚至比容器还重要。容器是短暂的,只有满足你的服务需求才会存在。

DevOps 团队应该将告警重点放到运行特征上,以尽可能贴近监控服务的体验。如果应用受到了影响,这些告警是评估事态的第一道防线。但是获得这些告警并不容易,除非你的监控系统是基于原生于容器的。

原生容器 Container-native 解决方案利用 编排元数据 orchestration metadata 来动态聚合容器和应用程序数据,并按每个服务计算监控度量。根据您的编排工具,您可能想在不同层次进行深入检测。比如,在 Kubernetes 里,你通常有 Namespace、ReplicaSet、Pod 和一些其他容器。聚合这些不同的层,对排除逻辑故障是很有必要的,与构成服务的容器的物理部署无关。

3、 监控 弹性 Elastic 多地部署 Multi-Location 的服务

弹性服务不是一个新概念,但是它在原生容器环境中的变化速度比在虚拟环境中快的多。迅速的变化会严重影响检测系统的正常运行。

监测传统的系统经常需要根据软件部署,手动调整检查指标。这种调整可以是具体的,如定义要捕获的单个指标,或基于应用程序在一个特定的容器中的操作配置要收集的数据。在小规模上(比如几十个容器)我们可以接受,但是再大规模就难以承受了。微服务的集中监控必须能够自由的随弹性服务而增长和缩减,无需人工干预。

比如,如果 DevOps 团队必须手动定义容器包含哪个服务需要监控,他们毫无疑问会失手,因为 Kubernetes 或者 Mesos 每天都会定期创建新的容器。同样,如果代码发布并置于生产环境时要求运维团队安装一个 定制的状态端点 custom stats endpoint ,也给开发者从 Docker 仓库获取基础镜像带来更多的挑战。

在生产环境中,建立面向跨越多个数据中心或多个云的复杂部署的监控,比如,如果你的服务跨越私有数据中心和 AWS,那么亚马逊的 AWS CloudWatch 就很难做到这一点。这就要求我们建立一个跨不同地域的监控系统,并可在动态的原生容器环境下运行。

4、 监控 API

在微服务环境中,API 接口是通用的。本质上,它们是将服务暴露给其它团队的唯一组件。事实上,API 的响应和一致性可以看作是“内部 SLA”,即使还没有定义一个正式的 SLA(服务等级协议)。

因此,API 接口的监控也是必要的。API 监控可以有不同的形式,但是很显然它绝对不是简单的二进制上下检查。例如,了解像时间函数这样的最常使用的 端点 endpoint 是有价值的。这使得团队可以看到服务使用的变化,无论是由于设计变更或用户的改变。

你也可以记录服务最缓慢的端点,这些可能揭示出重大的问题,或者至少指向需要在系统中做优化的区域。

最后,跟踪系统服务响应的能力是另一个很重要的能力,它主要是开发者使用,也能帮助你了解整体用户体验,同时将信息基于底层和应用程序视角分成两大部分。

5、 将您的监控映射到您的组织结构

这篇文章着重在微服务和监控上,像其他科技文章一样,这是因为很多人都关注此层面。

对于那些熟悉 康威定律 Conway’s law 的人来说,系统的设计是基于开发团队的组织结构。创造更快,更敏捷的软件的压力推动了团队去思考重新调整他们的开发组织和管理它的规则。

所以,如果他们想从这个新的软件架构(微服务)上获益,他们的团队必须将微服务映射到团队自身中。也就是说,他们需要更小的更松散耦合的团队,可以选择自己的方向只要能够满足整个需求即可。在每一个团队中,对于开发语言的使用,bug 的提交甚至工作职责都会有更大的控制能力。

DevOps 团队对此可以启用一个监控平台:让每一个微服务团队可以有自己的警报,度量指标,和控制面板,同时也要给出整体系统的视图。

总结

让微服务流行起来的是快捷。开发组织要想更快的为客户提供更多的功能,然后微服务技术就来了,架构转向微服务并且容器的流行让快捷开发成为可能,所有相关的进程理所当然的搭上了这辆火车。

最后,基本的监控原则需要适应伴随微服务而来的技术和结构。越早认识到这种转变的开发团队,能更早更容易的适应微服务这一新的架构。


via: http://thenewstack.io/five-principles-monitoring-microservices/

作者:Apurva DaveLoris Degioanni 译者:jiajia9linuxer 校对:jasminepeng

本文由 LCTT 原创编译,Linux中国 荣誉推出

塞尔维亚共和国诺维萨德大学的自然科学系和数学与信息学系,我们教学生很多东西。从编程语言的入门到机器学习,所有开设的课程最终目的是让我们的学生能够像专业的开发者和软件工程师一样思考。课程时间紧凑而且学生众多,所以我们必须对现有可利用的资源进行合理调整以满足正常的教学。最终我们决定将机房计算机系统换为 Fedora。

以前的设置

我们过去的解决方案是在 Ubuntu 系统上面安装 Windows 虚拟机并在虚拟机下安装好教学所需的开发软件。这在当时看起来是一个很不错的主意。然而,这种方法有很多弊端。首先,运行虚拟机导致了严重的计算机性能的浪费,因此导致操作系统性能和运行速度降低。此外,虚拟机有时候会在另一个用户会话里面同时运行。这会导致计算机工作严重缓慢。我们不得不在启动电脑和启动虚拟机上花费宝贵的时间。最后,我们意识到我们的大部分教学所需软件都有对应的 Linux 版本。虚拟机不是必需的。我们需要寻找一个更好的解决办法。

进入 Fedora!

Computer lab in Serbia powered by Fedora

默认运行 Fedora 工作站版本的一个机房的照片

我们考虑使用一种简洁的安装替代以前的 Windows 虚拟机方案。我们最终决定使用 Fedora,这有很多原因。

发展的前沿

在我们所教授的课程中,我们会用到很多各种各样的开发工具。因此,能够及时获取可用的最新、最好的开发工具很重要。在 Fedora 下,我们发现我们用到的开发工具有 95% 都能够在官方的软件仓库中找到!只有少量的一些工具,我们才需要手动安装。这在 Fedora 下很简单,因为你能获取到几乎所有的现成的开发工具。

在这个过程中我们意识到我们使用了大量自由、开源的软件和工具。保证这些软件总是能够及时更新通常需要做大量的工作,然而 Fedora 没有这个问题。

硬件兼容性

我们机房选择 Fedora 的第二个原因是硬件兼容性。机房现在的电脑还是比较崭新的。过去比较低的内核版本总有些问题。在 Fedora 下,我们总能获得最新的内核版本。正如我们预期的那样,一切运行良好,没有任何问题。

我们决定使用带有 GNOME 桌面环境的 Fedora 工作站版本。学生们发现它很容易、直观,可以快速上手。对我们来说,学生有一个简单的环境很重要,这样他们会更多的关注自己的任务和课程本身,而不是一个复杂的或者运行缓慢的用户界面。

自主的技术支持

最后一个原因,我们院系高度赞赏自由、开放源代码的软件。使用这些软件,学生们即便在毕业后和工作的时候,仍然能够继续自由地使用它们。在这个过程中,他们通常也对 Fedora 和自由、开源的软件有了一定了解。

转换机房

我们找来其中的一台电脑,完全手动安装好。包括准备所有必要的脚本和软件,设置远程控制权限和一些其他的重要组成部分。我们也为每一门课程单独设置一个用户账号以方便学生存储他们的文件。

一台电脑安装配置好后,我们使用一个强大的、免费的、开源的叫做 CloneZilla 的工具。 CloneZilla 能够制作硬盘镜像以做恢复用。镜像大小约为 11 G。我们用一些带有高速 USB 3.0 接口的闪存来还原磁盘镜像到其余的电脑。我们仅仅利用若干个闪存设备花费了 75 分钟设置好其余的 24 台电脑。

将来的工作

我们机房现在所有的电脑都完全使用 Fedora (没有虚拟机)。剩下的工作是设置一些管理脚本方便远程安装软件,电脑的开关等等。

我们由衷地感谢所有 Fedora 的维护人员、软件包管理人员和其他贡献者。我们希望我们的工作能够鼓励其他的学校和大学像我们一样将机房电脑的操作系统转向 Fedora。我们很高兴地确认 Fedora 完全适合我们,同时我们也保证 Fedora 同样会适合您!


via: https://fedoramagazine.org/fedora-computer-lab-university/

作者:Nemanja Milošević 译者:WangYueScreamLemonDemo 校对:jasminepeng

本文由 LCTT 原创编译,Linux中国 荣誉推出

gcc 编译器提供了几乎数不清的命令行选项列表。当然,没有人会使用过或者精通它所有的命令行选项,但是有一些命令行选项是每一个 gcc 用户都应该知道的 - 即使不是必须知道。它们中有一些很常用,其他一些不太常用,但不常用并不意味着它们的用处没前者大。

在这个系列的文章中,我们集中于一些不常用但是很有用的 gcc 命令行选项,在第一节已经讲到几个这样的命令行选项。

不知道你是否能够回想起,在这个系列教程的第一部分的开始,我简要的提到了开发者们通常用来生成警告的 -Wall 选项,并不包括一些特殊的警告。如果你不了解这些特殊警告,并且不知道如何生成它们,不用担心,我将在这篇文章中详细讲解关于它们所有的细节。

除此以外,这篇文章也将涉及与浮点值相关的 gcc 警告选项,以及在 gcc 命令行选项列表变得很大的时候如何更好的管理它们。

在继续之前,请记住,这个教程中的所有例子、命令和指令都已在 Ubuntu 16.04 LTS 操作系统和 gcc 5.4.0 上测试过。

生成 -Wall 选项不包括的警告

尽管 gcc 编译器的 -Wall 选项涵盖了绝大多数警告标记,依然有一些警告不能生成。为了生成它们,请使用 -Wextra 选项。

比如,下面的代码:

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int i=0;
    /* ...
       some code here 
       ...
    */

    if(i);
        return 1;
     return 0; 
}

我不小心在 if 条件后面多打了一个分号。现在,如果使用下面的 gcc 命令来进行编译,不会生成任何警告。

gcc -Wall test.c -o test

但是如果同时使用 -Wextra 选项来进行编译:

gcc -Wall -Wextra test.c -o test

会生成下面这样一个警告:

test.c: In function ‘main’:
test.c:10:8: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body]
 if(i);

从上面的警告清楚的看到, -Wextra 选项从内部启用了 -Wempty-body 选项,从而可以检测可疑代码并生成警告。下面是这个选项启用的全部警告标记。

  • -Wclobbered
  • -Wempty-body
  • -Wignored-qualifiers
  • -Wmissing-field-initializers
  • -Wmissing-parameter-type (仅针对 C 语言)
  • -Wold-style-declaration (仅针对 C 语言)
  • -Woverride-init
  • -Wsign-compare
  • -Wtype-limits
  • -Wuninitialized
  • -Wunused-parameter (只有和 -Wunused-Wall 选项使用时才会启用)
  • -Wunused-but-set-parameter (只有和-Wunused-Wall` 选项使用时才会生成)

如果想对上面所提到的标记有更进一步的了解,请查看 gcc 手册

此外,遇到下面这些情况, -Wextra 选项也会生成警告:

  • 一个指针和整数 0 进行 <<=>, 或 >= 比较
  • (仅 C++)一个枚举类型和一个非枚举类型同时出现在一个条件表达式中
  • (仅 C++)有歧义的虚拟基底
  • (仅 C++)寄存器类型的数组加下标
  • (仅 C++)对寄存器类型的变量进行取址
  • (仅 C++)基类没有在派生类的复制构建函数中进行初始化

浮点值的等值比较时生成警告

你可能已经知道,浮点值不能进行确切的相等比较(如果不知道,请阅读与浮点值比较相关的 FAQ)。但是如果你不小心这样做了, gcc 编译器是否会报出错误或警告?让我们来测试一下:

下面是一段使用 == 运算符进行浮点值比较的代码:

#include<stdio.h>

void compare(float x, float y)
{
    if(x == y)
    {
        printf("\n EQUAL \n");
    }
}

int main(void)
{
    compare(1.234, 1.56789);

    return 0; 
}

使用下面的 gcc 命令(包含 -Wall-Wextra 选项)来编译这段代码:

gcc -Wall -Wextra test.c -o test

遗憾的是,上面的命令没有生成任何与浮点值比较相关的警告。快速看一下 gcc 手册,在这种情形下可以使用一个专用的 -Wfloat-equal 选项。

下面是包含这个选项的命令:

gcc -Wall -Wextra -Wfloat-equal test.c -o test

下面是这条命令产生的输出:

test.c: In function ‘compare’:
test.c:5:10: warning: comparing floating point with == or != is unsafe [-Wfloat-equal]
 if(x == y)

正如上面你所看到的输出那样, -Wfloat-equal 选项会强制 gcc 编译器生成一个与浮点值比较相关的警告。

这儿是gcc 手册关于这一选项的说明:

这背后的想法是,有时,对程序员来说,把浮点值考虑成近似无限精确的实数是方便的。如果你这样做,那么你需要通过分析代码,或者其他方式,算出这种计算方式引入的最大或可能的最大误差,然后进行比较时(以及产生输出时,不过这是一个不同的问题)允许这个误差。特别要指出,不应该检查是否相等,而应该检查两个值是否可能出现范围重叠;这是用关系运算符来做的,所以等值比较可能是搞错了。

如何更好的管理 gcc 命令行选项

如果在你使用的 gcc 命令中,命令行选项列表变得很大而且很难管理,那么你可以把它放在一个文本文件中,然后把文件名作为 gcc 命令的一个参数。之后,你必须使用 @file 命令行选项。

比如,下面这行是你的 gcc 命令:

gcc -Wall -Wextra -Wfloat-equal test.c -o test

然后你可以把这三个和警告相关的选项放到一个文件里,文件名叫做 gcc-options

$ cat gcc-options&nbsp;
-Wall -Wextra -Wfloat-equal

这样,你的 gcc 命令会变得更加简洁并且易于管理:

gcc @gcc-options test.c -o test

下面是 gcc 手册关于 @file 的说明:

从文件中读取命令行选项。读取到的选项随之被插入到原始 @file 选项所在的位置。如果文件不存在或者无法读取,那么这个选项就会被当成文字处理,而不会被删除。

文件中的选项以空格分隔。选项中包含空白字符的话,可以用一个由单引号或双引号包围完整选项。任何字符(包括反斜杠: '\')均可能通过一个 '\' 前缀而包含在一个选项中。如果该文件本身包含额外的 @file 选项,那么它将会被递归处理。

结论

在这个系列的教程中,我们一共讲解了 5 个不常见但是很有用的 gcc 命令行选项: -Save-temps-g-Wextra-Wfloat-equal 以及 @file。记得花时间练习使用每一个选项,同时不要忘了浏览 gcc 手册上面所提供的关于它们的全部细节。

你是否知道或使用其他像这样有用的 gcc 命令行选项,并希望把它们在全世界范围内分享?请在下面的评论区留下所有的细节。


via: https://www.howtoforge.com/tutorial/uncommon-but-useful-gcc-command-line-options-2/

作者:Ansh 译者:ucasFL 校对:jasminepeng

本文由 LCTT 原创编译,Linux中国 荣誉推出

按照预期计划,Linus Torvalds 在 2016 年 12 月 11 日发布了 Linux 内核 4.9 的正式版本,这次主要带来了一些新的功能和一些驱动更新,当然,还有一些底层的改进。

Linux 内核 4.9 的开发始于 10 月中旬,这次缩短了合并窗口的截止期,以避免出现 4.8 时发生的在最后一刻提交的 PR 导致的内核错误。Linux 内核 4.9 是最新的主线内核,一些滚动发行版,比如 Arch Linux、Solus、openSUSE Tumbleweed 等都会很快将这个内核推送到它们的用户手中。

Linus ,“我估计这是我们开发的最大的发布版本,至少从提交数上来说是这样的。从变更的行数看,之前有过更大的版本,但是那些是因为一些特殊的原因(比如说,4.2 因 AMD GPU 寄存器定义文件而增加了大量变更行数。之前也因为一些代码重组而导致了大量变更行数: 3.2 是因为 staging 太大,3.7 是因为解离了自动 uapi 头文件,等等情况 )。以差异来说,4.9 才是最大的。”

Linux 内核 4.9 的主要变化

Linux 内核 4.9 中带来了许多新的功能,不过最激动人心的可能是对较老的 AMD Radeon 显卡的试验性支持。此外,这个版本也改进了对新的 AMD Radeon GPU 的支持,比如虚拟显示支持和更好的重置支持。对于 Intel GPU,也有对 DMA-BUF 方面的改进。

在这个版本中,对硬件和文件系统方面的改进也很多,涉及到 Btrfs、XFS、F2FS、OverlayFS 的 UBIFS 支持、FUSE 支持 POSIX ACL、OverlayFS SELinux 等方面。

相关情况

随着 4.9 内核的正式发布,4.10 (不是 5.x)内核的合并窗口也同时打开了。

此外,前几天发布了 4.8.13 之后仅仅两天,又发布了 4.8.14;而长期支持版本 4.4.38 LTS 也是在前一个版本发布两天后同期发布的。