tz70s closed pull request #3757: Introduce configurable action blob size limit.
URL: https://github.com/apache/incubator-openwhisk/pull/3757
This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:
As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):
diff --git a/ansible/roles/controller/tasks/deploy.yml
b/ansible/roles/controller/tasks/deploy.yml
index 29dcc1b96a..b1bdb24d91 100644
--- a/ansible/roles/controller/tasks/deploy.yml
+++ b/ansible/roles/controller/tasks/deploy.yml
@@ -190,6 +190,10 @@
"CONFIG_whisk_timeLimit_max": "{{ limit_action_time_max | default() }}"
"CONFIG_whisk_timeLimit_std": "{{ limit_action_time_std | default() }}"
+ "CONFIG_whisk_action_blobSize": "{{ limit_action_blob_size | default()
}}"
+ "CONFIG_akka_http_server_parsing_maxContentLength": "{{
limit_action_blob_size | default() }}"
+ "CONFIG_akka_http_client_parsing_maxContentLength": "{{
limit_action_blob_size | default() }}"
+
"CONFIG_whisk_activation_payload_max":
"{{ limit_activation_payload | default() }}"
diff --git a/ansible/roles/couchdb/tasks/deploy.yml
b/ansible/roles/couchdb/tasks/deploy.yml
index b59c23d044..4f87357176 100644
--- a/ansible/roles/couchdb/tasks/deploy.yml
+++ b/ansible/roles/couchdb/tasks/deploy.yml
@@ -63,6 +63,19 @@
force_basic_auth: yes
when: (couchdb.version|version_compare('2.0','>=')) and (db.instances|int ==
1)
+- name: setup httpd request entity size limit for database
+ uri:
+ url: "{{ db_protocol }}://{{ ansible_host }}:{{ db_port
}}/_node/couchdb@{{ ansible_host }}/_config/httpd/max_http_request_size"
+ method: PUT
+ body: >
+ "{{ limit_action_blob_size | default('50m') | human_to_bytes }}"
+ body_format: raw
+ status_code: 200
+ user: "{{ db_username }}"
+ password: "{{ db_password }}"
+ force_basic_auth: yes
+ when: (couchdb.version|version_compare('2.0','>=')) and (db.instances|int ==
1)
+
- name: enable the cluster setup mode
uri:
url: "{{ db_protocol }}://{{ ansible_host }}:{{ db_port }}/_cluster_setup"
diff --git a/ansible/roles/invoker/tasks/deploy.yml
b/ansible/roles/invoker/tasks/deploy.yml
index ee4a79aaf3..24d21f09ce 100644
--- a/ansible/roles/invoker/tasks/deploy.yml
+++ b/ansible/roles/invoker/tasks/deploy.yml
@@ -207,6 +207,9 @@
"CONFIG_whisk_timeLimit_min": "{{ limit_action_time_min | default() }}"
"CONFIG_whisk_timeLimit_max": "{{ limit_action_time_max | default() }}"
"CONFIG_whisk_timeLimit_std": "{{ limit_action_time_std | default() }}"
+ "CONFIG_whisk_action_blobSize": "{{ limit_action_blob_size | default()
}}"
+ "CONFIG_akka_http_server_parsing_maxContentLength": "{{
limit_action_blob_size | default() }}"
+ "CONFIG_akka_http_client_parsing_maxContentLength": "{{
limit_action_blob_size | default() }}"
"CONFIG_whisk_activation_payload_max": "{{ limit_activation_payload |
default() }}"
"CONFIG_whisk_transactions_header": "{{ transactions.header }}"
diff --git a/ansible/roles/nginx/templates/nginx.conf.j2
b/ansible/roles/nginx/templates/nginx.conf.j2
index a86593f26e..1e8787ef61 100644
--- a/ansible/roles/nginx/templates/nginx.conf.j2
+++ b/ansible/roles/nginx/templates/nginx.conf.j2
@@ -10,7 +10,7 @@ events {
http {
{# allow large uploads, need to thread proper limit into here #}
- client_max_body_size 50M;
+ client_max_body_size {{ limit_action_blob_size | default('50m') | upper }};
rewrite_log on;
{# change log format to display the upstream information #}
diff --git a/common/scala/src/main/resources/application.conf
b/common/scala/src/main/resources/application.conf
index feaa96095c..ee5544efe1 100644
--- a/common/scala/src/main/resources/application.conf
+++ b/common/scala/src/main/resources/application.conf
@@ -6,8 +6,15 @@ include "logging"
akka.http {
client {
- parsing.illegal-header-warnings = off
- parsing.max-chunk-size = 50m
+ request-timeout = 65s
+
+ idle-timeout = 70s
+
+ parsing {
+ illegal-header-warnings = off
+ max-chunk-size = 50m
+ max-content-length = 50m
+ }
}
host-connection-pool {
@@ -168,6 +175,11 @@ whisk {
std = 256 m
}
+ # action blob size limit configuration
+ action {
+ blob-size = 48 m
+ }
+
# action log-limit configuration
log-limit {
min = 0 m
diff --git a/common/scala/src/main/scala/whisk/core/WhiskConfig.scala
b/common/scala/src/main/scala/whisk/core/WhiskConfig.scala
index 0c937ae372..4ce02108d7 100644
--- a/common/scala/src/main/scala/whisk/core/WhiskConfig.scala
+++ b/common/scala/src/main/scala/whisk/core/WhiskConfig.scala
@@ -218,6 +218,7 @@ object ConfigKeys {
val memory = "whisk.memory"
val timeLimit = "whisk.time-limit"
val logLimit = "whisk.log-limit"
+ val actionBlobSize = "whisk.action.blob-size"
val activation = "whisk.activation"
val activationPayload = s"$activation.payload"
val userEvents = "whisk.user-events"
diff --git a/common/scala/src/main/scala/whisk/core/entity/Exec.scala
b/common/scala/src/main/scala/whisk/core/entity/Exec.scala
index a281144a62..9f9c667b38 100644
--- a/common/scala/src/main/scala/whisk/core/entity/Exec.scala
+++ b/common/scala/src/main/scala/whisk/core/entity/Exec.scala
@@ -19,7 +19,6 @@ package whisk.core.entity
import java.nio.charset.StandardCharsets
-import scala.language.postfixOps
import scala.util.matching.Regex
import spray.json._
@@ -29,6 +28,8 @@ import whisk.core.entity.ExecManifest._
import whisk.core.entity.size.SizeInt
import whisk.core.entity.size.SizeOptionString
import whisk.core.entity.size.SizeString
+import whisk.core.ConfigKeys
+import pureconfig.loadConfigOrThrow
/**
* Exec encodes the executable details of an action. For black
@@ -212,7 +213,9 @@ protected[core] case class SequenceExecMetaData(components:
Vector[FullyQualifie
protected[core] object Exec extends ArgNormalizer[Exec] with
DefaultJsonProtocol {
- val sizeLimit = 48 MB
+ import whisk.core.entity.size.pureconfigReader
+
+ val sizeLimit = loadConfigOrThrow[ByteSize](ConfigKeys.actionBlobSize)
// The possible values of the JSON 'kind' field for certain runtimes:
// - Sequence because it is an intrinsic
@@ -342,7 +345,7 @@ protected[core] object Exec extends ArgNormalizer[Exec]
with DefaultJsonProtocol
protected[core] object ExecMetaDataBase extends
ArgNormalizer[ExecMetaDataBase] with DefaultJsonProtocol {
- val sizeLimit = 48 MB
+ val sizeLimit = Exec.sizeLimit
// The possible values of the JSON 'kind' field for certain runtimes:
// - Sequence because it is an intrinsic
diff --git
a/core/invoker/src/main/scala/whisk/core/containerpool/docker/DockerContainerFactory.scala
b/core/invoker/src/main/scala/whisk/core/containerpool/docker/DockerContainerFactory.scala
index 3f2ee86406..c51eedb634 100644
---
a/core/invoker/src/main/scala/whisk/core/containerpool/docker/DockerContainerFactory.scala
+++
b/core/invoker/src/main/scala/whisk/core/containerpool/docker/DockerContainerFactory.scala
@@ -18,6 +18,7 @@
package whisk.core.containerpool.docker
import akka.actor.ActorSystem
+
import scala.concurrent.Await
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
@@ -30,11 +31,14 @@ import whisk.core.containerpool.ContainerFactoryProvider
import whisk.core.entity.ByteSize
import whisk.core.entity.ExecManifest
import whisk.core.entity.InstanceId
+
import scala.concurrent.duration._
import java.util.concurrent.TimeoutException
+
import pureconfig._
import whisk.core.ConfigKeys
import whisk.core.containerpool.ContainerArgsConfig
+import whisk.core.entity.Exec.sizeLimit
case class DockerContainerFactoryConfig(useRunc: Boolean)
@@ -70,7 +74,7 @@ class DockerContainerFactory(instance: InstanceId,
userProvidedImage = userProvidedImage,
memory = memory,
cpuShares = cpuShares,
- environment = Map("__OW_API_HOST" -> config.wskApiHost),
+ environment = Map("__OW_API_HOST" -> config.wskApiHost,
"__OW_ACTION_BLOB_SIZE" -> s"${sizeLimit.toMB}"),
network = containerArgsConfig.network,
dnsServers = containerArgsConfig.dnsServers,
name = Some(name),
diff --git
a/core/invoker/src/main/scala/whisk/core/containerpool/kubernetes/KubernetesContainerFactory.scala
b/core/invoker/src/main/scala/whisk/core/containerpool/kubernetes/KubernetesContainerFactory.scala
index e332b84861..4dfbe041ae 100644
---
a/core/invoker/src/main/scala/whisk/core/containerpool/kubernetes/KubernetesContainerFactory.scala
+++
b/core/invoker/src/main/scala/whisk/core/containerpool/kubernetes/KubernetesContainerFactory.scala
@@ -30,6 +30,7 @@ import whisk.common.TransactionId
import whisk.core.containerpool.Container
import whisk.core.containerpool.ContainerFactory
import whisk.core.containerpool.ContainerFactoryProvider
+import whisk.core.entity.Exec.sizeLimit
import whisk.core.entity.ByteSize
import whisk.core.entity.ExecManifest.ImageName
import whisk.core.entity.InstanceId
@@ -78,7 +79,7 @@ class KubernetesContainerFactory(label: String, config:
WhiskConfig)(implicit ac
image,
userProvidedImage,
memory,
- environment = Map("__OW_API_HOST" -> config.wskApiHost),
+ environment = Map("__OW_API_HOST" -> config.wskApiHost,
"__OW_ACTION_BLOB_SIZE" -> s"${sizeLimit.toMB}"),
labels = Map("invoker" -> label))
}
}
diff --git a/docs/deploy.md b/docs/deploy.md
index 5fef484c57..6493e38aba 100644
--- a/docs/deploy.md
+++ b/docs/deploy.md
@@ -57,3 +57,30 @@ Using docker-runc obtains significantly better performance,
but requires that th
2017-09-29T20:15:54.551Z] [ERROR] [#sid_102] [RuncClient] code: 1, stdout: ,
stderr: json: cannot unmarshal object into Go value of type []string
[marker:invoker_runc.pause_error:6830148:259]
```
When a docker-runc operations results in an error, the container will be
killed by the invoker. This results in missed opportunities for container
reuse and poor performance. Setting INVOKER_USE_RUNC to false can be used as a
workaround until proper usage of docker-runc can be configured for the
deployment.
+
+# System configuration for large size actions.
+
+Notice that current OpenWhisk implementation is still not suitable to deal
with large size action. The recommended way is to refactor applications into
smaller granularities.
+
+To create a large size action, you have to build the system with large size
tolerable limits.
+
+## Size limit
+
+Set `limit_action_code_size` for nginx, controller, invoker and database (only
support couchdb, currently).
+
+## Timeout limit
+
+The timeout depends on how large the system resource is. Therefore, several
timeout limits will be configured manually and separately. Here's some config
you might need to set:
+
+* Internal http timeout:
`akka.http.[client/server].[request-timeout/idle-timeout]`.
+* Database query timeout: i.e. `query_server_config.os_process_limit` in
couchdb.
+* Nginx: `proxy_read_timeout`.
+* [Aaction invocation
timeout](./reference.md#per-action-timeout-ms-default-60s)
+
+## System tunning
+
+Finally, you have to make sure the system have enough resources, including:
+
+* JVM heap size: `controller_heap` and `invoker_heap`.
+* If you are running OpenWhisk in sandboxed environment (i.e. VMs or Docker
for mac), make sure the resource is allocate sufficiently.
+* [Action memory limit](./reference.md#per-action-memory-mb-default-256mb)
diff --git a/docs/reference.md b/docs/reference.md
index d23ed92b20..8324206cec 100644
--- a/docs/reference.md
+++ b/docs/reference.md
@@ -465,7 +465,7 @@ The following table lists the default limits for actions.
| logs | a container is not allowed to write more than N MB to stdout | per
action | MB | 10 |
| concurrent | no more than N activations may be submitted per namespace
either executing or queued for execution | per namespace | number | 100 |
| minuteRate | no more than N activations may be submitted per namespace per
minute | per namespace | number | 120 |
-| codeSize | the maximum size of the actioncode | not configurable, limit per
action | MB | 48 |
+| codeSize | the maximum size of the actioncode | configurable during
deployment, limit per action | MB | 48 |
| parameters | the maximum size of the parameters that can be attached | not
configurable, limit per action/package/trigger | MB | 1 |
| result | the maximum size of the action result | not configurable, limit per
action | MB | 1 |
@@ -484,8 +484,8 @@ The following table lists the default limits for actions.
* A user can change the limit when creating or updating the action.
* Logs that exceed the set limit are truncated and a warning is added as the
last output of the activation to indicate that the activation exceeded the set
log limit.
-### Per action artifact (MB) (Fixed: 48MB)
-* The maximum code size for the action is 48MB.
+### Per action artifact (MB) (Default: 48MB)
+* The maximum code size for the action is fixed on deployment.
* It is recommended for a JavaScript action to use a tool to concatenate all
source code including dependencies into a single bundled file.
### Per activation payload size (MB) (Fixed: 1MB)
diff --git
a/tests/src/test/scala/whisk/core/containerpool/docker/test/DockerContainerFactoryTests.scala
b/tests/src/test/scala/whisk/core/containerpool/docker/test/DockerContainerFactoryTests.scala
index 31139dc802..90395f26ff 100644
---
a/tests/src/test/scala/whisk/core/containerpool/docker/test/DockerContainerFactoryTests.scala
+++
b/tests/src/test/scala/whisk/core/containerpool/docker/test/DockerContainerFactoryTests.scala
@@ -42,6 +42,7 @@ import whisk.core.containerpool.docker.RuncApi
import whisk.core.entity.ExecManifest
import whisk.core.entity.InstanceId
import whisk.core.entity.size._
+import whisk.core.entity.Exec.sizeLimit
@RunWith(classOf[JUnitRunner])
class DockerContainerFactoryTests
@@ -81,6 +82,8 @@ class DockerContainerFactoryTests
"net1",
"-e",
"__OW_API_HOST=://:",
+ "-e",
+ s"__OW_ACTION_BLOB_SIZE=${sizeLimit.toMB}",
"--dns",
"dns1",
"--dns",
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
With regards,
Apache Git Services