> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kasoftware.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 叢集

> 如何配置多個知行之橋安裝協同工作以實現高可用性和延展性。

export const siteNameShort = "知行之橋";

export const siteName = "知行之橋";

叢集可以讓多個 {siteName} 安裝協同工作，用相同的配置處理相同的資料。工作負載可以水平分佈在 {siteNameShort} 叢集中，以提高延展性並確保可用性。

## 概觀

為了利用 {siteNameShort} 支援的高可用性和容錯移轉功能，應將應用程式安裝在同一伺服器叢集（同一叢集）的多個系統上。然後由負載平衡器在承載 {siteNameShort} 例項的多個系統之間分配傳入的流量。

<img src="https://mintcdn.com/qiao/U-KEZ9JbQY4Wqs1D/public/images/clustering_load_balancer.png?fit=max&auto=format&n=U-KEZ9JbQY4Wqs1D&q=85&s=3f266f0ea2a032919d6bfb0a4d977db2" alt="Cluster behind a load balancer" width="350" data-path="public/images/clustering_load_balancer.png" />

當配置叢集時，伺服器叢集中的每個 {siteNameShort} 安裝都使用相同的應用程式配置，處理磁碟上相同位置的資料，並將交易記錄在相同的資料庫表中。

因此，應用程式的多個例項表現得就像是一個例項，並且任何一個例項的關閉都不會破壞叢集的效能。

## 配置 {siteNameShort} 進行叢集

在叢集內的每個節點都安裝 {siteNameShort} 後，每個安裝都應該配置為使用相同的 *應用程式資料庫* 和 *應用程式資料目錄*。

### 許可

必須為叢集中的每個節點應用唯一的許可證金鑰。轉到每個節點的許可頁面並應用其中一個金鑰。應用程式在叢集的共享目錄中建立一個許可證檔案。許可證檔名包括共享目錄中兩個節點的計算機名稱。

### 應用程式資料庫

{siteNameShort} 使用資料庫來記錄交易歷史和發生在應用程式中的所有錯誤。{siteNameShort} 的每個例項都應該配置為使用同一個應用程式資料庫，以確保所有處理的檔案最終合併到資料庫中。

#### .NET 版本

在 .NET 版本中配置應用程式資料庫，必須將 `AppDb` 環境變數配置為包括正確的連接字串和提供程式。為此，請修改安裝目錄 `www` 資料夾中的 `Web.Config` 檔案。在此檔案中有一個被註釋掉的名為 *connectionStrings* 的 XML 元素，例如：

```xml theme={null}
<!-- connectionStrings>
 <add 
  name="AppDb" 
  connectionString="server=SQLSERVER_LOCATION;database=DATABASE_NAME;uid=USER_ID;password=PASSWORD;" 
  providerName="System.Data.SqlClient"
 />
</connectionStrings -->
```

取消 *connectionStrings* 元素的註釋，將 `connectionString` 和 `providerName` 屬性設定為所需資料庫的適當連線參數。如果 {siteNameShort} 可以成功地使用這個連接字串建立連線，那麼它將使用這個資料庫作為應用程式資料庫。

#### 內建 Java 伺服器

將跨平臺版本與內建 Jetty 伺服器一起使用時，應用程式資料庫在安裝目錄 webapp 資料夾中的 `arc.xml` 檔案中配置。在此伺服器配置檔案中，必須將 `APP_DB` 環境變數設定為包含所需資料庫適當連線參數的 JDBC 連接字串。例如：

```xml theme={null}
<Call name="setInitParameter">
 <Arg>APP_DB</Arg>
 <Arg>jdbc:cdata:mysql:Server=MySQLServer;Port=3306;Database=mysql;User=user;Password=password</Arg>
</Call>
```

如果 {siteNameShort} 可以成功地使用 `APP_DB` 連接字串建立連線，那麼它將使用該資料庫作為應用程式資料庫。

#### 外部 Java 伺服器

將跨平臺版本與外部 Java servlet（應用程式內建 Jetty 伺服器以外的任何伺服器）一起使用時，配置應用程式資料庫的細節取決於所使用的特定 servlet。使用適用於特定 servlet 的語法，在配置伺服器時使用以下其中一種方法：

* 定義一個包括目標資料庫連線屬性的 JNDI 資料來源。
* 將 `APP_DB` 環境變數設定為 JDBC 連接字串。

如果 {siteNameShort} 可以使用 JNDI 資料來源或 `APP_DB` 連接字串連線到資料庫，那麼它將使用該資料庫作為應用程式資料庫。

### 應用程式資料目錄

{siteNameShort} 將所有配置資料和應用程式資料儲存在磁碟上一個名為資料目錄的資料夾中。使用叢集時，{siteNameShort} 的每個例項都應該配置為使用同一個資料目錄。這確保了所有例項處理相同的檔案並使用相同的配置。

#### .NET 版本

在 .NET 版本中配置應用程式資料目錄，必須將 `AppDirectory` 環境變數設定為應建立目錄的路徑。為此，請修改安裝目錄 www 資料夾中的 `Web.Config` 檔案。在此檔案中有一個被註釋掉的名為 *AppDirectory* 的 XML 元素，其下方有一個名為 *appSettings* 的元素，可以在其中指定自定義資料目錄位置：

```xml theme={null}
<!-- appSettings>
 <add key="AppDirectory" value="C:\\directory\\subdirectory\\subdirectory\\" />
</appSettings -->
```

取消 *appSettings* 元素的註釋，將 `AppDirectory` 鍵值設定為磁碟上資料目錄的適當路徑。如果 {siteNameShort} 可以找到該路徑，並且在給定路徑上具有適當的讀寫權限，它將在指定目錄中建立資料資料夾。

#### 內建 Java 伺服器

將跨平臺版本與內建 Jetty 伺服器一起使用時，應用程式資料目錄在安裝目錄 webapp 資料夾中的 `arc.xml` 檔案中配置。在此伺服器配置檔案中，必須將 `AppDirectory` 環境變數設定為所需目錄的路徑。以下範例演示了將資料目錄設定為已掛載驅動器上的共享資料夾時的情況：

```xml theme={null}
<Call name="setInitParameter">
 <Arg>AppDirectory</Arg>
 <Arg>/mnt/shared/arc</Arg>
</Call>
```

如果 {siteNameShort} 可以找到該路徑，並且在給定路徑上具有適當的讀寫權限，它將在指定目錄中建立資料資料夾。

#### 外部 Java 伺服器

將跨平臺版本與外部 Java servlet（應用程式內建 Jetty 伺服器以外的任何伺服器）一起使用時，配置應用程式資料目錄的細節取決於所使用的特定 servlet。使用適用於特定 servlet 的語法，必須將 `AppDirectory` 環境變數設定為所需目錄的路徑。

如果 {siteNameShort} 可以找到 `AppDirectory` 路徑，並且在給定路徑上具有適當的讀寫權限，它將在指定目錄中建立資料資料夾。

### 鎖與並行

{siteNameShort} 使用鎖來確保多個例項不會相互干擾或兩次處理同一個檔案。在叢集環境中，有效的鎖定對於保持吞吐量和防止衝突至關重要。因此，強烈建議不要跨多個伺服器場對 {siteNameShort} 例項進行叢集，因為這樣可能會產生檔案系統延遲。

為 {siteNameShort} 的每個例項設定一個共享的應用程式目錄足以確保每個例項都遵守檔案鎖。

### 配置反向代理

反向代理是位於用戶端和後端伺服器之間的伺服器，用於攔截傳入流量並將其轉寄到適當的目的地。配置得當時，反向代理可以透過請求頭轉寄保留真實的用戶端 IP 地址，同時保護後端基礎設施免於直接暴露。這種架構提供了負載平衡、增強安全性、快取和 SSL 終結等優勢。

當反向代理透過 `X-Forwarded-For` 等請求頭轉寄用戶端資訊時，限制受信任的代理至關重要。如果未明確僅信任已知的代理 IP 地址，惡意使用者可能會偽造這些請求頭來欺騙其來源，從而可能繞過安全控制或日誌記錄機制。

#### 跨平臺版（Cross-Platform Edition）

要在跨平臺版中配置反向代理，請將 `arc.properties` 檔案中的 [proxyMode](../installation/arc-properties-configuration#cdata-http-proxymode) 設定為 true，如下字串所示：`cdata.http.proxyMode=true`。

當 `proxyMode=true` 時，內嵌的 Jetty 伺服器將使用 `ForwardedRequestCustomizer` 從轉寄的請求頭中提取並應用真實的用戶端 IP。

如果使用外部 Java Servlet 容器，請在 Servlet 級別配置請求重寫，以適當地處理轉寄的請求頭。

#### .NET 版

要在 .NET 版中配置反向代理，必須在 **安全性** 頁面的 [代理設定](./settings/proxy-settings) 部分的 **HTTP 轉寄請求頭** 欄位中，提供一個以逗號分隔的清單，包含應用程式應用於確定用戶端 IP 地址的請求頭名稱。

#### 範例：使用 nginx 代理設定反向代理

確保用戶端無法欺騙用於轉寄 IP 地址的請求頭是代理伺服器的責任。以下範例說明了包含反向代理設定的代理配置。

```
location /arc/ {
  proxy_pass http://localhost:8080/;
  proxy_set_header Host              $host;
  proxy_set_header Referer           $http_referer;
  proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_set_header X-Forwarded-Port  $server_port;
  proxy_set_header X-NginX-Proxy     true;
  proxy_redirect http://localhost:8008/ http://$host:8008/arc/;
}
  # Declare all trusted IP or CIDR
  set_real_ip_from 192.168.1.100;
  set_real_ip_from 10.0.0.0/8;

  # Define the request header field whose value will be used to replace the client address
  real_ip_header X-Forwarded-For;

  # Enable recursive resolution to skip all trusted proxy IPs from X-Forwarded-For
  real_ip_recursive on
  
  # Optionally, set the real client IP to a new header
  Jetty_Forwarded-For: $remote_addr
```

此配置透過僅明確信任指定的代理 IP（192.168.1.100 和 10.0.0.0/8）來防止請求頭欺騙。如果惡意使用者偽造了 `X-Forwarded-For` 請求頭，nginx 將忽略它，並使用透過受信任代理進入的、最接近用戶端的 IP。
