From b0b5807c8b98637cdf277ffa21deec4af930dda8 Mon Sep 17 00:00:00 2001 From: immber Date: Tue, 8 Jan 2019 16:39:06 -0800 Subject: [PATCH] added scaling talk --- docs/source/01-04-planning-architecture.md | 35 +++++++++++++++++++++ docs/source/images/ServerArch.png | Bin 0 -> 27124 bytes 2 files changed, 35 insertions(+) create mode 100644 docs/source/images/ServerArch.png diff --git a/docs/source/01-04-planning-architecture.md b/docs/source/01-04-planning-architecture.md index d11ca4ac2..de1cfe803 100644 --- a/docs/source/01-04-planning-architecture.md +++ b/docs/source/01-04-planning-architecture.md @@ -19,3 +19,38 @@ Application servers: c4.xlarge (16 VM nginx + Talk VM machine pairs) Mongo nodes: 3x c3.medium (large db cluster, 1 master, 2 read replicas) If you need help with Talk performance or want custom scaling help or recommendations, let us know by logging a ticket and one of our engineers will get in touch with you: https://support.coralproject.net + +## How to Scale Talk Components +### Scaling the Talk Application + +In addition to scaling by adding additional app servers, Talk as a server component can flex to various roles. Depending on the desired configuration the roles can be split up to ensure high availability, and best matching to underlying host resources. + +There are three components to the Talk application that can be served independently or in combination on a single thread: API Server, WebSockets, and Jobs + +![ServerArchitectureDiagram](/talk/images/ServerArch.png) + +In the diagram we see the difference between a Typical configuration (which just adds additional Talk application instances) vs the Split configuration where different Talk components could be spread across different machine resources to optimize infrastructure utilization. +See [Serving the Application](/talk/configuration-cli-tools/#serving-the-application) + +### Scaling Redis + +Redis serves as a general cache and pub/sub broker. We treat all the data stored in Redis as ephemeral, so using as a cache serves us well for Talk to synchronize expensive query caches. It also serves as our pub/sub broker for use with live updates as propagated through the GraphQL subscription system. For this reason it is not recommended to implement multiple instances of Redis. + +### Scaling MongoDB + +MongoDB is treated as our general store for persisted data. Talk supports the most common strategies for scaling MongoDB instances including replicas and/or sharding. Depending on your specific data use cases, refer to MongoDBs documentation for more information about scaling https://www.mongodb.com/mongodb-scale. + +### Load Balancer +While this subject lives outside the Talk ecosystem, it is critical for application delivery. For websockets to work correctly, a load balancer must be selected that can support long lived connections that are required for websockets to work. + +## Running Talk in Production + +When you are ready to launch your production instance of Talk update your NODE_ENV environment variable from `development` to `production` mode. + +Then launch talk with `yarn start` or with the command `NODE_ENV=production ./bin/cli-serve -j -w` + + + + + + diff --git a/docs/source/images/ServerArch.png b/docs/source/images/ServerArch.png new file mode 100644 index 0000000000000000000000000000000000000000..aed5ffccaba6082506f1ba65ff68ff075485d0b0 GIT binary patch literal 27124 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 literal 0 HcmV?d00001