High performance guppe setup (#62)

* add worker script and container

* remove port bindings from worker

* another worker

* try replicas

* 8 workers

* try replicating web server

* document docker swarm commands

* use image instead of build as required by swarm
This commit is contained in:
Will Murphy 2022-11-06 14:43:54 -06:00 committed by GitHub
parent eb0871c9eb
commit 1a10e2ce9f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 79 additions and 5 deletions

View file

@ -19,14 +19,15 @@ fallback user profile discovery.
## Installation
`Dockerfile` and `docker-compose.yml` are provided for easy install
Guppe uses Docker Swarm for easy load balancing Web server replicas
```
git clone https://github.com/wmurphyrd/guppe.git
cd guppe
cp .env.defaults .env
echo DOMAIN=yourdomain.com >> .env
docker-compose up --build -d
docker swarm init --advertise-addr 127.0.0.1
docker stack deploy --compose-file docker-compose.yml guppe
```
## Updating
@ -41,7 +42,7 @@ Fetch latest code & restart server:
```
git pull
docker-compose up --build -d
docker stack deploy --compose-file docker-compose.yml guppe
```
## Optional configuration

52
deliveryWorker.js Normal file
View file

@ -0,0 +1,52 @@
require('dotenv').config()
const MongoClient = require('mongodb').MongoClient
const { onShutdown } = require('node-graceful-shutdown')
const ActivitypubExpress = require('activitypub-express')
const { DOMAIN, DB_URL, DB_NAME } = process.env
const client = new MongoClient(DB_URL)
const routes = {
actor: '/u/:actor',
object: '/o/:id',
activity: '/s/:id',
inbox: '/u/:actor/inbox',
outbox: '/u/:actor/outbox',
followers: '/u/:actor/followers',
following: '/u/:actor/following',
liked: '/u/:actor/liked',
collections: '/u/:actor/c/:id',
blocked: '/u/:actor/blocked',
rejections: '/u/:actor/rejections',
rejected: '/u/:actor/rejected',
shares: '/s/:id/shares',
likes: '/s/:id/likes'
}
const apex = ActivitypubExpress({
domain: DOMAIN,
actorParam: 'actor',
objectParam: 'id',
itemsPerPage: 100,
routes
})
client.connect()
.then(async () => {
apex.store.db = client.db(DB_NAME)
let resumeDeliveryTimer
function deliver () {
apex.startDelivery()
// delivery will stop if the queue empties, ensure it keeps running when new work is available
// no effect if called while already running
resumeDeliveryTimer = setTimeout(deliver, 5000)
}
deliver()
onShutdown(async () => {
clearTimeout(resumeDeliveryTimer)
// time for last delivery to finish (need to fix in apex)
await new Promise(resolve => setTimeout(resolve, 3000))
await client.close()
console.log('Guppe delivery worker closed')
})
})

View file

@ -2,7 +2,10 @@ version: "3.8"
services:
guppe:
build: .
image: datatitian/guppe
deploy:
mode: replicated
replicas: 4
restart: always
ports:
- 443:443
@ -21,7 +24,24 @@ services:
driver: local
options:
max-size: '10m'
worker1:
image: datatitian/guppe
command: [ "node", "deliveryWorker.js" ]
deploy:
mode: replicated
replicas: 8
restart: always
env_file: '.env'
environment:
DB_URL: 'mongodb://mongodb:27017'
depends_on:
- mongodb
logging:
driver: local
options:
max-size: '10m'
mongodb:
image: mongo:4.2
restart: always

View file

@ -49,6 +49,7 @@ const apex = ActivitypubExpress({
actorParam: 'actor',
objectParam: 'id',
itemsPerPage: 100,
offlineMode: true, // delivery done in workers only
routes
})