用例-阿斯特丽德:Netflix的人工来源依赖洞察
文摘:
Jon Schneider和Nadav Cohen / NETFLIX, 2016年5月:NETFLIX采用了完全基于二进制集成的依赖管理策略,在没有NOC的情况下,仅用数十名运营工程师就成功地完成了每天数千次的生产变更。这种成功在很大程度上归功于开发的工具和技术,这些工具和技术允许产品工程团队在尽可能多的背景下快速移动。
Astrid将从低级到Java方法调用的信息拼接到AWS中上千个实例的自动伸缩组,为工程师提供了一段代码对Netflix生态系统影响的多维视图。我们将提供阿斯特丽德的现场演示,Netflix计划在2016年开放源代码。
讨论转录:
[约翰]好吧。我叫约翰·施耐德。
[Nadav]我是Nadav Cohen。
[约翰]我们来自
(Nadav)开发人员
(约翰)生产力
[Nadav]团队
(约翰)在
(Nadav)净
(约翰)毛皮。
[Nadav]酷。
[约翰]你不知道我们练习了多少次。这就像我们在Netflix的一天一样有条理。这一切都是因为Netflix是一种自由和责任的文化。那是什么意思,纳达夫?
[Nadav]在我们的环境中,自由和责任意味着每个团队都可以选择自己的工具、自己的语言和自己的发布周期。
[John]虽然每个团队都可以做自己的事情,但我们作为一个中央开发人员生产力团队,试图为Netflix的每个团队提供良好的信息和见解。帮助他们确保,你知道,最大的生产力和最小化他们的交付时间。
[John]所以,就我们所知,有两种方法来真正集成你的代码库。您可以做源代码级集成。源级集成有时称为从头构建或单点回购。有一些非常成功的组织正在这样做。谷歌,Facebook和Twitter都在某种程度上从头脑中构建。但他们这样做是与大型工程组织和-通常是一个巨大的工程努力。
[John]我认为谷歌已经侵入了文件系统,你知道,使他们的从头部构建系统运行良好,Facebook也侵入了Git本身,使他们的构建系统运行良好。
[John]另一种选择是二进制集成,每个团队都将二进制文件发布到一个中央工件存储库,然后我们以这种方式进行集成。Netflix做二进制积分。所以我们是一个相对较大的组织,但只有少数人从事开发工作,所以我们选择了二元集成。
[约翰]今天我们在这里要告诉你的是,我们是如何处理这些二元依赖的问题的。我们看到的最常见的。我们会给出一些解决这些问题的方法。合理的警告。这是一个基于JVM的演讲,所以我们会给出解决方案。我们将在Gradle中提供解决方案,这是我们选择的大部分构建框架。但是,你知道,类似的解决方案可以写在其他工具堆栈中,如果你选择这样做的话。我们从第一个问题开始。Nadav。
[纳达夫]好吧。在John所说的基础上,这张幻灯片中唯一相关的信息是我们将在GitHub上演示的所有代码。如果你想的话,你可以在那里访问它。
[纳达夫]好吧。接下来,我们来看第一个例子。基本上,我们将演示在Java中将重复的类放在相同的类路径中会发生什么。在这个例子中,我要构建一个命令行应用程序来输出给定集合的幂集。首先我要添加一些库。我不想白费力气,对吧,我也有点懒。我要添加Guava它是一个谷歌库。我还要添加谷歌个集合。
[纳达夫]好吧。既然已经有了依赖关系,就可以实际编写输出功率集的代码了。我来做一下。
[纳达夫]好吧。所以假设我没有任何错误,这应该建立在Gradle。好的。我还可以检查我的依赖项。我发现我有番石榴和谷歌的收藏。然后我也可以运行它。如果我运行它,你可以看到我成功地得到了集合的幂集。
[Nadav]现在问题来了。Java类加载的特殊之处在于,顺序是不保证的。换句话说,如果在类路径中有两个类,例如Tomcat可能会选择加载A,然后加载B,而Jetty可能会选择加载B,然后加载A。当您在类路径上有重复的类或相同类的多个定义时,这就成为一个问题。最终,Java只会任意选择一个,而抛弃其余的。最终,你不知道在运行时你会得到什么。这当然是个问题。对吧?所有东西都通过了编译,这很好,我们把它发布到部署,然后所有东西,当然,都坏了。
[Nadav]所以这不是Gradle特有的问题,但基本上我要用Gradle向你展示一个非常简单的排序改变会导致这个问题。对吧?
[Nadav]我要转到Gradle文件。我要改变顺序,然后重新构建。构建是成功的,正如您所期望的那样。然后我要检查依赖关系。哦。同样的依赖关系。Gradle实际上并没有重新编译,因为就Gradle所知,这是完全相同的代码,它实际上是相同的依赖关系,所以一切都保持不变。但是当我继续运行时,我们得到了一个运行时异常。正确的。我们会得到一个无此方法的错误。 So what actually happened here was that our code dependent on a very specific method on the set’s class. Right? From Guava. But because we used Google collections first in Gradle, that one was loaded first and because this one has the same set class with different functionality but the same set class. It basically masked away the class we wanted to use and cause this runtime exception. Right. Which is, of course, a problem.
[Nadav]所以我们在Netflix内部所做的解决这些问题的工作,基本上就是看看这些重复的类问题会发生在哪里。在这种情况下,发生这种情况是因为在Guava中的谷歌集合,我相信你们中的一些人已经知道,实际上是同一个库。对吧?这就是为什么它们共享相同的代码。不幸的是,Gradle并不知道这一点,因为不同的命名,不同的依赖关系意味着它们可以幸福地生活在一起。所以我们在Netflix内部建立了一个插件,叫做“解决规则”,它可以帮助Gradle理解什么时候依赖关系是相同的,然后相应地解决冲突。
[Nadav]。让我继续添加插件,只是为了向您展示它有多简单。
Nadav星云。然后我要添加规则本身。在这里,我对插件说,每次你看到谷歌集合,我希望你用Guava替换它。因为它已经被重新命名为番石榴,而且还记录了谁制定的规则,是哪一天制定的,以防我忘记。我们知道这可能会发生。正确的。回到构建中,我只是想包含这个规则。希望所有东西都正确。这将构建并运行。好的,构建成功。 I run dependencies. And now you’ll see something has changed. Now instead of having Google collections and Guava, I basically set up Gradle manage Google collections to Guava. And once it saw that it’s actually the same library it conflict resolved it to the latest 19 which is exactly what I wanted in this case. All right. And when I run the same program, you see that the power set works as expected despite the fact that I have multiple declarations of conflicting libraries. All right.
[约翰]所以这是一个有点做作的例子。我们引入了两种一阶依赖关系它们都是已知的相同事物。但实际上,在过去的一年里,这确实伤害了我们。这种重复类的问题。具体来说,当我们作为一个组织从Java 7迁移到Java 8时,造成最大痛苦的库之一是ASM。ASM的版本,ASM的最后一个通过代码支持Java 7的版本有一个名为ASM的组,一个名为ASM的工件。第一个支持Java 8的代码有一个名为org。OW2。ASM的组,然后是一个名为ASM的工件。因此,当我们试图从7到8的过渡时,我们不得不尝试推出旧的ASM, ASM版本,我们不能依靠我们的构建工具冲突解决机制来为我们做这件事。所以这些事情在实践中真的很痛苦,但它是有帮助的。因此,这是一条有用的规则。 On to the next one?
[Nadav]。有人有问题吗?特别是在我们继续之前?
关于这个问题有什么问题吗?
我想那里有人。
(约翰)。是吗?
[Nadav]我不确定。
[约翰]如果是的话,请大声说。或以其他方式。我们继续。好的。继续。
[Nadav]好了,我们接下来要讲的问题与捆绑依赖关系有关。基本上,我要做的是构建另一个命令行实用程序,但这次我将使用slf4j将内容记录到控制台。好的。
[纳达夫]好吧。因此,我要做的第一件事是添加slf4j的依赖项。把它准备好。让我们来看看这实际上带来了什么。所以我可以运行Gradle依赖项。我看到这基本上带来了三个依赖关系。如您所料,第一个是日志实现。第二个是slf4j的API。然后是他们之间的桥梁。好的。
[Nadav]所以我现在继续写代码,实际写入控制台。所以。
[Nadav]当然每个人每天都要这么做。好的。好的。如果一切顺利,这个程序应该可以运行。完美的。所以我们确实从记录器那里得到了消息。现在我想让这个更有趣一点。我想使用我在过去几周建立的自己的库,它基本上会从Netflix的原创中随机返回一段引语。我不知道这对其他人是否有用但对这个例子来说非常有用。所以我还是要用它。
[Nadav]首先,我想添加依赖性。好的。好的。检查结果的依赖关系,我们看到我们得到了报价服务。太好了。现在就可以使用这项服务了。好的。然后运行它,看看会发生什么。
[纳达夫]好吧。因为依赖关系,我又得到了一个运行时异常这一次,我希望大家能清楚地看到,它在抱怨我们在类路径中有两个冲突的jar。一个是我知道的,因为我想使用日志记录,但另一个,我不知道它从哪里来。但它阻止我运行应用程序,因为这是Gradle,我知道我可以,你知道,排除依赖,我可以删除所有传递的东西。我来试着做一下。好的。然后运行,得到完全相同的异常。什么都没有改变,即使如果我看看依赖关系,我看到它仍然是一样的。让我试着把所有的及物都去掉。看看会发生什么。 Same thing. So what actually happened here and again maybe some of you have noticed this, this is what we call a bundle dependency.
[Nadav]包依赖基本上是一个简化的jar传递机制。从本质上讲,库生成器只是将所有依赖项嵌入到同一个jar中,使它非常容易实际生成和消费。你只有一罐。但是你也失去了所有关于依赖性的信息。正确的。在我们的例子中,因为我们实际上想要移除一些传递依赖关系,但我们做不到,因为信息丢失了。
[Nadav]所以现在我们知道了问题所在,下一步就是确保这些捆绑的依赖不会出现在我们的版本中。同样,我们可以使用Resolution Rules插件来做到这一点。如果特定的包出现在类路径中,构建就会失败。好的。再一次,我要添加插件。好的。顺便说一下,你会注意到我在依赖块中添加了Resolution Rule。这让我们在Netflix内部做了一件非常有趣的事情,那就是将规则外化给其他人。其他人如果觉得这是一个对他们有用的规则,可以在他们的构建中使用这种依赖关系,并从我们的集体知识和我们对可能发生的所有类型的依赖关系问题的集体经验中受益。
[John]除此之外,我们在Netflix有大约5000个版本,所以我们大约有四个人在工作,负责解决与这些问题相关的问题。所以你可以保证我们看到了一个广泛的共同依赖问题。因此,这个集合是解析规则的目录,应该有利于许多组织。
[纳达夫]好吧。谢谢你!这里我们用的是拒绝规则。基本上是说,每次你看到报价服务包,构建就会失败,说这是一个坏包,包装了你不想用的坏库。然后我们还可以让他们去维基上找一个词条来进一步解释为什么这是个问题。正确的。我们一次又一次地看到这种情况。正如John提到的,我们支持每个人的构建环境,这是一个反复出现的问题。从自助服务的角度来看,这是非常有用的。
[Nadav]同样,我们有作者和日期。只是为了记录是谁在什么时候,为什么建立了这个规则。然后我们试着运行它。好,现在我们得到了一个异常,但现在它是一个非常显式的异常。正确的。构建失败是因为我们有一个非常糟糕的捆绑包,我们只想摆脱它。现在我们知道了问题所在,我们可以解决它。我们把这个去掉。使用非捆绑版本。好的。 And now we can check the dependencies. Now that we’re no longer using the bundle package and the dependency information is actually there, we can see what’s actually been brought in. Right. And this is the problematic package that we’ve saw before.
[Nadav]但现在我们有了这个信息,我们也可以说transitive = false,然后把它一起去掉。正确的。现在我们只得到我们需要的服务。一旦我们有了,我们可以做Gradle运行,并获得报价。我觉得这是杰西卡·琼斯专门写的。好的。就是这样。
[约翰]太棒了。这是我们今天想做的关于解析法则的两个演示。我们还会跟进更多。在我们继续下一个内容之前,关于解析规则还有什么问题吗?它可能为你做什么?是的。
[观众]那么,有人能不能在他们的项目中把所有的解析规则打包在一起,并保留他们正在使用的NLP库,[…]他们正在使用的NLP库是非常冲突的。因为您最初会知道哪个包可以[…]与项目中的其他包一起使用。所以。
(约翰)是的。
[观众]当你有了[…]规则之后,[…]能不能把它们组合成一个超级规则集?
[约翰]我们稍后会给你看一些东西。我们有一个Gradle Lint演示即将到来,我们将向你展示我们如何收集可能存在的潜在问题包的信息,然后如何-我们可以相应地构建规则。
[John]但是我确实想给你一个捆绑依赖问题的具体例子。我们最常遇到的是Jersey包。它实际上是迄今为止我们讨论过的两个问题的演示:重复类和包依赖关系。Jersey bundle只是将所有可用的Jersey库打包成一个,如果有人试图依赖特定的Jersey核心特定版本,但也有Jersey bundle。它会导致这两个包之间的版本不匹配。根据它们在类路径中加载的顺序它们会以意想不到的方式爆炸。这是最有害的一种。稍后我们将向您展示这对Netflix的影响范围。但是。
(Nadav)确定。我认为问题的另一部分是,我们是否真的有,你知道,这种规则可供其他人使用。所以,是的,开源版本的解决规则实际上有相当多的规则,我们认为对其他人普遍有用。所以我的意思是,如果你有,如果你想,请随意查看GitHub项目。你会在里面看到所有的规则。
(约翰)是的。太好了。关于决议规则还有其他问题吗?是的。后面有一个。
(观众)
[John]现在这是一个——这是一个只有Gradle的解决方案,因为它使用了Gradle的解析策略等等,但我再次认为,如果有帮助的话,我们这里的解决方案可以在其他构建工具中重新实现。
(观众)
[John]我们有自由和责任的文化,所以当然任何团队都可以选择不同的构建框架。还有一些在Maven或其他地方。SVT吗?
[Nadav]有些人使用Node。
(约翰)是的。但我们试图提供,你知道,一条平坦的道路,你知道,如果你接受这条平坦的道路,你将以最简单的方式得到最多的支持和最多的。所以在这一点上绝大多数是Gradle构建的。
[Nadav]只是因为使用预先准备好的东西要容易得多,而且真的很适合Netflix的环境。
(约翰)是的。
[Nadav]现在,如果你正在使用Maven,还有一件事要添加,有一个执行者插件,它的工作原理与解决规则插件非常相似,所以你可以尝试使用它。如果您正在使用Ant,那么祝您好运。
(约翰)。
[纳达夫]好吧。
(约翰)。接下来我们要给你们看的是
[Nadav][…]
[John] -是的,我猜你可以直接打开浏览器。太好了。这里有一个例子。我们有一个叫做Astrid的工具,它是Netflix的内部依赖关系洞察工具。
[John]我想你们在主题演讲中已经听说了,JFrog的一个演示,实际上是一个和这个非常相似的工具。Astrid的主要功能之一是,如果我是一个图书馆制作人,我想知道对组织的影响范围是什么。那就是直接和间接依赖我的人?我可以让阿斯特丽德知道。
[John]所以我们刚才特别提到泽西捆绑是一个大问题。我们知道这件事有一段时间了。我们最近引入了解决规则但是尽管我们已经-你已经在这个想法周围购物了你不想使用泽西捆绑,它会影响到下游的人等等。今天,如果你看看Jersey bundle在我们组织中的影响范围,我们只要在这里搜索Jersey bundle的任何使用,你会看到它存在于,你知道,内部部署的超过25万个库版本中,这正在影响- Jersey bundle存在于近700个亚马逊服务器组中,实际部署在EC2中。这只是其中的一个例子,如果Jersey bundle是在相对较低的水平上引入的,它将会渗透到整个图表并影响到,你知道,很多人。我们预计,随着解决规则的出现,这个数字将在短期内大幅下降。
[约翰]阿斯特丽德能做的其他事情。这是一种,你知道的,有很多不同特征的杂烩。我们用它从Artifactory中抓取元数据,提交哈希和类似的东西,并为特定模块生成一个GitHub风格的发布说明页面。所以,如果platform-ipc的生产者,也就是我们内部的一个罐子,没有勤勉地提供变更日志给它的消费者,人们可以来这里看看在最近的版本中有什么改变。特别是如果他们有问题,他们会先看这里。
[John]那就是阿斯特丽德,所以——我们正在用阿斯特丽德做的或者即将要做的其他事情,我们发现在网飞公司清理Artifactory的故事特别困难。如果我们试图创建一个规则,比如,让我们删除超过90天的快照,这对我们来说真的很难,因为所有的团队都处于不同的发布周期。如果我们删除一个90天前的快照,它可能包含在一个30天前的候选快照中,而不是本周发布的版本。所以我们不想删除实际生产中的东西。使用Astrid,因为我们正在捆绑在一起,拼凑信息,从二进制工件到asg,它们实际上部署在AC2中。我们确切地知道在任何给定的时间内使用的是什么,然后我们可以清除旧的东西。它在那里很有用。真的很想看看JFrog会想出什么。我认为非常相似。
[John]关于阿斯特丽德还有什么问题吗?你的用例可能是什么因为我们在考虑开源这个所以这是我们发现自己所处的一个有趣的位置。没有?
[观众]一个问题。
(约翰)是的。
(观众)
[Nadav]这是个好问题。
(约翰)是的。问题是你如何确定哪些项目依赖于特定的依赖项。Astrid所做的实际上是摄取依赖描述符像ID文件或Pom。所以我们在内存中有大量的数据关于所有的一阶依赖关系是什么,然后我们可以从另一个方向,在这个过程中模拟最新版本的冲突解决,并以这种方式工作。我们打开Debian文件,就像我听说JFrog正在做的那样。看看里面有什么依赖关系。一直到部署……都是这样。所以,是的。
关于阿斯特丽德还有问题吗?是的,先生。
(观众)
(约翰)是的。问题是这是Java独有的还是NPM相关的。现在只支持Java。历史上,Netflix的许多服务都是用基于JVM的语言编写的。不过这种情况最近有所改变。我想我们大概有60%是Java, 30%是NPM,还有一些其他的东西。所以,是的,我们确实有一个相对短期的功能,它在Node中追求同样的洞察力,因为它在内部变得越来越重要。所以。
[约翰]好吧。好。下一个主要功能,我们要向你展示的是Gradle Lint和-所以决议策略。解决策略可能我们已经向你们展示过了,对我们来说有点困难,因为作为一个核心构建团队,我们强加给所有团队一个意见,但我们有自由和责任的文化,所以它并不总是感觉完全正确。感觉好一点的是,如果我们写一条规则,我们看你的构建文件,我们写一条规则,我们发现一个违反,说嘿,这可能是一个问题,然后我们为你提供某种自动修复规则,如果你运行某个命令,就会修复你的代码,你可以看到它,然后你可以选择是否接受这个违反。这就是我们最近用Gradle Limp插件所做的。我们将演示它的一些功能。门没开?
Nadav哦。就在那儿。
(约翰)。你只需要站在那里。好了。哦,我的。做报告。
Nadav重置。
(约翰)是的。
[Nadav][…]
[约翰]那是什么?我们在哪里?好的。
[John]所以我们将从一个非常简单的应用程序开始。这又是一个有点做作的例子。我们将从一个非常简单的应用程序开始,它只包含一些依赖项引用。这里的主要方法指的是Amazon S3 Client。它引用了另一种类型默认的AWSCredentials提供程序。这里有一个很好用的函数,叫做Jackson,它从来没有被引用,它引用Jackson对象映射器。这是我们的一门课。另一个是测试原因,我们做TDD。这个测试绝对是指junit。在构建端,我们只有三个依赖项。我们有AWS Java SDK、Jackson数据绑定核心和junit本身。
[约翰]所以。您将注意到一些潜在的错误。第一,我在编译作用域中引用了junit,而实际上我应该在测试编译作用域中引用它。就目前的情况而言,如果我是库生产者,我将它作为二进制依赖项推出,我的下游每个人都将在他们的类路径中获得junit,而他们可能不想要它。这是我们发现的一种不幸的不规律的情况。我也使用这个AWS Java SDK,这是一个家庭jar。它实际上是一个零字节的罐子。里面什么都没有。它有一个Pom文件,其中包含AWS Java SDK的所有其他组件,其中许多我都没有使用。这是一种方便的依赖,我添加了它但我没有使用它带来的很多东西。 And then finally I’m referring to Jackson databind here, version two-five-five. But I’m actually, because of latest version conflict resolution, I’m actually getting two-six or above. So we’re going to see how Lint will help us surface these issues and fix them for us. So that we know exactly what’s going on.
[John]首先我们要应用插件。类似于我们得到的决议规则插件,你知道,基本上是一种将规则打包在罐子里的方式,包括那些罐子,那些未使用的依赖规则,当它与Gradle Lint本身可用时。你可以直接在你的构建脚本中或者在某个组织范围内的脚本中声明你想要使用的。这里我们要用到未使用依赖规则。当我们运行Lint时,我们会看到我们有- Lint已经报告了一些违规。首先它会说,嘿,你在使用junit,但实际上你并没有在你的主源代码中使用junit。你只在考试中使用它。因此,我们应该将这个文件发送到测试编译配置,这样就不会影响到下游用户。其次,它说AWS Java SDK实际上只是一个空罐子。它不包含任何东西,所以我们可以去掉它,因为否则你就会引入你并不真正需要的依赖项。 And then, you know, another thing it’s doing is it’s saying, hey I see you have a first order dependency on the S3 SDK specifically so we want to add that. We want to be declarative about the fact that we require that, and add that to our build script. Similarly the AWS Java SDK core is required directly so we want to add that as well.
[John]这些规则很棒,但更好的是,在这一点上,因为每个规则都包含一个自动修复规则,我们可以运行fix Gradle Lint,我们会看到它实际上转换了我们的构建脚本本身,添加了它从Amazon Java SDK中发现的两个依赖项。它将junit依赖重新定位到适当的配置,因此我们不会影响下游的用户。现在我们的依赖关系清晰多了。我们的依赖关系从30、40或50个减少到现在的小得多。
[John]所以我们将添加另一个规则,只是一个我们将-我们将添加覆盖的依赖版本。这是我在这里引用的Jackson版本在这里我们有一个关于2-5-5的声明但实际上亚马逊Java SDK也在使用Jackson它使用的是一个更高的版本。我们听到很多开发者的抱怨。他们会在构建文件中放入一个特定的版本,然后他们会想为什么他们没有得到它。他们没有得到它,因为冲突因为这样或那样的原因被解决了。我们也想让它浮出水面。这里如果我们运行fix Gradle Lint,你会看到它会继续说,好吧,你实际上只是使用了2-6-6,我们也可以在你的构建中把它表面化,这样你就不会对你在运行时实际得到的版本感到困惑。关于到目前为止你所看到的Gradle Lint插件有什么问题吗?好的。
[John]所以这个Lint功能对我们来说真的很紧急。这导致了我们认为的最终一致的二进制积分的单序回购。我们的意思是,你知道,像这样的事情,二进制依赖管理是很难的。我们并不总是指定正确的版本。我们希望确保人们尽可能少地使用依赖项,但要明确他们使用的依赖项,他们有正确的版本。但是Lint,我们也想象它会被用来操纵源代码。
[John]现在有一个很好的例子,在slf4j存在之前,我们在内部有一个领先的曲线,我们写了我们的库叫[…]。slf4j的功能基本相同。这是普遍存在的答案,然而,直到今天,你知道,我们有成千上万的参考文献。你知道,这是相对简单的无论什么时候我们看到这段代码,我们可以用另一段代码替换它。然而,你知道,这真的不是一个负责任的利用我们的时间去寻找每一个参考文献。
[John]所以我们允许,我们将很快允许我们的库生产者做的是将规则打包到他们自己的罐子中,这些罐子将操纵源代码,改变API调用,诸如此类的事情。这将会一遍又一遍地出现在构建中,无论何时开发人员运行修复Gradle Lint,他们都会接受这个更改,并将其工作到代码中。所以这就像单一回购的替代方案,你知道,当你-如果我们决定从[…]到slf4j,我们在整个组织中进行重构操作。在这里,我们可以提供一个规则,然后它通过有机的工作,因为人们运行修复Gradle Lint。
[约翰]好吧。我想现在大家可以提问了。Netflix开发人员生产力团队的情况,或者到目前为止你看到的情况?
[观众]那么这些东西对任何人都适用吗?
(约翰)是的。这些都在GitHub上。我们今天演示的那些,Gradle Lint插件,Resolution Rules插件,都在那里。
(Nadav)是的。只有阿斯特丽德还在体内。
(约翰)是的。
[Nadav]但我们实际上是在寻求反馈。如果这是其他人可能会感兴趣的东西,我们不妨将其开源。
[约翰]对。是的。我们想知道你们的用例是什么。所以。
[观众]那么这对项目有什么影响呢[…]当你制定规则,解决规则[…]。这是否反映了依赖关系报告的任何输出?
[John]问题是:解决规则插件是否反映在依赖报告的输出中?这是一个非常有见地的问题,因为有两种可能,它要么影响一个一级依赖关系要么影响一个传递依赖关系。在影响一级依赖关系的情况下,假设您由于某种原因不匹配AWS版本。这最终将在Pom或IBXM中表示。
[John]在影响及物动词版本的情况下,它不会。这对我们来说又是一个棘手的问题,因为,你知道,潜在的,如果你应用解析规则,它修复了一个传递,你的代码可以编译和测试,一切看起来都很好,你发布它,如果你的下游消费者不应用解析规则,你的项目可能会出现功能障碍。
[约翰]所以现在我们只是说,嗯,你知道,每个人都在用它,所以我应该没问题。最终它会影响到一个较短的版本,所以它应该会渗透到整个版本。但是当我们有一个决议规则的时候,我们可能也会有一个相关的Lint规则。这样我们就能找到问题的根源不管一阶依赖关系在哪里然后解决它。这最终是更正确的解决方案。
[Nadav]在他刚刚说的基础上,我们还集成了我们的度量插件,这是我们之前完全没有提到的。基本上,Lint插件可以与另一个插件对话,我们称之为信息代理,它与度量插件对话,最终将度量发送到弹性搜索实例。
[约翰]对。
[Nadav]然后我们可以做各种有趣的聚合,看看,你知道,整个组织有多少违规行为。是否有一个特定的团队在背后,你知道,我们需要和他们谈谈,我们的计划是在解决规则方面也做同样的事情。所以我们实际上有一个集中的地方所有关于组织的聚合信息,基于这些信息我们可以采取相应的行动。正确的。也许会写更多的规则,也许会和车队谈谈,这真的取决于我们的发现。
[John]度规帮助我们的一个很好的例子是这样的。我们之前用适应解决的问题,Guava谷歌集合问题。哦,没用过了,我需要。开枪。我把未使用的去掉因为它对我来说太聪明了。这是一个规则它只是一个重复的依赖类规则,它会查看你的依赖项,然后说,嘿,你实际上有两个包含相同类的东西,或者在这种情况下,这两个库之间有超过298个类的重叠。不幸的是,我们对此没有自动修复规则,因为我不知道你真正想要的是哪个,但它还是会显示出来,所以开发人员不会对运行时顺序问题感到惊讶。而且因为我们要把所有这些违例传递到我们的度量收集器,我们知道作为一个团队,我们在这里看到,这是一个例子,在这两个库之间有一个重复的依赖类,我们要为它添加一个解析规则,我们要为它添加另一个Lint规则来处理这个问题。是的,先生。
(观众)
[John]问题是:规则是否只由我们的团队管理?
(Nadav)是的。所以答案是,我们有一些集中的规则,每个人都可以使用。但是任何东西都可以自由地添加他们自己的规则,如果他们觉得他们可以更严格地构建他们的构建方式——本质上是构建的。正确的。所以你只要用你自己的规则添加另一个依赖项,你自己的内部规则,然后,你知道,你可以应用那些。
(观众)
[Nadav]。它们根本不是硬编码的。您只需使用自己的解析规则添加依赖项,就可以开始了。
(约翰)是的。这是正确的。
[观众]那么您在Java方面已经有了这些,您在NPM方面也会走同样的路线吗?[…]简直就是狂野的西部[…]
[John]我认为我们已经注意到的问题是:我们在NPM上是否也在走同样的道路?在记录中,有一点关于NPM也像狂野的西部所以你也想说你的名字,先生,开玩笑的。
(观众)
(约翰)。好了。到目前为止,我们的理解是,因为NPM有那种层次打包机制,它真的不像在Java中那样丑陋,在Java中我们有平坦的类路径,你知道,一个类会赢,等等。我们对Jigsaw项目抱有很大的希望,希望它能让我们在Java中以分层的方式分层依赖。虽然他们为此提供了一些编译时间[…],不幸的是,在运行时,那个层的构造——那个层的机制留给了运行时。因此,Java 9无法解决这个问题。而且,你知道,这将继续成为我们的痛点,所以我们必须在当下做些什么。是的,先生。
[观众]既然你现在在谈论Java和NPM,有没有一个度量数据库或[…]。这将是一种[…]技术,还是仅仅是Java特有的?
[Nadav]这是个有趣的问题。问题是:如果我们的弹性搜索数据库是语言不可知的,对吧,一旦我们转向不同的技术。我不认为——我不认为——我们实际上已经在内部讨论过这个问题,但我相信答案将是肯定的。
[观众][…]开源。不管怎样,我都得去做。
[John]问题是:我们会把它开源吗?最终如果它是多平台的。现在,度量收集器实际上是Java端——JVM端开源的。它是Gradle metrics插件。这些都与之相关。是的。我们为NPM做的任何事情都是像这样的通用解决方案,我认为我们没有任何理由不把它也开源。我们只是在旋转它。所以。
(约翰)[…]。我听说[…]。蛮野的家伙。还有其他问题吗?[…]。好的。谢谢你能来,我们会在你身边的。谢谢你!
