About neohope

一直在努力,还没想过要放弃...

使用ICE实现RPC简单示例03

接第01部分,本节用来说明Java语言的代码实现。

使用slice2java之后,会生成10个文件,Client与Server需要分别包含多个文件。

首先是Server端:
1、新建一个java项目,引用ice-3.6.1.jar
2、copy以下几个文件
_iIceTestDisp.java
_iIceTestOperations.java
_iIceTestOperationsNC.java
iIceTest.java
iIceTestHolder.java
3、新建一个类MyICETest,实现iIceTestDisp_接口

package com.neohope.ice.test;

import Ice.Current;

public class MyIceTest extends _iIceTestDisp {
    @Override
    public String SayHelloTo(String s, Current __current) {
        return "Hello " + s;
    }

    @Override
    public int Add(int a, int b, Current __current) {
        return a+b;
    }
}

4、新建测试类TestServer

package com.neohope.ice.test;

public class TestServer {

    public static void main(String[] args) {
        Ice.Communicator ic = null;

        //初使化
        ic = Ice.Util.initialize(args);

        //创建适配器,并指定监听端口
        Ice.ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints("NeoTestAdapter", "default -p 1900");

        //绑定
        Ice.Object obj = new MyIceTest();
        adapter.add(obj, Ice.Util.stringToIdentity("NeoICETest"));

        //激活适配器
        adapter.activate();

        //持续监听,直到服务关闭
        ic.waitForShutdown();

        //清理
        if (ic != null) {
            try {
                ic.destroy();
            } catch (Exception e) {
                System.err.println(e.getMessage());
            }
        }
    }
}

5、编译运行

然后是Client端:
1、新建一个java项目,引用ice-3.6.1.jar
2、copy以下几个文件
Callback_iIceTest_Add.java
Callback_iIceTest_SayHelloTo.java
iIceTestPrx.java
iIceTestPrxHelper.java
iIceTestPrxHolder.java
3、新建测试类TestClient

package com.neohope.ice.test;

public class TestClient {
    public static void main(String[] args) {
        Ice.Communicator ic = null;

        //初使化
        ic = Ice.Util.initialize(args);
        Ice.ObjectPrx obj = ic.stringToProxy("NeoICETest:default -p 1900");

        //查找并获取代理接口
        iIceTestPrx client = iIceTestPrxHelper.checkedCast(obj);
        if (client == null) throw new Error("Invalid proxy");

        //调用服务端方法
        System.out.println(client.SayHelloTo("neohope"));
        System.out.println(client.Add(1, 2));

        //清理
        if (ic != null) {
            try {
                ic.destroy();
            } catch (Exception e) {
                System.err.println(e.getMessage());
            }
        }
    }
}

4、编译运行

PS:
1、不要乱修改id,如果要修改,必须全部修改
2、我调整了包名,不调整也可以

使用ICE实现RPC简单示例02

接第01部分,本节用来说明C#语言的代码实现。

使用slice2cs之后,会生成一个文件JustATest.cs,无论是Client还是Server都要包含这个文件。

首先是Server端:
1、新建一个Console项目,引用ICE程序集中的Ice.dll,项目中添加JustATest.cs文件。
2、新建一个类MyICETest,实现iIceTestDisp_接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ice;
using com.neohope.ice.test;

namespace TestICEServer
{
    class MyICETest : iIceTestDisp_
    {
        public override string SayHelloTo(string s, Current current__)
        {
            return "Hello " + s;
        }

        public override int Add(int a, int b, Current current__)
        {
            return a + b;
        }
    }
}

3、修改Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestICEServer
{
    class Program
    {
        static void Main(string[] args)
        {
            Ice.Communicator ic = null;

            //初使化
            ic = Ice.Util.initialize(ref args);

            //创建适配器,并指定监听端口
            Ice.ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints("NeoTestAdapter", "default -p 1900");

            //绑定
            Ice.Object obj = new MyICETest();
            adapter.add(obj,Ice.Util.stringToIdentity("NeoICETest"));

            //激活适配器
            adapter.activate();

            //持续监听,直到服务关闭
            ic.waitForShutdown();

            //清理
            if (ic != null)
            {
                try
                {
                    ic.destroy();
                }
                catch (Exception e)
                {
                }
            }
        }
    }
}

4、编译运行

然后是Client端:
1、新建一个Console项目,引用ICE程序集中的Ice.dll,项目中添加JustATest.cs文件。
2、修改Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using com.neohope.ice.test;
//using JustATest;

namespace TestICE
{
    class Program
    {
        static void Main(string[] args)
        {
            Ice.Communicator ic = null;

            try
            {
                //初使化 
                ic = Ice.Util.initialize(ref args);
                Ice.ObjectPrx obj = ic.stringToProxy("NeoICETest:default -p 1900");

                //查找并获取代理接口
                iIceTestPrx client = iIceTestPrxHelper.checkedCast(obj);
                if (client == null)
                {
                    throw new ApplicationException("Invalid proxy");
                }

                //调用服务端方法
                Console.WriteLine(client.SayHelloTo("neohope"));
                Console.WriteLine(client.Add(1, 2));
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                //清理
                if (ic != null)
                {
                    try
                    {
                        ic.destroy();
                    }
                    catch (Exception e)
                    {
                        Console.Error.WriteLine(e);
                    }
                }
            }
        }
    }
}

3、编译运行

PS:
1、不要乱修改id,如果要修改,必须全部修改
2、我调整了包名,不调整也可以

使用ICE实现RPC简单示例01

看一眼下面的框架,你就会发现,ICE框架其实与CORBA很相似。但ICE更加的简洁高效,并增加了很多现代框架的特性。同时,其开发组件更加易用,不需每种语言单独下载,学习成本相对较低。

Ice_Client_and_Server_Structure

ICE是典型CS架构,与CORBA相同,ICE帮我们处理的底层的网络通信及服务定位,我们只需要告诉ICE服务在哪里,需要哪个服务,调用参数是什么,然后就坐等处理结果就好咯。

使用ICE的时候,首先要先下载ICE的开发包,下载后直接解压就好了。
ICE下载地址

在使用ICE的时候,首先要用Slice语言,定义一个接口描述文件,比如我自己写了一个很简单的接口。
JustATest.ice

module JustATest
{ 
  interface iIceTest
  { 
    string SayHelloTo(string s);
    int Add(int a, int b);
  }; 
};

然后用对应语言的转化工具,将接口描述文件,转化为对应语言。

#设置环境变量
set ICE_HOME=C:\NeoArch\ZeroC\Ice-3.6.1
set PATH=%ICE_HOME%\bin;%PATH%

#转化为java
slice2java JustATest.ice

#转化为csharp
slice2cs JustATest.ice

那ICE的Client端,是如何找到Server,并告诉Server要调用哪个服务的呢?

//首先,Server在启动的时候,要指定Adapter的名称与端口
ic.createObjectAdapterWithEndpoints("NeoTestAdapter", "default -p 1900");
//然后,在Server端的Adapter上,要做一个类似于将服务名称与服务对象绑定的动作
adapter.add(obj,Ice.Util.stringToIdentity("NeoICETest"));

//当Client启动的时候,要指定端口及服务名称,这样就找到了
Ice.ObjectPrx obj = ic.stringToProxy("NeoICETest:default -p 1900");

那如果两个服务同名,只是端口不一致咋办呢?
你可以发现,无论是Client还是Server,无论是C#还是Java,都有类似的代码,你懂的。

        //C#
        public static readonly string[] ids__ =
        {
            "::Ice::Object",
            "::JustATest::iIceTest"
        };
    //java
    public static final String[] __ids =
    {
        "::Ice::Object",
        "::JustATest::iIceTest"
    };

在client段调用的时候,有checkedCast和uncheckedCast两种转换方式,说白了,checkedCast会先校验接口是否匹配,而uncheckedCast会直接强制转换不做任何校验。可以根据实际情况选用咯。

产品管理模式演化

==========================================================
最开始的时候,公司产品管理比较混乱,几乎对每一个客户都进行了定制,出现了大量的分支。
后面发现维护成本太高,开始合并各版本之间的功能,但最终仍有十几个版本。

PS:后来公司换了老板,初期很多有经验的研发及实施人员都流失了,很可惜。

==========================================================
2009年,项目比较小,我们采用的是按功能划分的方式进行分工的,经常一个项目就一个人,或一个项目拆为几大块,每人一块来进行。这个模式持续了一段时间。

现在回过头来看这段时间的一些产品,产品功能不多,但需求做的很好,产品定位比较准确,符合客户要求,后期移交其他同事维护后,架构上和界面上都没有大的变化。对于小规模的开发,这种方式还是适用的。

==========================================================
2010年底到2011年,公司开始了电子病历项目的开发,投入了不少的人力。由于项目变的比较复杂,现在变成了十来个人一起扑到一个项目上。第一次引入了需求、测试人员。本人甚至客串了一段时间的美工+前端(惨不忍睹)。

这段时间是架构转型的时间,时间紧任务重,语言也刚开始学,加了很多班,好在项目最终验收了。

后来由于很多原因,整个产品线被砍掉了,又流失了不少人。

==========================================================
2012年,开始了平台项目,初期核心团队不大,产品已经有了原型,加上前面的积累,整个任务还算顺利,但仍然是加了很多班。

架构为简单的SSH,后台逻辑为主,前端现在看来惨不忍睹。

花了很多时间,补充平台应用。

==========================================================
2013年,团队人员增加了很多,引入了MVN,开始有了较好的任务分工,架构变的明晰。

花了很多时间,把其他缺失的部分补上来,逐渐形成了一个产品线。

开始使用快速原型法。

开始引入ESB。

==========================================================
2014年,团队人员再次增加了很多,同时加上很多水平不错的同事加入,有了较好的发展。

开始推进单元测试,产品流程越来越规范,快速原型法使用的越来越多,大量使用交互稿。

很多地方开始务实,产品定位进行了调整,很多项目都开始使用ESB。

部分项目,前后端开始分离。

==========================================================
2015年,团队人员有些变动,核心团队还比较稳定。

开始推进高并发,更加关注代码质量。

补充了很多ESB的接口。

前端团队飞速成长,前后端彻底分离。

==========================================================
顺便说一下,我在2009加入公司时,研发中心除了总监,只有我一个人。初期从其他部门调来几个人员,加上招的一些人,也不足10人,现在研发中心已经接近150了。

致新人,差距是如何产生的(01)

今年,我们组来了很多的java新人(编程经验小于一年的小朋友)。

对于他们,我都会做下面的事情:

1、让他们自己列出自己的知识架构,从而告知其不断积累的重要性

90%的人只用过java语言,只知道SSH。

这里,我会结合他们大学课程、实际经验,给他们补充一部分知识架构,拓展一下视野。

并告诉他们如何去对比的学习新知识,如何找到一种适合自己的学习方式,并要找到适合自己的知识积累方式。

2、以一个很简单的例子,告诉他们应多考虑原理,而不只是用

在一个网站中,在只用了一个框架,比如struts2或spring mvc的情况下,前端登录页面的用户名、密码,是如何发送到后台,并返回验证结果到前台的。

所有人,都直接提到了action如何获取用户名及密码,但只有很少人考虑了,浏览器是如何找到服务器/容器的,也只有很少人知道,容器是如何定位到哪个应用、哪个action的。

然后,会告诉他们,希望他们可以在一年之后,用最复杂的解释,告诉我,这个流程是如何运作的。两年之后,把整个流程变简单,并可以自己去实现一个简单的框架。

3、送给他们一本《程序员的职业素养》,让他们自己去领悟其中的内容

4、探讨他们的职业发展道路

5、开始安排培训,并开始逐步解除新项目

因为,在我看来,程序员在前三年的时候,是个明显的分水岭,所用的学习方式,直接决定了他是程序员还是码农还是该转行。

Cassandra3基本操作01

1、首先看一下各节点状态

neohope@debian8-node01:~/Deploy/apache-cassandra-3.0.1$ bin/nodetool status
Datacenter: datacenter1
=======================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
--  Address        Load       Tokens       Owns    Host ID                               Rack
UN  172.16.172.23  230.25 KB  256          ?       760879a3-e06b-43bb-97bf-b045a655da9c  rack1
UN  172.16.172.24  237.17 KB  256          ?       5bf3e77d-ccf4-4f81-9465-de0babe1e0cc  rack1
UN  172.16.172.25  241.55 KB  256          ?       5a7ed53f-c8e0-4658-af9a-41880dada5ef  rack1

Note: Non-system keyspaces don't have the same replication settings, effective ownership information is meaningless

2、然后用cqlsh连接cassandra

neohope@debian8-node01:~/Deploy/apache-cassandra-3.0.1$ bin/cqlsh debian8-node01
Connected to NeoCluster at debian8-node01:9042.
[cqlsh 5.0.1 | Cassandra 3.0.1 | CQL spec 3.3.1 | Native protocol v4]
Use HELP for help.

cqlsh:neokeyspace> help

Documented shell commands:
===========================
CAPTURE  CLS          COPY  DESCRIBE  EXPAND  LOGIN   SERIAL  SOURCE   UNICODE
CLEAR    CONSISTENCY  DESC  EXIT      HELP    PAGING  SHOW    TRACING

CQL help topics:
================
AGGREGATES               CREATE_KEYSPACE           DROP_TRIGGER      TEXT     
ALTER_KEYSPACE           CREATE_MATERIALIZED_VIEW  DROP_TYPE         TIME     
ALTER_MATERIALIZED_VIEW  CREATE_ROLE               DROP_USER         TIMESTAMP
ALTER_TABLE              CREATE_TABLE              FUNCTIONS         TRUNCATE 
ALTER_TYPE               CREATE_TRIGGER            GRANT             TYPES    
ALTER_USER               CREATE_TYPE               INSERT            UPDATE   
APPLY                    CREATE_USER               INSERT_JSON       USE      
ASCII                    DATE                      INT               UUID     
BATCH                    DELETE                    JSON            
BEGIN                    DROP_AGGREGATE            KEYWORDS        
BLOB                     DROP_COLUMNFAMILY         LIST_PERMISSIONS
BOOLEAN                  DROP_FUNCTION             LIST_ROLES      
COUNTER                  DROP_INDEX                LIST_USERS      
CREATE_AGGREGATE         DROP_KEYSPACE             PERMISSIONS     
CREATE_COLUMNFAMILY      DROP_MATERIALIZED_VIEW    REVOKE          
CREATE_FUNCTION          DROP_ROLE                 SELECT          
CREATE_INDEX             DROP_TABLE                SELECT_JSON     

Continue reading Cassandra3基本操作01

HBase简单通讯代码

首先,就要说一下配置问题了。HBase客户端的配置有两种方式,一种是通过配置文件,另一种是通过代码设置。

1、配置文件方式
配置文件名称为hbase-site.xml,该文件必须放置到CLASS_PATH下面才会有效,文件示例如下:
hbase-site.xml

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
	<property>
		<name>hbase.rootdir</name>
		<value>hdfs://hadoop-master:9000/hbase</value>
	</property>
	<property>
		<name>hbase.cluster.distributed</name>
		<value>true</value>
	</property>
	<property>
		<name>hbase.master</name>
		<value>hdfs://hadoop-master:60000</value>
	</property>
	<property>
		<name>hbase.zookeeper.quorum</name>
		<value>hadoop-master,hadoop-slave01,hadoop-slave02</value>
	</property>
</configuration>

2、通过代码配置方式

        Configuration hbaseConfig = HBaseConfiguration.create();
        hbaseConfig.setInt("timeout", 120000);
        hbaseConfig.set("hbase.master", "hdfs://hadoop-master:60000");
        hbaseConfig.set("hbase.zookeeper.quorum", "hadoop-master,hadoop-slave01,hadoop-slave02");
        hbaseConfig.setInt("hbase.zookeeper.property.clientPort", 2181);
        hbaseConfig.setInt("hbase.client.retries.number", 1);

Continue reading HBase简单通讯代码

浏览器插件的演化

浏览器插件,主要使用了两种,一种是微软的ActiveX插件,一种是Java Applet。

说实话,两种插件的引入,主要是为了突破浏览器的本地访问限制。而且,很多控件都是内网使用,是自签名的,你懂的。

ActiveX插件,主要用于了调用WindowsAPI,调用本地EXE等。
这种模式,在2013年-2014年,逐步被CS+BS的模式所替代。

Applet插件,主要用于了多线程下载控制,调用JS等。总体来说,JVM对Applet的沙盒控制还是越来越严格了。
在2013年引入了Java Web Star,但效果也一般。

BS架构的演化

==========================================================
2010年下半年,公司开始BS开发,主要语言为java。以Sevlet+JSP为主,只用了Struts1框架。

2011年,引入三大框架Struts2、Hibernate、Spring。

2012年-2013年,以后台通信业务为主,主要使用了Hibernate、Spring。负载均衡采用了APACHE+TOMCAT的方式。

2013年-2014年,引入了Maven及模块式开发,引入了ESB,开始推行单元测试。Struts2逐步切换到SpringMVC,Hibernate逐步切换到MyBatis,并进行了二次封装。

2015年,引入监控机制,版本发布机制,开始抽离SQL语句。引入Reids+Nginx,引入MongoDB,引入消息中间件。

2016年,引入CI,引入eXistDB。

==========================================================
自从2010年开始使用C#以来,也有不少BS项目是C#开发的。

2010年-2014年,主要采用ASPX+ADO.net的开发模式。

2015年,引入了EntityFramwork+MVC的开发模式

2016年,引入单元测试及CI。