設計C S架構應用程式的併發功能

2022-01-10 23:17:25 字數 4671 閱讀 7440

序號併發使用者

** 1

5個以下

每使用者20000,總價小於10萬

25-20

每使用者15000,總價小於30萬

320-50

每使用者12000,總價小於60萬

450個以

每使用者10000,總價最小50萬

從軟體開發的角度,我來分享一下我對併發功能的設計與實現。

需求與設計

1 正常的順序是先啟動伺服器,再啟動客戶端主程式。如果啟動客戶端主程式時,連線不上伺服器,要報錯並終止程式。

2 執行過程中,伺服器可能因各種情況停止工作。比如殺度軟體掃瞄,停電等原因,這時我們的客戶端主程式要能檢測到伺服器岩機,掛起當前介面。

為了減少這種事情發生的概率,我建議在伺服器中安裝程式alwaysup。

alwaysup能將可執行檔案、批處理檔案及快捷方式作為windows系統服務,並且進行管理和監視確保100%執行。當程式崩潰、掛起、彈出錯誤對話方塊時,alwaysup 能自動重啟程式,並執行自定義的檢查功能確保程式一直可用。alwaysup 能傳送詳細的email使你清楚地了解崩潰、重啟等事件。

詳細資訊參考以下位址

3 我們的c/s程式有兩種執行模式。第一種是客戶端主程式與伺服器不在同一臺機器上,兩個程序執行在物理隔離的兩台電腦中,第二種就是客戶端主程式與伺服器都執行在伺服器中,客戶端以遠端桌面的方式執行。

前一種模式好理解,兩台機器之前以.net通訊機制(.net remoting,wcf)互動,後一種模式兩個程序實際是執行在同一部電腦中,在併發控制上這兩者有區別。

我們來看一下c#中的程序(process)的定義,位址在

裡面有乙個sessionid的屬性,它的含義如下

gets the terminal services session identifier for the associated process.  獲取程序的終端服務的會話標識。

在程式開發時為了識別是否是相同的併發,前者只需要根據ip位址或mac位址,後者則需要根據sessionid來識別。

這個知識點的重要性在於,使用者a已經登入過,在另一台電腦或會話中使用者a再次登入時,系統要可以識別出來,要麼阻止重複的登入,要麼踢出前乙個登入,要麼重新整理登入會話。

4 我們從資料的操作角度對併發使用者作兩個分組,一組是可編輯資料的使用者,另一組是唯讀使用者(readonly)。公司的主管,經理層或是總經理層,常常是查詢報表,他們不需要運算元據。由於查詢資料對伺服器的壓力要少很多(事務),所以一般在銷售併發使用者的時候,還會贈送相應數量的檢視使用者數。

5 使用者之間關係的處理。管理員可以踢出使用者,使用者之間可以傳送訊息通知,管理員可以強制所有使用者下線(由於系統需要進行重大更新,系統重要業務處理(月結,年結,期末處理等))。

6 執行過程中,客戶端意外終止。比如乙個耗費時間的操作(mrp運算,工作單發料,產品完工),使用者在等待過程中失去耐心,強制殺死執行中的程序。這時因為沒有呼叫logoff方法清除伺服器中的程序會話。如果再次啟動登入時,可能會提示會話已經存在,或是登入使用者超過最大許可數。

前面提到由於有心跳機制,伺服器程序死去,客戶端程序要掛起(阻止使用者任何輸入,暴力一點的方法是退出)。

這一點提到伺服器執行正常,客戶端意外終結,完全沒有時機去通知伺服器我已經下線。我們的處理方法是伺服器每5分鐘輪循一次客戶端,檢測到會話所在的客戶端程序無法回應,則主動清除會話資訊,以便於客戶端下一次正常登入。

7  我們對許可機制有嚴格的要求,安裝完成erp後,會給當前機器環境生成乙個簽名檔案,這個檔案附註於許可檔案中。執行時我們會檢測當前執行的機器是否與許可檔案中的機器簽名匹配。

private

static

string getdiskdrivesignature()

private

static

string getdiskdrivesize()

private

static

string getdiskdrivetotaltracks()

從**中可以看出,是使用wmi。

這是伺服器中的許可驗證方法,客戶端程式因為有併發數量控制,不驗證許可檔案和它的簽名。

8 阻止伺服器程式被第三方惡意api呼叫

.net remoting的服務端**例子:

static

void main(string args)

.net remoting客戶端程式例子:

tcpchannel channel = new tcpchannel();
channelservices.registerchannel(channel, false);
iperson obj = (iperson)activator.getobject(typeof(remotingobjects.iperson), "tcp://localhost:8080/remotingpersonservice");
string username=obj.getname();

最後一行我們呼叫了伺服器中的程式。如果伺服器程式被惡意人員獲取,可以很容易的構造出客戶端程式進行呼叫,伺服器完全不知覺。為解決這個問題,我們的設計方案是客戶端登入時,將當前環境因素(ip位址,電腦名,mac位址,程式集版本與雜湊值等)組合傳送到伺服器中,經過乙個特定的演算法,得出乙個雜湊值,登入完成後(使用者名稱密碼正確,許可權允許)返回給客戶端,客戶端也以之前的環境變數進行演算法計算,將這兩者的值比較,若相等則允許登入。

這為惡意呼叫伺服器程式增加了難度。

9  伺服器會話

說穿不值一文錢,其實就是個datatable物件,當有使用者登入(login)時,增加會話記錄。使用者登出(logout)時,清除會畫記錄。

也可以學習asp.net的session物件的設計思路,參考這裡 exploring session in asp.net

datatable因為操作上的不方便,後期維護的時候,我們把它完善成強型別物件。

[serializable]
public

class session

public

string userid

public

string usergroup

public

string machinename

......
}
public

class sessioncollection :list

//經過oop的封裝,呼叫時比datatable要方便
singletonsessions.....;
sessions.add(new session());

10  日誌記錄

記錄客戶端登入日誌,資料庫表設計

1) 日誌主表 userlog(logno,logintime,logouttime,profile)

紀錄登入和登出時間,如果是客戶端程序被強制殺死,logouttime常常是沒有值。對於程序意外終止,用下面的方法不能截獲終止前**事件。

2)  日誌明細表 userlogdetail(logno,seqno,functioncode,opentime,closetime)

記錄使用者登入後,執行了哪些系統功能,持續了多長時間。

3 ) 日誌數量表 userlogdetailaction(logno,seqno,remark)

記錄使用者登入後,操作了哪個功能的哪一筆資料。是做了編輯操作,還是執行過帳。remark的演算法如下

entity   salesorder=...
stringbuilder builder=new stringbuilder();
foreach(ifield field in salesorder.fields)
string remark=builder.tostring();

userlog使用者日誌主表的最後乙個欄位profiler,是乙個後門,它記錄了登入erp系統的當前登入使用者的本機電腦的幾乎所有資訊,相當於乙個隱私收集工具。在審計(audit)的時候,我們可以用於幫忙使用者澄清一些不必要的錯誤。

比如erp的各部門主管常常是將erp賬戶與密碼給下面的同事,讓他們幫忙獲取資料,而自己常常是不進入系統的。

高一級的許可權放開給不合理的人員,增加了系統的風險,而這個profiler可以在一定程度上避免這種情況發生。

大公司的it審計一看即可知道此登入的使用者電腦不具備此高階許可權。不過為了維護使用者的聲譽,我們對此功能做了選擇性的處理,在實施時根據自己的實際需要去選擇,預設情況下並不會進行隱私收集。

模擬測試

可以通過多開幾個虛擬機器來模擬測試併發,虛擬機器與主機之前的連線方式如下:

1) 主機與虛擬機器設為同乙個網段的ip位址,比如192.168.1.100,192.168.1.101

2) 虛擬機器與主機之間的網路連線方式設定為橋接(bridge)

在測試併發時,可以將伺服器端駐留在物理主機中,啟動vs並開啟除錯模式。如果是以windows服務存在,可以在程式中新增以下**來強制附加偵錯程式。

if(!debugger.isattached)
debugger.launch();

併發應用程式

執行緒併發 序列的執行任務 顯示地為任務建立執行緒 使用executor框架 title taskexecutionwebserver description 1 單執行緒的序列執行 缺點 糟糕的響應和較低的吞吐量 2 將每個任務放在各自的執行緒中執行 缺點 執行緒的管理的複雜性 3 將每個任務提交...

1 3 4 設計併發友好的應用程式

1.3.4 設計併發友好的應用程式 使用傳統的命令風格編寫多執行緒應用程式時,我們要面對兩個問題 非常難讓現有的順序 變成並行的 由於要顯式使用執行緒,必須改動大部分的基本 使用共享狀態和鎖定是困難的。必須細緻考慮怎樣使用鎖來避免爭用條件和死鎖,留下足夠的空間並行執行。函式式程式設計給了我們答案 使...

Android 應用程式架構

android應用程式架構 1 可擴充套件檢視 view 建立應用程式 2 內容管理器 content providers 訪問其他應用程式資料 共享自身資料 3 資源管理器 resource manager 提供非 資源訪問,本地字串 分層檔案 4 通知管理器 notification manag...