对于由单个团队维护的小型系统,将所有服务放在一个构建中是很好的。这样做可以很容易地使用runAll任务运行您的所有服务,稍后我们将在本手册的运行服务一节中看到这一点。
如果你有多个团队,那么正如Lagom构建概念中描述的那样,我们建议将你的系统划分为多个构建
如果您还不关心扩展到多个团队,那么可以跳过这一节。

发布服务

即使有多个构建,您仍然经常希望在开发中一起运行您的服务。Lagom允许将一个构建发布的服务导入到另一个构建中。
假设您有一个hello服务,希望将其发布并导入到另一个构建中。您可以通过从sbt运行publishLocal将其发布到本地存储库。这是发布服务最简单的方法,但是这意味着每个想要运行导入服务构建的开发人员都需要将其发布到他们自己的存储库中,并且他们需要为每个想要导入的版本这样做。
更常见的方法是,许多开发人员可以共享单个Maven或Ivy存储库,他们可以发布和从中提取工件。如何做到这一点有几个选项。如果您想在本地运行存储库,常见的解决方案是ArtifactoryNexus。有关如何在sbt中配置这些构件的信息,请参见如何发布构件

导入服务

可以通过在构建中添加以下声明来导入hello服务:

  1. lazy val hello = lagomExternalScaladslProject("hello", "com.example" %% "hello-impl" % "1.0")

传递给lagomExternalScaladslProject的第一个参数是将在构建中用于引用这个外部定义的项目的名称。而第二个参数提供了对hello-impl JAR的依赖关系,使用传统的sbt语法声明依赖关系。注意,实际上lagomExternalScaladslProject方法返回一个sbtProject,如果需要,您可以进一步定制它。
您可以使用与管管理Lagom服务相同的设置来进一步配置服务(它可用的端口,它绑定到的地址等)。

Mock服务

有时,您导入的服务将依次依赖于其他服务。这可能导致一个接一个地导入服务,直到您发现必须在构建中运行整个系统。除了不方便管理之外,对于大型系统来说,这可能是不可行的。相反,您可以选择模拟一些服务,提供一个真实服务API的假实现。模拟实现仅用于运行开发中使用该服务API的其他服务,而不必将实际实现导入到它们的构建中。这类似于单元测试中mock库的使用—如MockitojMockscalamock—但是是在服务级别而不是类级别。
编写和使用模拟服务实现就像编写和使用实际服务实现一样,只是业务逻辑被简单的硬编码响应所取代。模拟服务实现不应依赖于任何其他服务、数据库、消息中间件或任何其他基础设施。例如,您可能正在开发一个OAuth服务,该服务使用单独的用户身份验证服务来验证用户凭据,然后为经过身份验证的用户生成并存储API令牌。反过来,用户身份验证服务可能与处理新用户注册的服务、处理密码更改的用户配置文件管理服务和用于SSO集成的LDAP服务器交互。当测试OAuth服务时,并不总是需要包含所有额外的复杂性并对其进行端到端测试。相反,您可以运行一个模拟用户身份验证服务,该服务实现与实际API相同的API,但只支持一小部分测试用户。在OAuth服务的构建中运行模拟服务允许您测试OAuth功能,与那些不相关的关注点隔离开来。
通过在该项目中创建依赖于原始服务API库的新服务实现,您可以选择在与消费服务相同的构建中实现模拟服务。或者,您可以在与实际服务相同的构建中实现模拟服务,将其与实际实现一起发布,并将模拟导入消费服务的构建中,如上所述。
在消费服务构建中聚焦Mock的好处是随着消费服务的发展很容易改变Mock实现,随之而来的好处是Lagom的自动重载,而且不需要为每一次变化发布Mock到工件库。如果实际服务有多个使用者,那么它允许每个使用者都有一个定制的Mock实现,该实现适合于自己对服务的使用。
另一方面,将模拟定位在实际实现旁边的好处是,单个模拟实现可以由多个消费服务项目共享。有时,这将比为每个消费服务创建模拟实现更方便。选择权在你。

使用外部服务

现在你已经把hello服务集成到你的构建中(或模拟的等效服务),任何你的Lagom项目都可以在给它的hello-api工件添加一个库依赖项之后与它通信:

  1. lazy val `greetings-api` = (project in file("greetings-api"))
  2. .settings(libraryDependencies += lagomScaladslApi)
  3. lazy val greetingsImpl = (project in file("greetings-impl"))
  4. .enablePlugins(LagomScala)
  5. .settings(libraryDependencies += "com.example" %% "hello-api" % "1.0")
  6. .dependsOn(`greetings-api`)

在为服务的每个消费者添加API依赖项后,我们需要绑定服务客户端。Lagom使用这种绑定来提供服务API的实现,该API使用客户端与远程服务通信。这可以使用serviceClient.implement[T]在绑定服务客户端中解释。
提供绑定后,只需在sbt控制台中输入reload。然后,当执行runAll时,你应该看到hello服务已经启动,以及在构建中定义的所有其他服务:

  1. > runAll
  2. [info] ...
  3. [info] Service hello listening for HTTP on 0:0:0:0:0:0:0:0:22407
  4. [info] ...
  5. (Services started, use Ctrl+D to stop and go back to the console...)

消息中间件解耦

使用Lagom Message Broker支持的服务可以完全避免在其构建中运行其他服务的需要。这些服务不需要彼此直接连接,只需要连接到Kafka。对于开发目的,您可以使用Kafka -console-producerKafka -console-consumer命令行脚本(或其他简单的Kafka客户端)来模拟与其他服务的交互。