因爲本人的技術水平有限,不免會出現錯誤。本文對任何一我的有幫助都是我莫大的榮幸,任何一個大神對個人點撥,我都會感激涕零。linux
在2013年8月低的時候,公司中了XXX市場監督局肉品配送車輛監控的項目。整個系統軟件部分須要實現的功能不難,最大的難點就是服務器的系統要求是Linux的,其次就是10月底系統可以初步成型。因爲以前作的車輛監控系統都基於Windows的,要在短期內完成這個項目,因而Mono就成了個人首選。張善友的博客,也成了我常常光顧的地方,後來經過跟張哥的一番溝通。最終採用了張哥推薦的方案,數據庫使用PostgreSQL,Web服務器使用國產的Jexus,Linux操做系統使用CentOS6.2(這個是客戶要求的)。其餘均可以很好移植,以前的系統前臺使用的Extjs+SilverLight+Asp.net,服務層使用的WCF,當時張哥有提醒我Mono下的WCF坑特別的多,ORM使用的是Nhibernate,地圖引擎依舊採用的DeepEarth。有張哥的點撥,個人信心滿滿的。看上去彷佛我須要解決的問題就是搭建好Mono環境,搞定Mono下的WCF服務就能夠大功告成了。sql
裝Linux系統,配置Mono環境,安裝Jexus。寫了個簡單的Silverlight + WCF的程序部署到Jexus,居然成功跑來了,當時的我偷笑了。然而,當我真正把系統部署到Jexus上面,才知道噩夢纔剛剛開始。登陸頁面都沒有過不去,此時估計不少人都會想要是在Linux下能Debug就行了,我也不例外。因而乎,我就折騰MonoDevelop,安裝過程當中遇到各類奇葩問題,並且不支持SilverLight的項目,我放棄了。採用最原始的辦法,寫日誌。通過幾天的折騰,終於能夠跑起來了。數據庫
因爲在折騰WCF的時候,遇到的默默其妙的問題比較多,有些可以經過Google搜索到。我這裏就列舉三個。服務器
1:尋址版本 AddressingNone不支持添加 WS-Addressing 標頭。若是你的WCF部署在IIS下能正常的調用,而部署在Jexus下確拋出這種異常。session
檢查項目下引用的dll,估計某些dll在Mono下支持不是很好。在有可能出錯的異常寫日誌,而不要拋出這個異常。好比下面這個簡單的例子,FluentNhibernate在Mono下的支持就不是很好。併發
public IList<Custmer> GetCustoemrs() { try { using (var session = SessionFactory.GetCurrentFactory().OpenSession()) { var query = session.CreateQuery("from Customer "); return query.List<Customer>(); } } catch (Exception ex) { LogHelper.WriteException("GetCustomers method raise error:", ex); //throw; } } public class SessionFactory { public static ISessionFactory GetCurrentFactory() { return sessionFactory ?? (sessionFactory = CreateSessionFactory()); } private static ISessionFactory CreateSessionFactory() { return Fluently.Configure() .Database(MsSqlConfiguration.MsSql2008.ConnectionString( x => x.FromConnectionStringWithKey("db"))) .Mappings(m => m.FluentMappings.AddFromAssemblyOf<CustomerMap>()) .BuildSessionFactory(); } private static ISessionFactory sessionFactory { get; set; } }
2:客戶端反序列化失敗app
當我把WCF部署到Jexus,成功生成本地代理後,調用WCF就會一直報這個錯誤。究其緣由,就是由於生成代理類的屬性指定了反序列化的順序,而服務端我是沒有指定的。因此,先把WCF服務部署到IIS下,而後客戶端地址指向部署IIS的WCF服務,從新更新服務,再把配置文件中地址指向部署在Jexus的WCF服務便可。工具
Jexus下Host的WCF服務生成的本地代理:post
[System.Runtime.Serialization.DataMemberAttribute(IsRequired=true, Order=1)] public string CustomerCode { get { return this.CustomerCodeField; } set { if ((object.ReferenceEquals(this.CustomerCodeField, value) != true)) { this.CustomerCodeField = value; this.RaisePropertyChanged("CustomerCode"); } } }
IIS下Host的WCF服務生成的本地代理:測試
[System.Runtime.Serialization.DataMemberAttribute()] public string CustomerCode { get { return this.CustomerCodeField; } set { if ((object.ReferenceEquals(this.CustomerCodeField, value) != true)) { this.CustomerCodeField = value; this.RaisePropertyChanged("CustomerCode"); } } }
3:WCF服務致使Jexus的httpd worker不斷重啓
這個問題是困擾我最久的,在IE11下最爲明顯,Service.svc文件的post請求,動不動就被Pending。在最開始我不知道Jexus一直在重啓,由於我看jws.log中沒有Jexus重啓的日誌。後來得知能夠經過 ps –ef | grep jws 指令能夠查看進程的啓動時間,以下圖所示,能夠看到httpd worker進程不斷的重啓。
問題找到了,又開始新的一輪折騰。首先,減小客戶端對Service.svc文件的post請求,其次將WCF回傳的數據進行壓縮處理。一番修改後,IE11下,故障依舊。因而想到了用WebService嘗試下,就把某個服務修改爲WebService的方式後,貌似httpd worker不會重啓了,處理不過來請求的時候,只會中斷請求。既然這樣,我就狠心把WCF的綁定方式由CustomBinding的方式改爲了BasicHttpBinding,然而故障仍是那麼的頑固存在。
通過一番測試,感受多是Jexus的問題,測試代碼:
class Program { private static ServiceClient client; private static int count = 0; static void Main(string[] args) { client = new ServiceClient(); client.GetCustomersCompleted += client_GetCustomersCompleted; int callCount = Convert.ToInt32(ConfigurationManager.AppSettings["CallCount"]); Console.WriteLine("Press begin to Call WCF Service:"); while (Console.ReadLine().ToLower() == "begin") { DoWork(callCount); } Console.Read(); } private static void DoWork(int callCount) { for (int i = 1; i <= callCount; i++) { ThreadPool.QueueUserWorkItem(CallService, i); } } private static void CallService(object state) { client.GetCustomersAsync(state); } static void client_GetCustomersCompleted(object sender, GetCustomersCompletedEventArgs e) { if (e.Error == null) { Interlocked.Add(ref count, 1); Console.WriteLine("成功調用:{0}", count); } else { Console.WriteLine(e.Error); } } } }
若是是對WebService模擬併發發起請求的時候,httpd worker不會重啓,若是是WCF,httpd worker會不斷的重啓。沒有辦法只有諮詢Jexus的做者宇內了。跟他描述了問題,按照他說的更新了Jexus版本,優化了Linux。最後發了個測試工具給宇內,宇內發現Jexus在處理WCF請求的時候是有點問題。在這裏仍是要感謝宇內那麼熱心的幫助我解決問題。
數據庫的遷移遇到的問題不是不少,藉助navicat將數據從SqlServer導入到PostgreSQL。因爲系統的業務不是很複雜,以前就採用了Nhibernate,須要修改配置文件中主鍵字段的映射,由於PostgreSQL中採用的是序列。以前SqlServer中一些稍微複雜點的查詢是採用存儲過程寫的,存儲過程的移植性很差,在PostgresSQL下這部分只能從新寫了。
<id name="TypeID" type="Int32" unsaved-value="0"> <column name="TypeID" length="4" sql-type="int" not-null="true" unique="true" index="PK_SysAllType"/> <generator class="sequence"> <param name="sequence">sysalltype_typeid_seq</param> </generator> </id>
因爲地圖服務器是單獨一臺,最終是用Perl + Apache來實現的,實現也挺簡單的,幾十行代碼,就是地圖引擎請求一個圖片路徑,將圖片輸出就能夠了。最開始的時候,用的是Asp.net,部署在Jexus上,可是不知道爲何某些圖片始終輸出不出來,最終仍是放棄了。
最後附上一張系統遷移後成功後的圖片: