升訊威線上客服系統的並行高效能資料處理技術:高效能OSS檔案儲存

2023-11-13 12:00:50

我在業餘時間開發維護了一款免費開源的升訊威線上客服系統,也收穫了許多使用者。對我來說,只要能獲得使用者的認可,就是我最大的動力。

最近客服系統成功經受住了客戶現場組織的壓力測試,獲得了客戶的認可。
客戶組織多名客服上線後,所有員工同一時間開啟訪客頁面瘋狂不停的給線上客服發訊息,系統穩定無異常無掉線,客服回覆訊息正常。訊息實時到達無任何延遲。

https://kf.shengxunwei.com/


我會通過一系列的文章詳細分析升訊威線上客服系統的並行高效能技術是如何實現的,使用了哪些方案以及具體的做法。本文將介紹如何為多執行緒處理同步資料。

先看實現效果

客服端

訪客端

什麼是物件儲存OSS

OSS具有與平臺無關的RESTful API介面,您可以在任何應用、任何時間、任何地點儲存和存取任意型別的資料。

您可以使用API、SDK包或者OSS遷移工具輕鬆地將海量資料移入或移出阿里雲OSS。資料儲存到OSS以後,您可以選擇標準儲存(Standard)作為移動應用、大型網站、圖片分享或熱點音視訊的主要儲存方式,也可以選擇成本更低、儲存期限更長的低頻存取儲存(Infrequent Access)、歸檔儲存(Archive)、冷歸檔儲存(Cold Archive)或者深度冷歸檔(Deep Cold Archive)作為不經常存取資料的儲存方式。

OSS工作原理

資料以物件(Object)的形式儲存在OSS的儲存空間(Bucket )中。如果要使用OSS儲存資料,您需要先建立Bucket,並指定Bucket的地域、存取許可權、儲存型別等屬性。建立Bucket後,您可以將資料以Object的形式上傳到Bucket,並指定Object的檔名(Key)作為其唯一標識。

OSS以HTTP RESTful API的形式對外提供服務,存取不同地域需要不同的存取域名(Endpoint)。當您請求存取OSS時,OSS通過使用存取金鑰(AccessKey ID和AccessKey Secret)對稱加密的方法來驗證某個請求的傳送者身份。

Object操作在OSS上具有原子性和強一致性。

開始設定存取憑證

您可以選擇以下型別的存取憑證。

  • 臨時存取憑證:對於需要高安全性的場景,例如臨時授權應用存取OSS,建議使用臨時存取憑證。臨時存取憑證可以限制存取的有效期,從而減少存取憑證洩露的風險。此外,臨時存取憑證支援許可權控制,可以有效地避免許可權過大的問題。更多資訊,請參見使用臨時存取憑證。

  • 長期存取憑證:出於安全性考慮,不建議您使用長期存取憑證,建議您使用臨時存取憑證。對於需要便利性的場景,長期存取憑證可以在較長時間內免除多次重新整理的麻煩。建議每三個月更換一次長期存取憑證,以提高賬號的安全性。當長期存取憑證洩露或者不再使用時,應該及時刪除或者禁用相關的存取憑證,以免造成安全風險。更多資訊,請參見使用長期存取憑證。

建立 OSS 儲存空間

在支援資源組的地域建立儲存空間時,您可以為Bucket設定資源組。關於資源組的更多資訊。


import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.CreateBucketRequest;
import com.aliyun.oss.model.DataRedundancyType;
import com.aliyun.oss.model.StorageClass;

public class CreateBucket {

    public static void main(String[] args) throws Exception {
        // yourEndpoint填寫Bucket所在地域對應的Endpoint。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 從環境變數中獲取存取憑證。執行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填寫Bucket名稱。
        String bucketName = "examplebucket";
        // 填寫資源組ID。如果不填寫資源組ID,則建立的Bucket屬於預設資源組。
        //String rsId = "rg-aek27tc****";


        // 建立OSSClient範例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);

        try {
            // 建立CreateBucketRequest物件。
            CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);

            // 如果建立儲存空間的同時需要指定儲存型別、儲存空間的讀寫許可權、資料容災型別, 請參考如下程式碼。
            // 此處以設定儲存空間的儲存型別為標準儲存為例介紹。
            //createBucketRequest.setStorageClass(StorageClass.Standard);
            // 資料容災型別預設為本地冗餘儲存,即DataRedundancyType.LRS。如果需要設定資料容災型別為同城冗餘儲存,請設定為DataRedundancyType.ZRS。
            //createBucketRequest.setDataRedundancyType(DataRedundancyType.ZRS);
            // 設定儲存空間讀寫許可權為公共讀,預設為私有。
            //createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);

            // 在支援資源組的地域建立Bucket時,您可以為Bucket設定資源組。
            //createBucketRequest.setResourceGroupId(rsId);

            // 建立儲存空間。
            ossClient.createBucket(createBucketRequest);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

簡單上傳

簡單上傳是指通過PutObject方法上傳單個檔案(Object)。簡單上傳包括流式上傳和檔案上傳,流式上傳使用InputStream作為OSS檔案的資料來源,檔案上傳使用本地檔案作為OSS檔案的資料來源。本文介紹如何使用流式上傳和檔案上傳方式上傳檔案。

以下程式碼用於將字串上傳到目標儲存空間examplebucket中exampledir目錄下的exampleobject.txt檔案。


import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import java.io.ByteArrayInputStream;

public class Demo {

    public static void main(String[] args) throws Exception {
        // Endpoint以華東1(杭州)為例,其它Region請按實際情況填寫。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 從環境變數中獲取存取憑證。執行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填寫Bucket名稱,例如examplebucket。
        String bucketName = "examplebucket";
        // 填寫Object完整路徑,完整路徑中不能包含Bucket名稱,例如exampledir/exampleobject.txt。
        String objectName = "exampledir/exampleobject.txt";

        // 建立OSSClient範例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);

        try {
            // 填寫字串。
            String content = "Hello OSS,你好世界";

            // 建立PutObjectRequest物件。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new ByteArrayInputStream(content.getBytes()));

            // 如果需要上傳時設定儲存型別和存取許可權,請參考以下範例程式碼。
            // ObjectMetadata metadata = new ObjectMetadata();
            // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
            // metadata.setObjectAcl(CannedAccessControlList.Private);
            // putObjectRequest.setMetadata(metadata);
           
            // 上傳字串。
            PutObjectResult result = ossClient.putObject(putObjectRequest);            
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}   


簡介

升訊威線上客服與行銷系統是一款客服軟體,但更重要的是一款行銷利器。

https://kf.shengxunwei.com/

  • 可以追蹤正在存取網站或使用 APP 的所有訪客,收集他們的瀏覽情況,使客服能夠主動出擊,施展話術,促進成單。
    訪* 客端在 PC 支援所有新老瀏覽器。包括不支援 WebSocket 的 IE8 也能正常使用。
  • 行動端支援所有手機瀏覽器、APP、各大平臺的公眾號對接。
  • 支援訪客資訊互通,可傳輸訪客標識、名稱和其它任意資訊到客服系統。
  • 具備一線專業技術水平,網路中斷,拔掉網線,手機飛航模式,不丟訊息。同類軟體可以按視訊方式對比測試。

希望能夠打造: 開放、開源、共用。努力打造 .net 社群的一款優秀開源產品。

鐘意的話請給個贊支援一下吧,謝謝~