Nginx集群之WCF大文件上傳及下載(支持6G傳輸)

来源:http://www.cnblogs.com/yongfeng/archive/2017/11/24/7890372.html
-Advertisement-
Play Games

Nginx的匹配規則,很容易幫助我們劃分WCF服務的網段,從而實現企業數據信息系統多區域劃分,如小數據的微服務、傳輸數據文件的服務、即時通信服務、或者郵件服務,相當於構建了一條企業內部信息化的數據匯流排(DataBus)。Nginx的匹配原則能夠有效的分配URL,將流式數據分發給相應的服務處理,並且在... ...


目錄

1       大概思路... 1

2       Nginx集群之WCF大文件上傳及下載... 1

3       BasicHttpBinding相關配置解析... 2

4       編寫WCF服務、客戶端程式... 3

5       URL保留項... 8

6       部署WCF服務程式到區域網內1台PC機... 8

7       Nginx集群配置搭建... 9

8       WCF客戶端程式的運行結果... 11

9       總結... 13

 

1       大概思路

l  Nginx集群之WCF大文件上傳及下載

l  BasicHttpBinding相關配置解析

transferMode、messageEncoding、maxReceivedMessageSize、receiveTimeout、sendTimeout

l  編寫WCF服務、客戶端程式

l  URL保留項

l  部署WCF服務程式到區域網內1台PC機

l  Nginx集群配置搭建

l  WCF客戶端程式的運行結果

l  總結

2       Nginx集群之WCF大文件上傳及下載

Nginx的匹配規則,很容易幫助我們劃分WCF服務的網段,從而實現企業數據信息系統多區域劃分,如小數據的微服務、傳輸數據文件的服務、即時通信服務、或者郵件服務,相當於構建了一條企業內部信息化的數據匯流排(DataBus)。

以下是本文講述的主要結構圖:

客戶端以BasicHttpBinding訪問Nginx的功能變數名稱zhyongfeng.com/fileupload,然後Nginx進行負載均衡,將消息分發到後端任意一臺WCF上傳下載伺服器的PC機,然後進行上傳文件至“冷數據”處,又從“冷數據”處下載文件。

針對“冷數據”可以劃分目錄,建立單獨的FTP伺服器及WCF伺服器,進行操作處理。如下圖所示:

以下是WCF上傳下載伺服器的架構:

 

3       BasicHttpBinding相關配置解析

basicHttpBinding相關配置,具體參考:

https://msdn.microsoft.com/zh-cn/library/system.servicemodel.basichttpbinding.aspx

以下是主要應用到的配置

transferMode

獲取或設置一個值,該值指示是通過緩衝處理還是流處理來發送消息。(繼承自 HttpBindingBase。)

messageEncoding

獲取或設置是使用 MTOM 還是文本對 SOAP 消息進行編碼。

maxReceivedMessageSize

獲取或設置最大大小,以位元組為單位,可以使用此綁定配置的通道上接收的消息。(繼承自 HttpBindingBase。)

receiveTimeout

獲取或設置連接在撤消之前保持非活動狀態的最大時間間隔,在此時間間隔內未接收任何應用程式消息。(繼承自 Binding。)

sendTimeout

獲取或設置在傳輸引發異常之前可用於完成寫入操作的時間間隔。(繼承自 Binding。)

 

針對MTOM編碼和非同步調用的性能改善,可以參照論文:

利用MTOM編碼和非同步調用改進流傳輸的性能.pdf

 

4       編寫WCF服務、客戶端程式

l  WCF服務程式

Program.cs

using System.ServiceModel;
using Service;
using System;

namespace FileTransferHosting
{
    class Program
    {
        static void Main(string[] args)
        {
            using (ServiceHost host = new ServiceHost(typeof(FileTransferOperation)))
            {
                host.Opened += delegate
                {
                    Console.WriteLine(host.Description.Endpoints[0].Address.Uri + "已經啟動,按任意鍵終止服務!");
                };

                host.Open();
                Console.Read();
            }
        }
    }
}

FileTransferOperation.cs

using Service.Interface;
using System;
using System.IO;
using System.ServiceModel;

namespace Service
{
    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class FileTransferOperation : IFileTransferOperation
    {
        /// <summary>
        /// 上傳文件
        /// </summary>
        /// <param name="remoteFile"></param>
        public void UploadLoad(RemoteFileInfo remoteFile)
        {
            StreamToFile(remoteFile);
        }

        /// <summary>
        /// 寫文件
        /// </summary>
        /// <param name="remoteFile"></param>
        public void StreamToFile(RemoteFileInfo remoteFile)
        {
            string fileFullPath = Path.Combine(System.Environment.CurrentDirectory, remoteFile.FileName);
            Stream sourceStream = remoteFile.FileByteStream;
            if (sourceStream == null) { return; }
            if (!sourceStream.CanRead) { return; }
            //創建文件流,讀取流中的數據生成文件
            using (FileStream fs = new FileStream(fileFullPath, FileMode.Create, FileAccess.Write, FileShare.None))
            {
                const int bufferLength = 4096;
                byte[] myBuffer = new byte[bufferLength];//數據緩衝區
                int count;
                while ((count = sourceStream.Read(myBuffer, 0, bufferLength)) > 0)
                {
                    fs.Write(myBuffer, 0, count);
                }
                fs.Close();
                sourceStream.Close();
            }
        }

        /// <summary>
        /// 下載文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public Stream DownLoad(string fileName)
        {
            string fileFullPath = Path.Combine(System.Environment.CurrentDirectory, fileName);
            if (!File.Exists(fileFullPath))//判斷文件是否存在
            {
                return null;
            }
            try
            {
                Stream myStream = File.OpenRead(fileFullPath);
                return myStream;
            }
            catch { return null; }
        }
    }
}

服務端配置文件:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="FileTransferBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <basicHttpBinding>
        <binding name="FileTransferdBinding" receiveTimeout="00:30:00" sendTimeout="00:30:00" maxReceivedMessageSize="6442450944" transferMode="Streamed"
            messageEncoding="Mtom" />
      </basicHttpBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="FileTransferBehavior" name="Service.FileTransferOperation">
        <endpoint binding="basicHttpBinding" bindingConfiguration="FileTransferdBinding"
            contract="Service.Interface.IFileTransferOperation" />
        <host>
          <baseAddresses>
            <add baseAddress="http://127.0.0.1:5600/fileupload" />
          </baseAddresses>
        </host>
      </service>
    </services>
  </system.serviceModel>
</configuration>

l  客戶端程式

Program.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using FileTransferClient.FileTransferService;

namespace FileTransferClient
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("請輸入文件完整路徑:");
            string fullFilePath = Console.ReadLine().Trim();

            
            using (FileTransferOperationClient proxy=new FileTransferOperationClient())
            {
                DateTime datetime1 = DateTime.Now;
                byte[] buffer = System.IO.File.ReadAllBytes(fullFilePath);
                Stream streamBuffer= new MemoryStream(buffer);
                //上傳文件
                proxy.UploadLoad(buffer.Length, System.IO.Path.GetFileName(fullFilePath), streamBuffer);
                OutPutDiffTime(DateTime.Now, datetime1, "上傳成功");


                Console.WriteLine("開始下載文件:");
                DateTime datetime2 = DateTime.Now;
                string filename = System.IO.Path.GetFileName(fullFilePath);
                //下載文件
                Stream sourceStream = proxy.DownLoad(filename);
                if (sourceStream == null) { return; }
                if (!sourceStream.CanRead) { return; }
                //創建文件流,讀取流中的數據生成文件
                using (FileStream fs = new FileStream(Path.Combine(System.Environment.CurrentDirectory, filename), FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    const int bufferLength = 4096;
                    //數據緩衝區
                    byte[] myBuffer = new byte[bufferLength];
                    int count;
                    while ((count = sourceStream.Read(myBuffer, 0, bufferLength)) > 0)
                    {
                        fs.Write(myBuffer, 0, count);
                    }
                    fs.Close();
                    sourceStream.Close();
                }
                OutPutDiffTime(DateTime.Now, datetime2, "下載成功");
                Console.Read();
            }
        }
        public static void OutPutDiffTime(DateTime datetime2,DateTime datetime1,string mesg)
        {
            TimeSpan ts = (datetime2 - datetime1);
            string dateDiff = ts.Hours.ToString() + "小時"
                    + ts.Minutes.ToString() + "分鐘"
                    + ts.Seconds.ToString() + "";
            Console.WriteLine(String.Format("花費了{0},{1}", dateDiff, mesg));
        }
    }
}

客戶端配置文件(註意這裡客戶端transferMode=”Streamed”要採用流式數據進行處理,並且將endpoint address改為” http://zhyongfeng.com/fileupload”):

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IFileTransferOperation" receiveTimeout="00:30:00"
          sendTimeout="00:30:00" maxReceivedMessageSize="6442450944" transferMode="Streamed"
          messageEncoding="Mtom" />
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://zhyongfeng.com/fileupload" binding="basicHttpBinding"
        bindingConfiguration="BasicHttpBinding_IFileTransferOperation"
        contract="FileTransferService.IFileTransferOperation" name="BasicHttpBinding_IFileTransferOperation" />
    </client>
  </system.serviceModel>
</configuration>

如下圖所示:

5       URL保留項

詳見:http://www.cnblogs.com/yongfeng/p/7851039.html

6       部署WCF服務程式到區域網內1台PC機

遠程部署WCF服務端程式到PC機

7       Nginx集群配置搭建

通過自主義功能變數名稱zhyongfeng.com:80埠進行負載均衡集群訪問,則訪問C:\Windows\System32\drivers\etc\hosts,添加下列“本機IP 自定義的功能變數名稱”:

10.93.85.66    zhyongfeng.com

使用Nginx匹配原則針對WCF部署的1台PC機配置如下:

worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    upstream zhyongfeng.com {
        server    10.92.202.56:5600;
        server    10.92.202.57:5700; 
        server    10.92.202.58:5800;
    }
    server {
        listen       80;
        server_name  zhyongfeng.com;
        location / {
            proxy_pass   http://zhyongfeng.com;
            proxy_connect_timeout       10s;
        } 
    location /fileupload {
            proxy_pass   http://10.92.202.56:5600/fileupload;
            proxy_connect_timeout       10s;
        } 
    }
}

運行CMD:

D:\DTLDownLoads\nginx-1.10.2>start nginx

D:\DTLDownLoads\nginx-1.10.2>nginx -s reload

訪問WCF服務端:http://zhyongfeng.com/fileupload,運行結果:

8        WCF客戶端程式的運行結果

啟動WCF客戶端程式,直接上傳Linux的ubuntu系統iso鏡像,總大小為1.5G左右,上傳時間區域網(伺服器線路是10Gpbs)花費7分鐘左右,下載時間大概是3分鐘。

客戶端伺服器的網路狀況,運行效果如下圖:

 

 

9       總結

Nginx的匹配原則能夠有效的分配URL,將流式數據分發給相應的服務處理,並且在區域網內能夠支持較大的上傳下載功能。通過BasicHttpBinding的相關配置,能夠控制流式數據上傳大小,同時支持流式數據的下載功能,達到WCF大文件上傳及下載的效果。

當然,具體的應用場景,還是要結合數據大小而言論的,這裡只是提供一個解決方案的參考。

例如一些處理視頻文件每天都是1TB,處理PB級的大數據文件,還是建議使用hadoop的HDFS實現比較好。

另一方面,數據大小達若幹MB或幾KB的發票、報表文件,這些文件主要在多而不在大,hadoop的MapReduce顯然有點大材小用了,可以採用“業務領域-年-月-日”的方式,建立自己一套數據結構存儲方式。

 

源代碼下載:

http://download.csdn.net/download/ruby_matlab/10131307

 

PDF下載:

Nginx集群之WCF大文件上傳及下載(支持6G傳輸).pdf


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在博客園也很多年了,一直未曾分享過什麼東西,也沒有寫過博客,但自己也是汲取著博客園的知識成長的; 這兩天想著不能這麼無私,最近.NET CORE貌似挺流行的,閑來無事也自己搞了個asp.net core signalr 博客園裡面也有人在.net core 2.0下麵集成了signalr,但是是集成 ...
  • PS: 第一次用Repeater控制項 記錄一下 請忽略我的命名不規範 請忽略我的最終效果圖(太醜了) 需要用到的朋友可以自行調整的漂亮點 最終效果圖 HTML 後臺代碼 批註:分頁主要實現在於sql語句上 ...
  • 在net framework 4.0中微軟又提供了一個新的非同步操作的功能,叫做任務並行庫(TPL)。任務並行庫的核心是任務(task)。一個任務代表了一個非同步操作,譔操作可以通過多種方式運行,可以使用或不使用獨立的線程。 一個任務(Task)可以通過多種方式和其他任務組合起來使用。... ...
  • 背水一戰 Windows 10 之 控制項(控制項基類 - FrameworkElement): 基礎知識, 相關事件, HorizontalAlignment 和 VerticalAlignment ...
  • case Acad::eOk:lstrcpy(Glb_AcadErrorInfo,_T("正確"));break;case Acad::eNotImplementedYet:lstrcpy(Glb_AcadErrorInfo,_T("尚未實現"));break;case Acad::eNotAppl ...
  • 調用列印程式“PublishToWeb JPG.pc3”進行圖片列印,該列印驅動程式中內置了很多的列印方案,在同尺寸的列印方案下,數據範圍越大列印出來的清晰度就越差,內置的尺寸不一定都滿足,在又要通過我們的插件去完成列印任務,又不能讓客戶總是做配置的情況下,我總結了一個不是很完美的解決方案,實現思路 ...
  • 自從出現了泛型和LINQ,對於集合的排序變得更簡單了。 //倒序 list.OrderByDescending(p=> p.a).ThenByDescending(p => p.b); //多個欄位順序排序 list.OrderBy(i => i.a).ThenBy(i => i.b); ...
  • 1 class Program 2 { 3 private static byte[] result = new byte[1024]; 4 static void Main(string[] args) 5 { 6 //設定伺服器IP地址 7 IPAddress ip = IPAddress.Pa ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...