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
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...