Akka Discovery Integration

§Using Akka Discovery

As of version 1.5.1, Lagom has built-in integration with Akka Discovery throught a ServiceLocator that wraps Akka Discovery. This ServiceLocator implementation is called AkkaDiscoveryServiceLocator. This is the recommended implementation for production specially for users targeting Kubernetes and DC/OS (Marathon).

§Dependency

To use this feature add the following in your project’s build:

import com.lightbend.lagom.core.LagomVersion

libraryDependencies += "com.lightbend.lagom" %% "lagom-scaladsl-akka-discovery-service-locator" % LagomVersion.current

The example above uses LagomVersion.current in order to guarantee that dependency stays aligned with your current Lagom plugin version.

§Configuration

Once you have it in your project you can add the component to your LagomApplicationLoader.

import com.lightbend.lagom.scaladsl.devmode.LagomDevModeComponents
import com.lightbend.lagom.scaladsl.server._
import com.lightbend.lagom.scaladsl.akka.discovery.AkkaDiscoveryComponents

class HelloApplicationLoader extends LagomApplicationLoader {

  override def load(context: LagomApplicationContext) =
    new HelloApplication(context) with AkkaDiscoveryComponents

  override def loadDevMode(context: LagomApplicationContext) =
    new HelloApplication(context) with LagomDevModeComponents

}

By default, Lagom uses Aggregate multiple discovery methods. The first discovery method is set to Configuration and the second is set to DNS. So the static definition of service endpoints has a priority over DNS discovery.

To statically configure service endpoints in your application.conf file consult the Aggregate multiple discovery methods documentation.

§DNS SRV vs. DNS A/AAAA Lookups

AkkaDiscoveryServiceLocator supports DNS SRV as well as DNS A lookups. It defaults to SRV lookups since it’s the most common usage in environments like Kubernetes and DC/OS (Marathon).

Since Lagom’s ServiceLocator API does not support port-name and protocol fields as used in SRV lookups, AkkaDiscoveryServiceLocator will use default values as fallback. The default port-name is http (as defined by setting lagom.akka.discovery.defaults.port-name) and the default protocol is tcp (as defined by setting lagom.akka.discovery.defaults.port-protocol).

Those values are only used if a lookup is done for a string that does not comply with the SRV format. For instance, when looking for another Lagom service using a Lagom service client. In such a case, the lookup is done using the service name, as defined by its ServiceDescriptor, and the defaults for port-name and protocol.

If both lagom.akka.discovery.defaults.port-name and lagom.akka.discovery.defaults.port-protocol are set to null or a blank string, the lookups are done without those values which correspond to simple a DNS A lookup.

§Confinguring Service Mappings

It’s possible to override those values on a per service base using service-name-mappings.

You may map a service name to a SRV string as in:

lagom.akka.discovery {
  service-name-mappings {
    my-service-name {
      # lookup is done using 'my-service-name'
      # but translated to SRV string _http._tcp.default.svc.cluster.local
      lookup = _http._tcp.default.svc.cluster.local
    }
  }
}

You can also override the port name and protocol to force a DNS A lookup:

lagom.akka.discovery {
  service-name-mappings {
    # lookup is done using 'my-cassandra-server'
    # but translated to cassandra.default.svc.cluster.local
    # and without port name and protocol, ie: DNS A lookup
    my-cassandra-server {
      lookup = cassandra.default.svc.cluster.local
      port-name = null
      port-protocol = null
    }
  }
}

This per service override will allow a DNS A lookup the cassandra server while any other lookups will still use the defaults.

The default settings are in defined in the reference configuration as:

lagom.akka.discovery {

  # When the service lookup regex fails, the defaults are used for the port and protocol.
  defaults {

    # The default port name. Blank if no port name should be added by default.
    port-name = http

    # The default port protocol. Blank if no port protocol should be added by default.
    port-protocol = tcp

    # The default scheme to use in returned URIs if not defined in the port-name-scheme-mappings.
    scheme = http
  }

  # A mapping of service names to lookup information. Each mapping should define the following:
  #
  # - lookup - An alternative name for the service. This can be configured with a simple name or a SRV lookup, for exampe:
  #   * my-service (simple name)
  #   * my-service.default.svc.cluster.local (simple fully-qualified name)
  #   * _http._tcp.my-service (SRV)
  #   * _http._tcp.my-service.default.svc.cluster.local (fully-qualified SRV)
  # - port-name - The port name to use. If undefined, it will use the default lagom.akka.discovery.defaults.port-name.
  #               Setting to null or empty string will result to a lookup without port-name (eg: DNS A records)
  # - port-protocol - The protocol to use. If undefined, it will use the default lagom.akka.discovery.defaults.port-protocol.
  #               Setting to null or empty string will result to a lookup without protocol (eg: DNS A records)
  # - scheme - The scheme to return in the URI. If undefined, it will use the default scheme lagom.akka.discover.defaults.scheme.
  #
  # For example:
  # service-name-mappings {
  #   my-service-name {
  #     lookup = my-service.default.svc.cluster.local
  #     port-name = http
  #     port-protocol = tcp
  #     scheme = http
  #   }
  # }
  service-name-mappings {
  }


  # The timeout for a successful lookup.
  lookup-timeout = 5 seconds
}

Note: this component was previous published as an independent library. If you have it on your classpath it’s recommended to remove it and use the one being provided by Lagom directly.

Found an error in this documentation? The source code for this page can be found here. Please feel free to edit and contribute a pull request.