Skip to content

Latest commit

 

History

History
133 lines (110 loc) · 5.35 KB

apps.md

File metadata and controls

133 lines (110 loc) · 5.35 KB

Apps

Apps are actors too. Any running app has it's certain endpoint and anyone can send messages to it. There are implementation differences between App and Service.

Since app is a user-supplied piece of code, that is accounted to be faulty, apps are run in isolation from the core part of cocaine-runtime. At least, app instances are run in separate processes, called slaves, workers, or slave worker processes. The level of isolation and how these processes are started and handled is described in a specific isolate plugin.

Isolate plugin interface has the two main methods: spool and spawn. Spool is used to fetch application's code or image to local computing node, and spawn is used to launch one worker instance.

Start-up procedure

Let's consider a start-up procedure for some app testapp.

A certain cluster node, specifically it's service node, receives message [start_app, sid, [{"testapp":"someprofile"}]]. We won't go into details of specific profile here, or isolate plugin, or cache storage interactions. We assume that there's no cache storage on cluster nodes, and describe generic start-up procedure.

So when node service receives app_start message, it creates an instance of slave_t class, which starts an instance of engine_t class, which has queue member. app_t constructor calls isolate_t::spool method, which is supposed to prefetch and unpack application code from shared network storage to local storage (spool directory in case of plain process isolate).

Also, a special service is started. It's called invocation service, it has two methods enqueue and info, and it's published to locator under the name of application being started, here testapp. Consequently, anyone who is resolving service named tetsapp, receives the endpoint of this invocation service, and method table which consists of two methods: enqueue and info.

So, by far, there is an app code deployed on local node, and there is the published invocation service named testapp listening on certain endpoint.

When client connects to this testapp service, and sends in messages, using enqueue method of this service, the following things happen. Service calls method enqueue of it's connected slave instance. Then it calls wake method, which makes slave's thread to wake up. Slave's engine calls pump method. Since there's no active running workers that are able to process newly enqueued messages, no messages are fetched from queue. Then it calls balance method. Balance method does balancing as it is described in [overview.md#Balancing_slave]. So it finds that there are unprocessed messages in queue, and uses it's isolate's method spawn to spawn more workers.

In case of plain-process isolate, worker is run in the cwd of it's spool directory, with the exec path of .slave field from manifest. Process plugin passes various options (as argv) like worker uuid, app name, endpoint that worker has to connect to communicate with cocaine-runtime. Worker process should, after it's initialization, connect to it's app's socket, send handshake message (which is handled by engine_t), and a first heartbeat message, when worker is ready to process incoming messages.

After it happens, slave becomes active, and when pump method is called once again, active slave receives messages, which are passed through slave's socket to the slave worker process.

Available Isolates

There are two basic isolate plugins currenly in use. The process isolate, which operations are as described above, and docker isolate.

For basic understanding how Docker works in general, refer to [docker.md]. The docker isolate's spool method instead of fetching app's tar, does basically a docker pull call through local docker daemon's REST api. Docker isolate's start method does docker run call with resource constraints found in profile.

App configuration

Unlike Services, which are configured in cocaine-runtime configuration file on nodes of cluster, apps are configured through the following entities stored in shared storage.

manifest currently it specifies the path to slave worker process that cocaine-runtime is supposed to run in worker isolate. It used to contain different other options, but currently they got out of use, and usually manifest boils down to something like

{"slave": "./path/to/worker"}

path to worker is specified relatively to tgz root, in case of tar-packed app, and to container root in case of docker container.

profile specifies various balancing, isolate and other properties related to application runtime configuration. Usually, profile to run app in docker container looks like this:

{
  "queue-limit":1000,
  "concurrency":100,
  "spawn-threshold": 10,
  "isolate":{
    "type":"docker",
    "args":{
      "registry":"http://dockerregistry.tst.ape.yandex.net"
      "repository":"unstable"
    }
  }
}

Refer to [TODO] to see the complete specification of available profile parameters.

runlist is a map from app-name to profile. Cocaine-runtime uses it to start apps on a start of a particular node start, as described in Services.md#node_service. Typical runlist would look like this:

{
  "app-some-1":"docker-local",
  "app-other":"run-from-tgz",
  "app-another": "queue-10000"
}

Here, again, app-some-1, app-other, app-another are apps names, and docker-local, run-from-tgz and queue-1000 are profile names, with which corresponding app should be run.