一、写在最前

  由于本人的技术水平有限,难免会出现错误。本文对任何一个人有帮助都是我莫大的荣幸,任何一个大神对我的点拨,我都会感激不尽。

二、技术选型

  在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服务就可以大功告成了。

三、环境搭建

  装Linux系统,配置Mono环境,安装Jexus。写了个简单的Silverlight + WCF的程序部署到Jexus,竟然成功跑来了,当时的我偷笑了。然而,当我真正把系统部署到Jexus上面,才知道噩梦才刚刚开始。登录页面都没有过不去,此时估计很多人都会想要是在Linux下能Debug就好了,我也不例外。于是乎,我就折腾MonoDevelop,安装过程中遇到各种奇葩问题,而且不支持SilverLight的项目,我放弃了。采用最原始的办法,写日志。经过几天的折腾,终于可以跑起来了。

四、WCF攻克

  由于在折腾WCF的时候,遇到的默默其妙的问题比较多,有些能够通过Google搜索到。我这里就列举三个。

  1:寻址版本 AddressingNone不支持添加 WS-Addressing 标头。如果你的WCF部署在IIS下能正常的调用,而部署在Jexus下确抛出这种异常。

  检查项目下引用的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:客户端反序列化失败

  当我把WCF部署到Jexus,成功生成本地代理后,调用WCF就会一直报这个错误。究其原因,就是因为生成代理类的属性指定了反序列化的顺序,而服务端我是没有指定的。所以,先把WCF服务部署到IIS下,然后客户端地址指向部署IIS的WCF服务,重新更新服务,再把配置文件中地址指向部署在Jexus的WCF服务即可。

Jexus下Host的WCF服务生成的本地代理:

[System.Runtime.Serialization.DataMemberAttribute(IsRequired=true, Order=)]
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 = ;
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 = ; 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, );
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上,但是不知道为什么某些图片始终输出不出来,最终还是放弃了。

最后附上一张系统迁移后成功后的图片:

  

我将系统从Windows迁移至Linux下的点点滴滴的更多相关文章

  1. SpringNote02.Blog系统迁移到Linux下

    基于SpringMVC-Hibernate的博客系统还在继续开发中 . 项目地址:https://github.com/defshine/SpringBlog 整个项目迁移到linux下开发,安装in ...

  2. windows客户端远程访问linux下mysql方法

    windows客户端远程访问linux下mysql方法 1. 改表法.可能是你的帐号不允许从远程登陆,只能在localhost.这个时候只要在localhost的那台电脑,登入mysql后,更改 &q ...

  3. 几款抓包工具在windows,mac,linux下的支持分析

    抓包工具的使用 几款抓包工具在windows,mac,linux下的支持分析 抓包工具简介 Chrome/Firefox 开发者工具: 浏览器内置,方便易用 Fiddler/Charles: 基于代理 ...

  4. jira从windows迁移到linux

    说明:迁移的就是 jira安装路径/atlassian/jira/atlassian-jira/WEB-INF/classes/jira-application.properties文件中的jira_ ...

  5. MySQL数据库从windows迁移到linux

    前几天搭建了lamp环境,想把之前写的小东西迁到linux上运行,涉及到把mysql数据库的文件迁移到linux上,直接用fileZilla传过去应该不行,我试了下,反正没成功.下面是我采用的方法: ...

  6. Oracle 11g Windows 迁移至 Linux

    OS: windows server 2008 R2 enterprise DB: 11.2.0.1.0 数据库配置: ORACLE_BASE=D:\app\Administrator ORACLE_ ...

  7. SVN服务器从Windows迁移到Linux

    gerui 2013.9.14 ge-rui@sohu.com 一.备份VisualSVN项目 1. 现在要使用Linux作为svn服务器,之前是在windows Server 2008上的,用的是V ...

  8. windows下的mysql迁移到linux下

    最近做毕业设计,需要把windows下的mysql移植到linux下 曾经有过在window下移植mysql数据库的经验,只需要把msql的数据文件复制到另一台安装mysql的机器的数据存放位置,然后 ...

  9. Socket程序从windows移植到linux下需要注意的

    )头文件 windows下winsock.h或winsock2.h linux下netinet/in.h(大部分都在这儿),unistd.h(close函数在这儿),sys/socket.h(在in. ...

随机推荐

  1. 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)

    前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...

  2. [虾扯蛋] android界面框架-Window

    从纯sdk及framwork的角度看,android中界面框架相关的类型有:Window,WindowManager,View等.下面就以这几个类为出发点来概览下安卓开发的"界面架构&quo ...

  3. Socket聊天程序——服务端

    写在前面: 昨天在博客记录自己抽空写的一个Socket聊天程序的初始设计,那是这个程序的整体设计,为了完整性,今天把服务端的设计细化记录一下,首页贴出Socket聊天程序的服务端大体设计图,如下图: ...

  4. ABP文档 - 后台作业和工作者

    文档目录 本节内容: 简介 后台作业 关于作业持久化 创建一个后台作业 在队列里添加一个新作业 默认的后台作业管理器 后台作业存储 配置 禁用作业执行 Hangfire 集成 后台工作者 创建一个后台 ...

  5. Bootstrap-Select 动态加载数据的小记

    关于前端框架系列的可以参考我我刚学Bootstrap时候写的LoT.UI http://www.cnblogs.com/dunitian/p/4822808.html#lotui bootstrap- ...

  6. 解决PHP-问题:Class 'SimpleXMLElement' not found in

    1.问题 在ubuntu 16.10中,学习PHP,学习到PHP如何生成XML文件时候,碰到了这个问题: PHP Fatal error: Class 'ClassName\SimpleXMLElem ...

  7. Ajax实现原理,代码封装

    都知道实现页面的异步操作需要使用Ajax,那么Ajax到是怎么实现异步操作的呢? 首先需要认识一个对象 --> XMLHttpRequest 对象 --> Ajax的核心.它有许多的属性和 ...

  8. zookeeper源码分析之三客户端发送请求流程

    znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的 ...

  9. 前端MVC学习总结(一)——MVC概要与angular概要、模板与数据绑定

    一.前端MVC概要 1.1.库与框架的区别 框架是一个软件的半成品,在全局范围内给了大的约束.库是工具,在单点上给我们提供功能.框架是依赖库的.AngularJS是框架而jQuery则是库. 1.2. ...

  10. android计算每个目录剩余空间丶总空间以及SD卡剩余空间

    ublic class MemorySpaceCheck { /** * 计算剩余空间 * @param path * @return */ public static String getAvail ...