如何以编程方式生成类似Heroku的子域名?

我们已经看到了当您使用简单的“heroku create”将应用程序部署到Heroku时自动分配的有趣子域。

一些例子:炽热薄雾4652,电动夜-4641,晨霜-5543,辐射河-7322,等等。

它们似乎都遵循形容词 – 名词 – 4数字模式(大部分)。 他们只是输入了一些形容词和名词的字典,然后在推送应用程序时随机选择它们的组合吗? 是否有一个Ruby gem可以实现这一点,或许提供了一个可以通过词性搜索的字典,或者这是手动完成的事情?

Heroku API团队的工程师在这里:我们采用最简单的方法来生成应用程序名称,这基本上就是你所建议的:将形容词和名词的数组保存在内存中,随机选择一个元素并将其与来自的随机数组合起来1000至9999。

不是我写过的最激动人心的代码,但是为了扩展这个代码我们必须要做的事情很有意思:

  • 首先,我们选择一个名称,尝试INSERT然后挽救唯一性约束错误以选择不同的名称。 这个工作正常,而我们有一大堆名称(以及使用它们的不那么大的应用程序集),但在一定规模上,我们开始注意到在名称生成过程中发生了很多冲突。

    为了使其更具弹性,我们决定选择几个名称,并通过单个查询检查哪些名称仍然可用。 我们显然仍然需要检查错误并因竞争条件而重试,但是表中有如此多的应用程序,这显然更有效。

    它还有一个额外的好处,即如果我们的名字池很低,我们可以提供一个简单的钩子来获取警报(例如:如果采用1/3的随机名称,发送警报)。

  • 我们第一次遇到碰撞问题时,我们只是通过从2位数到4位从根本上增加了我们名字池的大小。有61个形容词和74个名词,这使我们从~400k到~40mi名称( 61 * 74 * 8999 )。

  • 但是当我们运行200万个应用程序时,我们又开始接收碰撞警报,并且速度远高于预期:大约一半的名称发生了碰撞,考虑到我们的游泳池大小和运行的应用程序数量,没有任何意义。

    您可能已经猜到的罪魁祸首是rand是一个非常糟糕的伪随机数生成器 。 使用SecureRandom挑选随机元素和数字可以从根本上降低碰撞量,使其与我们预期的一致。

有了这么多工作要扩展这种方法,我们不得不问是否有更好的方法来生成名称。 讨论的一些想法是:

  • 使名称生成成为应用程序ID的函数。 这将更快,并完全避免碰撞的问题,但在缺点,它会浪费很多名称与删除的应用程序(该死的,我们有很多应用程序创建和删除后不久作为不同的集成测试的一部分) 。

  • 使名称生成确定性的另一个选项是在数据库中拥有可用名称池。 这样可以轻松地执行诸如仅在删除应用程序2周后重复使用名称之类的操作。

很高兴看到下次碰撞警报触发时我们会做什么!

希望这有助于任何从事友好名称生成的人。

有几种可能性。

您可以生成随机字符串 。

如果你想使用真实的单词,你需要一本字典。 然后,您可以创建生成单词和数字排列的结果。

另一个不错的选择是Ruote采用的另一个。 Ruote依靠rufus-mnemo为每个进程生成一个唯一的名称。 rufus-mnemo提供了将整数转换为更容易记住“单词”的方法,反之亦然。

您可以为记录生成唯一ID,然后将其转换为单词。

我创建了一个gem来执行此操作: RandomUsername

同样的gem是Bazaar和Faker 。