1. Architektur
Der DQE One Server und alle seine Abhängigkeiten werden als Docker-Images bereitgestellt und mit Docker Compose auf einer Google Compute Engine-VM ausgeführt. Nach der Bereitstellung verbindet sich der Server mit einer Salesforce-Org, in der das DQE One-Paket installiert ist (verfügbar im AppExchange).
Dieses Dokument beschreibt eine mögliche Konfiguration, entweder mit einer direkt über HTTPS erreichbaren VM oder hinter einem GCP-Load-Balancer. Die Sicherheitsebene Ihrer eigenen Umgebung wird nicht behandelt.
Flussdiagramm
Das folgende Diagramm beschreibt alle eingehenden/ausgehenden Datenflüsse sowie die von der Anwendung benötigten IPs und Ports.
Sicherheitsmaßnahmen
Wir können kein Beispiel für die Implementierung der Sicherheitsebene liefern, das perfekt zu Ihrer Architektur passt. Wir können jedoch einige Empfehlungen geben, die für die Nutzung der Anwendung selbst relevant sind.
- Protokolle und Ports: Alle ausgehenden/eingehenden Datenflüsse der Anwendung erfolgen über HTTPS (Port 443). Es ist nicht notwendig, einen weiteren Port zum Internet zu öffnen. Die DQE-IPs, die erreichbar sein müssen, sind im vorherigen Diagramm beschrieben.
- IP-Filterung: Der DQE One Server muss nur von den Salesforce-Servern aus erreichbar sein. Es wird daher empfohlen, eingehende IPs mit einer VPC-Firewallregel oder einer Cloud Armor-Richtlinie zu filtern. Die Ausnahme ist die CustomUI-Oberfläche, die vom Webbrowser Ihrer Benutzer aus erreichbar sein muss: Erlauben Sie zusätzlich die öffentlichen IPs oder das VPN Ihres Unternehmens. Siehe die Liste der von Salesforce veröffentlichten IPs (vergessen Sie nicht die Hyperforce-IPs).
- Authentifizierungsprotokoll: Salesforce bietet nativ mehrere Protokolle, um Anfragen zwischen seinen Servern und dem DQE One Server abzusichern. Bei der Konfiguration der Connected App „DQE One Customer“ in Ihrer Org können Sie die Authentifizierungsmethode „Basic Auth“ auswählen und Ihre Anwendungs-Firewall entsprechend konfigurieren.
Wenn die VM direkt aus dem Internet erreichbar ist, benötigt sie einen DNS-Eintrag und ein zugehöriges SSL-Zertifikat, die auf sie verweisen.
Wenn sich die VM hinter einem GCP-Load-Balancer befindet, werden der DNS-Eintrag und das SSL-Zertifikat auf dem Load Balancer installiert, der den Datenverkehr an die VM in Ihrer VPC weiterleitet.
Empfehlung
Dieser Abschnitt listet die Komponenten auf, die für die Installation der DQE One Server-Instanz auf GCP erforderlich sind.
Hinweis: Die Schätzungen basieren auf 1 Million Datensätzen. Je nach Volumen der verarbeiteten Datenbanken kann es notwendig sein, den Arbeitsspeicher zu erhöhen, um die Verarbeitungszeiten zu optimieren.
- Compute Engine-VM: empfohlen Ubuntu 22.04 oder 24.04 LTS, zum Beispiel Maschinentyp
e2-standard-4(4 vCPU / 16 GB). - Load Balancer: nicht erforderlich, kann aber verwendet werden, falls bereits vorhanden.
| Komponente | Minimum | Empfohlen |
|---|---|---|
| CPU | 4 vCPU | 8 vCPU |
| RAM | 12 GB | 16 GB |
| Festplatte | 30 GB SSD | 60 GB SSD |
Hinweis: Der Worker allein kann während einer Verarbeitung bis zu 5 GB Arbeitsspeicher belegen. Weitere Informationen zu VM-Instanzen finden Sie in der Google Cloud-Dokumentation.
Zusammensetzung und Dienste
Der DQE One Server stellt die Dienste und APIs bereit, die Salesforce über die DQE One-App aufruft. Er besteht aus den folgenden Diensten, die alle in der in 2.4 beschriebenen Datei docker-compose.yml definiert sind.
Webanwendung (web)
Ein Backend-Container, der eine Microservices-Anwendung enthält. Diese Anwendung stellt alle APIs bereit, die zum Starten von Prozessen, zur Verwaltung von Verarbeitungswarteschlangen und zur Instanziierung von Workern aufgerufen werden. Sie hängt von Redis und RabbitMQ ab. Sie wird ausschließlich über Nginx unter dem Pfad /unify/ im Web bereitgestellt.
-
image: von DQE Software bereitgestellt und in der DQE Azure Container Registry gehostet:
<Name of the registry container>.azurecr.io/<name of the image> - environment: SFAPIVERSION, PORT, REDIS_URL, CLOUDAMQP_URL, CUSTOMUI, UNIFYSERVERURL
- command:
bash ./entrypoint.sh
Worker (worker)
Ein Backend-Container, der Warteschlangenaufgaben asynchron verarbeitet. Er entnimmt Aufgaben aus der RabbitMQ-Warteschlange und führt sie aus. Er verwendet dasselbe Image wie die Webanwendung und wird nicht im Web bereitgestellt.
- image: dasselbe Image wie die Webanwendung
- environment: SFAPIVERSION, WORKDIRPATH, REDIS_URL, CLOUDAMQP_URL
- command:
python -u ./unify/queue_worker.pyc
CustomUI (customui)
Eine Webanwendung mit der Oberfläche zur Konfiguration der Deduplizierungsregeln. Sie muss vom Webbrowser Ihrer Benutzer aus erreichbar sein, über Nginx auf dem Stammpfad /. Sie ruft außerdem einige Backend-APIs auf, um beispielsweise Metadaten aus dem CRM abzurufen.
- image: von DQE Software bereitgestellt
- environment: PORT, SESSION_SECRET
Redis (redis)
Eine Key/Value-Datenbank zum Speichern interner Betriebsschlüssel wie Salesforce-Org-Konfigurationen, Sitzungen usw.
Sie können das offizielle redis-Image verwenden. Als Sicherheitsmaßnahme blockieren manche Organisationen öffentliche Images und erlauben nur Images aus privaten Registries: Verwenden Sie in diesem Fall das kompatible Redis-Image, das DQE in seiner privaten Registry veröffentlicht.
- image:
redis:7.4-alpineoder das DQE-Image - volumes:
redis_data:/data(benanntes Docker-Volume)
RabbitMQ (rabbitmq)
Ein Warteschlangen-Manager, der Verarbeitungsanfragen empfängt und plant. Bis ein Prozess einem Worker zugewiesen und abgeschlossen wurde, verbleibt er in der Warteschlange. Dies sorgt auch für Ausfallsicherheit: Wird der Server neu gestartet, wird die Verarbeitung dort fortgesetzt, wo sie unterbrochen wurde.
Wie bei Redis können Sie das offizielle Image oder das Image aus der privaten DQE-Registry verwenden.
- image:
rabbitmq:3.13-management-alpineoder das DQE-Image - volumes:
rabbitmq_data:/var/lib/rabbitmq(benanntes Docker-Volume) - environment: RABBITMQ_DEFAULT_USER, RABBITMQ_DEFAULT_PASS, RABBITMQ_DEFAULT_VHOST
2. Installation
Zwei Szenarien sind möglich:
- Szenario 1 — VM direkt erreichbar: Die VM hat eine externe IP, und Nginx auf der VM übernimmt HTTPS mit Ihrem SSL-Zertifikat.
- Szenario 2 — VM hinter einem GCP-Load-Balancer: Ein External Application Load Balancer übernimmt HTTPS und leitet HTTP-Datenverkehr an die VM in Ihrer VPC weiter. Die VM benötigt keine externe IP.
Die Schritte sind für beide Szenarien gleich, mit Ausnahme der Nginx-Konfiguration und der Firewallregeln.
2.1. Voraussetzungen
Starten Sie die VM und verbinden Sie sich, zum Beispiel per SSH aus der Compute Engine-Konsole oder mit gcloud compute ssh. Weitere Details finden Sie in der Google Cloud-Dokumentation.
Docker-Installation
Installieren Sie Docker Engine und das Docker Compose-Plugin aus dem offiziellen Docker-Repository:
sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker
sudo usermod -aG docker $USERMelden Sie sich ab und wieder an, damit Ihr Benutzer Docker ohne sudo ausführen kann, und überprüfen Sie dann die Installation:
docker --version
docker compose versionDocker Compose
Docker Compose wird im vorherigen Schritt als Plugin installiert: Verwenden Sie docker compose (mit Leerzeichen). Die eigenständige docker-compose-Binärdatei wird nicht mehr benötigt.
NGINX-Installation
sudo apt-get update
sudo apt-get install -y nginx
sudo mkdir -p /etc/nginx/sslErstellen Sie die Datei /etc/nginx/sites-available/dqe-one mit dem Inhalt, der Ihrem Szenario entspricht.
Szenario 1 — VM direkt über HTTPS erreichbar. Kopieren Sie zuerst Ihr SSL-Zertifikat und den privaten Schlüssel nach /etc/nginx/ssl/:
server {
listen 80;
server_name <your-domain.com>;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name <your-domain.com>;
ssl_certificate /etc/nginx/ssl/<certificate>.pem;
ssl_certificate_key /etc/nginx/ssl/<private-key>.key;
ssl_protocols TLSv1.2 TLSv1.3;
access_log /var/log/nginx/dqeone.log;
error_log /var/log/nginx/dqeone-error.log error;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 300s;
# DQE One UI (CustomUI)
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://127.0.0.1:8001/;
}
# DQE One Server API — the trailing "/" removes the /unify/ prefix
location /unify/ {
proxy_pass http://127.0.0.1:8000/;
}
location /lookup {
proxy_pass http://127.0.0.1:8000;
}
location /static {
proxy_pass http://127.0.0.1:8000;
}
location /API {
proxy_pass http://127.0.0.1:8000;
}
}Szenario 2 — VM hinter einem GCP-Load-Balancer. HTTPS wird vom Load Balancer übernommen:
server {
listen 80;
access_log /var/log/nginx/dqeone.log;
error_log /var/log/nginx/dqeone-error.log error;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_read_timeout 300s;
# DQE One UI (CustomUI)
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://127.0.0.1:8001/;
}
# DQE One Server API — the trailing "/" removes the /unify/ prefix
location /unify/ {
proxy_pass http://127.0.0.1:8000/;
}
location /lookup {
proxy_pass http://127.0.0.1:8000;
}
location /static {
proxy_pass http://127.0.0.1:8000;
}
location /API {
proxy_pass http://127.0.0.1:8000;
}
}Aktivieren Sie die Konfiguration:
sudo ln -s /etc/nginx/sites-available/dqe-one /etc/nginx/sites-enabled/dqe-one
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx2.2. VPC-Firewallregeln
Führen Sie diese Befehle in Cloud Shell oder auf einem beliebigen Rechner mit der gcloud-CLI aus.
Szenario 1: Erlauben Sie HTTP/HTTPS nur aus den Salesforce-IP-Bereichen und den IPs Ihres Unternehmens:
gcloud compute instances add-tags <vm-name> --zone <zone> --tags dqe-one
gcloud compute firewall-rules create dqe-one-https \
--network <vpc-name> \
--direction INGRESS \
--allow tcp:80,tcp:443 \
--source-ranges <Salesforce IP ranges>,<admin VPN IP range> \
--target-tags dqe-oneSzenario 2: Erlauben Sie HTTP nur aus den IP-Bereichen des Google-Load-Balancers und der Health Checks. Filtern Sie Salesforce- und Unternehmens-IPs mit einer Cloud Armor-Richtlinie auf dem Load Balancer.
gcloud compute instances add-tags <vm-name> --zone <zone> --tags dqe-one
gcloud compute firewall-rules create dqe-one-lb \
--network <vpc-name> \
--direction INGRESS \
--allow tcp:80 \
--source-ranges 130.211.0.0/22,35.191.0.0/16 \
--target-tags dqe-oneErstellen Sie für Szenario 2 einen External Application Load Balancer mit einem HTTPS-Frontend (Ihr SSL-Zertifikat), einem Backend-Dienst, der auf eine Instanzgruppe mit der VM auf Port 80 verweist, und einem HTTP-Health-Check auf dem Pfad /. Weitere Details finden Sie in der Google Cloud-Dokumentation.
Hinweis: Die Ports 8000 und 8001 sind in der folgenden docker-compose.yml an 127.0.0.1 gebunden: Sie sind nur über Nginx erreichbar und dürfen in der Firewall nicht geöffnet werden.
2.3. Konfigurationsdateien
Erstellen Sie den Anwendungsordner und die Datei .env mit den von DQE Software bereitgestellten Werten:
sudo mkdir -p /opt/dqe-one
sudo chown $USER /opt/dqe-one
cd /opt/dqe-one
nano .env
nano docker-compose.ymlInhalt der Datei .env. Verwenden Sie sichere Passwörter ohne die Zeichen @ : / ? # (das RabbitMQ-Passwort wird in eine Verbindungs-URL eingefügt):
# Values provided by DQE Software
SERVER_IMAGE=<registry-url>/<dqe-one-server-image>:<tag>
CUSTOMUI_IMAGE=<registry-url>/<dqe-one-ui-image>:<tag>
REDIS_IMAGE=redis:7.4-alpine
RABBITMQ_IMAGE=rabbitmq:3.13-management-alpine
SFAPIVERSION=v65.0
# Strong passwords, without @ : / ? # (inserted into the AMQP URL)
RABBITMQ_USER=dqeone
RABBITMQ_PASSWORD=ChangeMe_Str0ngPassword
SESSION_SECRET=ChangeMe_LongRandomString2.4. DQE One Server — docker-compose.yml
Inhalt der Datei docker-compose.yml:
name: dqe-one
x-logging: &default-logging
driver: json-file
options:
max-size: "50m"
max-file: "5"
services:
customui:
image: ${CUSTOMUI_IMAGE}
container_name: custom-ui
restart: unless-stopped
logging: *default-logging
environment:
- PORT=8001
- SESSION_SECRET=${SESSION_SECRET}
ports:
- "127.0.0.1:8001:8001" # reachable only through Nginx
web:
image: ${SERVER_IMAGE}
container_name: one-server
hostname: oneserver
restart: unless-stopped
logging: *default-logging
depends_on:
redis:
condition: service_healthy
rabbitmq:
condition: service_healthy
environment:
- SFAPIVERSION=${SFAPIVERSION}
- PORT=8000
- REDIS_URL=redis://redis:6379
- CLOUDAMQP_URL=amqp://${RABBITMQ_USER}:${RABBITMQ_PASSWORD}@rabbitmq:5672/admin
- CUSTOMUI=http://customui:8001
- UNIFYSERVERURL=http://web:8000
ports:
- "127.0.0.1:8000:8000" # reachable only through Nginx
command: bash ./entrypoint.sh
worker:
image: ${SERVER_IMAGE}
container_name: queue-worker
restart: unless-stopped
logging: *default-logging
depends_on:
web:
condition: service_started
rabbitmq:
condition: service_healthy
environment:
- SFAPIVERSION=${SFAPIVERSION}
- WORKDIRPATH=/app/unify
- REDIS_URL=redis://redis:6379
- CLOUDAMQP_URL=amqp://${RABBITMQ_USER}:${RABBITMQ_PASSWORD}@rabbitmq:5672/admin
command: python -u ./unify/queue_worker.pyc
redis:
image: ${REDIS_IMAGE}
container_name: redis
hostname: redis
restart: unless-stopped
logging: *default-logging
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 10
rabbitmq:
image: ${RABBITMQ_IMAGE}
container_name: rabbitmq
hostname: rabbitmq
restart: unless-stopped
logging: *default-logging
environment:
- RABBITMQ_DEFAULT_USER=${RABBITMQ_USER}
- RABBITMQ_DEFAULT_PASS=${RABBITMQ_PASSWORD}
- RABBITMQ_DEFAULT_VHOST=admin
volumes:
- rabbitmq_data:/var/lib/rabbitmq
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"]
interval: 10s
timeout: 10s
retries: 12
start_period: 30s
volumes:
rabbitmq_data:
redis_data:Wichtige Punkte:
- Passwörter und Image-Namen werden aus der Datei
.envgelesen. - Redis und RabbitMQ müssen betriebsbereit sein, bevor die Webanwendung startet, und alle Container starten nach einem Neustart der VM automatisch neu.
- Die Protokolle werden rotiert (5 × 50 MB pro Container), damit sie die Festplatte nicht füllen können.
3. Launcher
Obwohl der Server auf GCP bereitgestellt wird, werden die DQE-Docker-Images über eine von DQE Software verwaltete Azure Container Registry bereitgestellt. Es wird kein Azure-Tool benötigt: Docker meldet sich direkt an.
3.1. Verbindung mit der DQE Azure Container Registry
docker login <registry-url> --username <Login provided by DQE>Geben Sie das von DQE bereitgestellte Passwort ein, wenn Sie dazu aufgefordert werden. Eine erfolgreiche Anmeldung zeigt Login Succeeded an.
3.2. Start von docker-compose.yml
cd /opt/dqe-one
docker compose pull
docker compose up -d
docker compose psErwartete Ausgabe — alle Dienste Up, Redis und RabbitMQ healthy:
NAME SERVICE STATUS
custom-ui customui Up
one-server web Up
queue-worker worker Up
rabbitmq rabbitmq Up (healthy)
redis redis Up (healthy)Wenn ein Container ständig neu startet, prüfen Sie seine Protokolle (ersetzen Sie web durch den Dienstnamen):
docker compose logs -f webÖffnen Sie abschließend https://<your-domain.com> in einem Browser, um zu prüfen, dass die DQE One-Oberfläche erreichbar ist. Prüfen Sie in Szenario 2 außerdem, dass das Backend im Load Balancer Healthy ist.
3.3. Aktualisierung
Wenn DQE Software eine neue Version bereitstellt, aktualisieren Sie die Image-Tags in der Datei .env und führen Sie dann Folgendes aus:
cd /opt/dqe-one
docker compose pull
docker compose up -d
Verknüpfung mit