Run a service locally

Running a service locally is helpful to test and debug. The following sections provide commands for starting and stopping a single service locally.

Prerequisites

In order to run your service locally, you’ll need to have the following prerequisites:

  • Docker 20.10.8 or higher

  • Access to the gcr.io/akkaserverless-public container registry

  • Your service packaged as a container

The samples provided with the Akka Serverless SDKs all have docker-compose files preconfigured to run your service locally. They also contain the configuration to start a local Google Pub/Sub emulator that the Akka Serverless proxy will connect to when you make use of Publishing and subscribing to topics on a broker in your service.

Starting your service

To start the proxy, run the following command from the directory with the docker-compose.yml file:

  1. Start the proxy

    docker compose up
  2. Start the service

    Java
    mvn compile exec:exec
    JavaScript/TypeScript
    npm start
    Scala
    sbt run

By default this command will start your containers in foreground mode. This means the terminal window will show all output from all containers. To start in "detached" mode, add the -d or --detach flag to the docker compose commands.

Invoking your service

After you start the service it will accept invocations on localhost:9000. You can use gRPCurl or cURL to invoke your service.

Using cURL

Linux or macOS
curl \
  -XPOST \ (1)
  -H "Content-Type: application/json" \ (2)
  -d '{"counterId": "foo"}' \ (3)
  localhost:9000/com.example.CounterService/GetCurrentCounter (4)
Windows 10+
curl ^
  -XPOST ^ (1)
  -H "Content-Type: application/json" ^ (2)
  -d '{"counterId": "foo"}' ^ (3)
  localhost:9000/com.example.CounterService/GetCurrentCounter (4)
1 The XPOST flag indicates cURL will send a POST request
2 The content type for this request is set to application/json
3 The message payload in JSON format
4 The URL with the RPC procedure name which is deduced from the protobuf definition of the component you’re calling.

Using gRPCurl

Inspect your services with the gRPC list and describe commands:

grpcurl -plaintext localhost:9000 list

grpcurl -plaintext localhost:9000 describe com.example.CounterService

Get a current value from the CounterService:

Linux or macOS
grpcurl \
  -d '{"counterId": "foo"}' \ (1)
  -plaintext localhost:9000 \ (2)
  com.example.CounterService/GetCurrentCounter (3)
Windows 10+
grpcurl ^
  -d '{"counterId": "foo"}' ^ (1)
  -plaintext localhost:9000 ^ (2)
  com.example.CounterService/GetCurrentCounter (3)
1 The message payload in JSON format with -d
2 The address of the proxy (using plaintext instead of TLS)
3 The RPC procedure name which is deduced from the protobuf definition of the component you’re calling.

Shut down the proxy

To shut down the proxy, which removes all data kept in memory, run the command below:

docker stop akkaserverless-proxy

To delete the proxy container, run

docker rm akkaserverless-proxy

Running multiple services

You can run multiple services at the same time. To do that, each service will need its own proxy container. Each proxy container will need its own port.

To update the docker compose file to run multiple proxy instances, add the snippet below:

akka-serverless-proxy: (1)
  image: gcr.io/akkaserverless-public/akkaserverless-proxy:latest
  command: -Dconfig.resource=dev-mode.conf -Dakkaserverless.proxy.eventing.support=google-pubsub-emulator
  ports:
    - "900x:9000" (2)
  environment:
    USER_FUNCTION_HOST: ${USER_FUNCTION_HOST:-host.docker.internal}
    USER_FUNCTION_PORT: (3)
1 This name has to be unique in your docker compose file (docker compose uses this name to uniquely identify the running container)
2 The host port ("900x") in the port mapping must be unique for each proxy instance
3 The user function port must be unique for each service you start. You can set the port on which your service listens in the start method.