bboyjing's blog

尝试ZeorC ICE之【在线预定图书项目(二)】

本章节继续借助在线预定图书项目来学习Ice。

实现客户端调用

客户端的写法和之前ice_better_hello中Client的写法基本一样,,测试的时候先把IceBox启动,然后直接跑Client的main方法就可以了,代码虽简单,这里也贴一下,以后这么简单的代码就不展示了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Client.java文件
public class Client extends Application {
public static void main(String[] args) {
Client app = new Client();
int status = app.main("Client", args, "config.client");
System.exit(status);
}
@Override
public int run(String[] args) {
tickBook();
return 0;
}
private void tickBook() {
Ice.ObjectPrx base = communicator().propertyToProxy("OnlineBook.Proxy");
OnlineBookPrx prxy = OnlineBookPrxHelper.checkedCast(base);
Message message = new Message();
message.name = "bboyjing";
message.type = 1;
message.price = 99.99;
message.valid = true;
message.content = "this is content";
System.out.println(prxy.bookTick(message));
}
}
// config.client文件
OnlineBook.Proxy=OnlineBook:tcp -h localhost -p 10000

新增SMS服务

接下来我们再开发一个简单的服务SMSService,假设是发短信的服务,其接口的Slice文件如下:

1
2
3
4
5
6
[["java:package:cn.didadu.generate"]]
module sms {
interface ISmsService {
void sendSms(string msg);
};
};

SMSService的服务端代码如下,要注意下和OnlineBookService稍有不同,Logger采用了Ice所提供的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class SmsService extends _ISmsServiceDisp implements Service{
private Logger logger;
private Ice.ObjectAdapter _adapter;
@Override
public void start(String name, Communicator communicator, String[] args) {
logger = communicator.getLogger().cloneWithPrefix(name);
// 创建ObjectAdapter,这里和service同名
_adapter = communicator.createObjectAdapter(name);
// 创建servant,同样和service同名
_adapter.add(this, communicator.stringToIdentity(name));
// 激活servant
_adapter.activate();
logger.trace("SmsService", "started");
}
@Override
public void stop() {
logger.trace("SmsService", "stopped");
_adapter.destroy();
}
@Override
public void sendSms(String msg, Current __current) {
System.out.println("Send sms " + msg);
}
}

修改config.icebox和config.service:

1
2
3
4
5
// config.icebox文件新增如下配置:
IceBox.Service.SmsService=cn.didadu.service.SmsService --Ice.Config=config.service
//config.config.service文件新增如下配置:
SmsService.Endpoints=tcp -h localhost -p 10001

注意一下,OnlineBook和SmsService的端口不一样,官方不建议将多个服务绑定到同一个EndPoint上。我们再启动下IceBox服务,现在的输出如下:

1
2
3
INFO [main] (OnlineBookService.java:28) - Service OnlineBook started.
-- 17-3-15 18:03:40:694 SmsService: SmsService: started
MyAppIceBox ready

可见两种Log的输出不一样,具体哪种好,看自己选择吧。下面我们给IceBox加一个配置IceBox.LoadOrder=OnlineBook,SmsService,可以指定服务启动的顺序。客户端的调用代码就不贴出来了,比较简单。

新增需求

现在有了两个Ice服务,加入现在增加一个需求,通过发送短息完成Book订购,则需要需要在SmsService服务内部发起对OnlineBook接口的调用,这样SmsService就变成OnlineBook的一个客户端了,所以只要遵循个客户端访问服务端的标准做法去调用即可。修改SmsService.java的sendSms()方法:

1
2
3
4
5
6
7
8
9
10
11
12
public void sendSms(String msg, Current __current) {
// 注意,因为没有加载config.client,此处要用stringToProxy
Ice.ObjectPrx base = _adapter.getCommunicator().stringToProxy("OnlineBook:tcp -h localhost -p 10000");
OnlineBookPrx prxy = OnlineBookPrxHelper.checkedCast(base);
Message message = new Message();
message.name = "bboyjing";
message.type = 1;
message.price = 99.99;
message.valid = true;
message.content = "this is content";
System.out.println("Tick book " + prxy.bookTick(message));
}

还有一种共用Communicator的方式来实现:

  1. 在config.icebox文件中添加如下配置:

    1
    2
    3
    4
    5
    # 打印出线程信息
    Ice.Trace.ThreadPool=1
    # 共用UseSharedCommunicator
    IceBox.UseSharedCommunicator.OnlineBook=1
    IceBox.UseSharedCommunicator.SmsService=1
  2. 修改sendSms()方法中构造Ice.ObjectPrx实例的方式,只要有服务的名称就可以了:

    1
    Ice.ObjectPrx base = _adapter.getCommunicator().stringToProxy("OnlineBook");

这种共用Communicator的方式,据说可以实现服务本地调用的优化,从写法上确实也能看出来,没有了Endpoint信息,只有服务的名称了。到目前为止,我们的Endpoint都是写死的,另外对于多个IceBox集群负载均衡也没涉及到。这就引出了以服务注册表Registry为依托的Service Locator组件,以及依赖其而诞生的强大的分布式框架–IceGrid,下一章节我们就来学习IceGrid的相关内容。