zoukankan      html  css  js  c++  java
  • 我将系统从Windows迁移至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服务就可以大功告成了。

    三、环境搭建

      装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下,然后客户端地址指向部署IISWCF服务,重新更新服务,再把配置文件中地址指向部署在JexusWCF服务即可。

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

    [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");
                    }
                }
            }

      3WCF服务导致Jexushttpd 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不会重启,如果是WCFhttpd 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 libusb 安装及简单使用
    Linux 交换eth0和eth1
    I.MX6 GPS JNI HAL register init hacking
    I.MX6 Android mmm convenient to use
    I.MX6 GPS Android HAL Framework 调试
    Android GPS GPSBasics project hacking
    Python windows serial
    【JAVA】别特注意,POI中getLastRowNum() 和getLastCellNum()的区别
    freemarker跳出循环
  • 原文地址:https://www.cnblogs.com/supperwu/p/3500024.html
Copyright © 2011-2022 走看看