ice grid 第一篇
关键点:
(1)如果想提高并发的话,还是在一个node上对于同一个application开多个server instance.
1.名词解释
。Replica groups
A replica group is the term for a collection of replicated object adapters. An
application can create any number of replica groups. Each group requires a
unique identifier.
• Nodes
An application must assign its servers to one or more nodes.
• Servers
A server’s description includes a unique name and the path to its executable. It
also lists the object adapters it creates.
• Object adapters
Information about an object adapter includes its endpoints and any wellknown
objects it advertises. If the object adapter is a member of a replica
group, it must also supply that group’s identifier.
• Objects
A well-known object is one that is known solely by its identity. The registry
maintains a global list of such objects for use during locate requests.
IceGrid uses the term descriptor to refer to the description of an application
代理
直接代理;:对象 和 地址 。例如,代理: SimplePrinter:default -p 10000
间接代理:两种。第一种仅仅包含well-known objects(众所周知对象),例如代理 SimplePrinter 就是对象SimplePrinter的代理。第二种包含对象和对象适配器标识,例如,SimplePrinter@PrinterAdapter
2.一个简单的ice架构(ice registry只提供定位服务)
(1)客户端代码:
Ice::ObjectPrx proxy =
communicator->stringToProxy("factory@EncoderAdapter");//第一步是定位服务,通过括号内的"对象@对象适配器id"找到了代理
Ripper::MP3EncoderFactoryPrx factory =
Ripper::MP3EncoderFactoryPrx::checkedCast(proxy); //第二步是使用代理得到想要的远端对象。是对远端对象的第一次调用
Ripper::MP3EncoderPrx encoder = factory->createEncoder();
(2)配置文件
registry 配置:
/opt/ripper/registry.cfg contains the following properties:(前五个必选)
IceGrid.InstanceName=inputtest //如果不写。默认是IceGrid
IceGrid.Registry.Client.Endpoints=tcp -p 4061
IceGrid.Registry.Server.Endpoints=tcp
IceGrid.Registry.Internal.Endpoints=tcp
IceGrid.Registry.Data=/opt/ripper/registry
IceGrid.Registry.DynamicRegistration=1
IceGrid.Registry.AdminPermissionsVerifier=IceGrid/NullPermissionsV
erifier
IceGrid.Registry.AdminCryptPasswords=../etc/passwd //这个选项倒是很有意思,可以设置操作admin的权限
client配置文件:
Ice.Default.Locator=IceGrid/Locator:tcp -h registryhost -p 4061 (在没有写IceGrid的名字的情况下)
server配置,opt/ripper/server.cfg
EncoderAdapter.AdapterId=EncoderAdapter (对象适配器id)
EncoderAdapter.Endpoints=tcp //不写端口地址,表明系统自动分配端口
Ice.Default.Locator=IceGrid/Locator:tcp -h registryhost -p 4061
(3)启动
启动registry
icegridregistry --Ice.Config=/opt/ripper/registry.cfg
启动server
/opt/ripper/bin/server --Ice.Config=/opt/ripper/server.cfg
3 使用ice registry来管理server(xml和node)
3.1 使用xml文件描述server,使用node
为了使用icegridadmin管理工具,我们使用xml配置sever文件:
<icegrid>
<application name="Ripper">
<node name="Node1">
<server id="EncoderServer"
exe="/opt/ripper/bin/server"
activation="on-demand">
<adapter name="EncoderAdapter"
id="EncoderAdapter"
endpoints="tcp"/>
</server>
</node>
</application>
</icegrid>
事实上,以上的描述文件会生成一个server的配置文件如下,由node生成(文件位置在类似/opt/ripper/node/servers/EncoderServer/config/config):
# Server configuration
Ice.Admin.ServerId=EncoderServer
Ice.Admin.Endpoints=tcp -h 127.0.0.1
Ice.ProgramName=EncoderServer
# Object adapter EncoderAdapter
EncoderAdapter.Endpoints=tcp
EncoderAdapter.AdapterId=EncoderAdapter
Ice.Default.Locator=IceGrid/Locator:default -p 4061
# Registry properties
IceGrid.Registry.Client.Endpoints=tcp -p 4061
IceGrid.Registry.Server.Endpoints=tcp
IceGrid.Registry.Internal.Endpoints=tcp
IceGrid.Registry.AdminPermissionsVerifier=IceGrid/NullPermissionsV
erifier
IceGrid.Registry.Data=/opt/ripper/registry
# Node properties
IceGrid.Node.Endpoints=tcp
IceGrid.Node.Name=Node1
IceGrid.Node.Data=/opt/ripper/node
IceGrid.Node.CollocateRegistry=1 //标明registry和node在一个进程中
Ice.Default.Locator=IceGrid/Locator:tcp -p 4061
因为使用协同的registry和node,所以一个命令可以启动registry和node
icegridnode --Ice.Config=/opt/ripper/config
说明:(1)如果没有标明adapter id,那么默认生成id名字为:EncoderServer.EncoderAdapter
3.2 增加节点
(1)server配置
<icegrid>
<application name="Ripper">
<node name="Node1">
<server id="EncoderServer1"
exe="/opt/ripper/bin/server"
activation="on-demand">
<adapter name="EncoderAdapter"
endpoints="tcp"/>
</server>
</node>
<node name="Node2">
<server id="EncoderServer2"
exe="/opt/ripper/bin/server"
activation="on-demand">
<adapter name="EncoderAdapter"
endpoints="tcp"/>
</server>
</node>
</application>
</icegrid>
(2)node配置
IceGrid.Node.Endpoints=tcp
IceGrid.Node.Name=Node2
IceGrid.Node.Data=/opt/ripper/node
Ice.Default.Locator=IceGrid/Locator:tcp -h registryhost -p 4061
(3)客户端
缺陷就是每个server上一个不同的object adapter id,需要进行选择。(这对于增删节点等都很麻烦)
非直接代理:
• factory@EncoderServer1.EncoderAdapter
• factory@EncoderServer2.EncoderAdapter
string adapter;
if ((rand() % 2) == 0)
adapter = "EncoderServer1.EncoderAdapter";
else
adapter = "EncoderServer2.EncoderAdapter";
Ice::ObjectPrx proxy =
communicator->stringToProxy("factory@" + adapter);
Ripper::MP3EncoderFactoryPrx factory =
Ripper::MP3EncoderFactoryPrx::checkedCast(proxy);
Ripper::MP3EncoderPrx encoder = factory->createEncoder();
4 well-known objects(众所周知对象)
4.1 概念
有两种类型的简介代理:一种指定对象标识和对象适配器标志(object@object_adapter_id) ;一种仅仅指定对象标志。后者称为众所周知代理(well-known proxy),它指向well-known object(众所周知对象)。
可以通过以下几个地方声明:
XML文件。 (statically in descriptors,)
icegrid admin的编程接口 • programmatically using IceGrid’s administrative interface,
使用 ice admin工具动态添加 • dynamically using an IceGrid administration tool.
下面是一个例子,well-known对象和它们的代理
Identity Proxy
Object1 Object1:tcp -p 10001
Object2 Object2@TheAdapter
Object3 Object3
4.2 生成well-known对象
(1)xml文件中
<icegrid>
<application name="Ripper">
<node name="Node1">
<server id="EncoderServer"
exe="/opt/ripper/bin/server"
activation="on-demand">
<adapter name="EncoderAdapter"
id="EncoderAdapter"
endpoints="tcp">
<object identity="EncoderFactory"
type="::Ripper::MP3EncoderFactory"/>
</adapter>
</server>
</node>
</application>
</icegrid>
(2)通过编程接口
接口api说明如下,
module IceGrid {
interface Admin {
...
void addObject(Object* obj)
throws ObjectExistsException,
DeploymentException;
void updateObject(Object* obj)
throws ObjectNotRegisteredException,
DeploymentException;
void addObjectWithType(Object* obj, string type)
throws ObjectExistsException,
DeploymentException;
void removeObject(Ice::Identity id)
throws ObjectNotRegisteredException,
DeploymentException;
...
};
};
编程实现,
Ice::ObjectAdapterPtr adapter =
communicator->createObjectAdapter("EncoderAdapter");
Ice::Identity ident =
communicator->stringToIdentity("EncoderFactory");
FactoryPtr f= new FactoryI;
Ice::ObjectPrx factory = adapter->add(f, ident);
IceGrid::AdminPrx admin = // ...
try {
// admin->addObject(factory); // OOPS!,要求首先激活object adapter
admin->addObjectWithType(factory, factory->ice_id());
} catch (const IceGrid::ObjectExistsException &) {
admin->updateObject(factory);
}
(3)
icegridadmin --Ice.Config=/opt/ripper/config
>>> object add "EncoderFactory@EncoderAdapter"
4.3 使用ice query查找 well-known objects
(1)接口说明:
module IceGrid {
enum LoadSample {
LoadSample1,
LoadSample5,
LoadSample15
};
interface Query {
idempotent Object* findObjectById(Ice::Identity id);
idempotent Object* findObjectByType(string type);
idempotent Object* findObjectByTypeOnLeastLoadedNode(
string type, LoadSample sample);
idempotent Ice::ObjectProxySeq findAllObjectsByType(
string type);
idempotent Ice::ObjectProxySeq findAllReplicas(Object* proxy);
};
};
(2)示例,
一个含有两个well-known objects的例子
<icegrid>
<application name="Ripper">
<node name="Node1">
<server id="EncoderServer1"
exe="/opt/ripper/bin/server"
activation="on-demand">
<adapter name="EncoderAdapter"
endpoints="tcp">
<object identity="EncoderFactory1"
type="::Ripper::MP3EncoderFactory"/>
</adapter>
</server>
</node>
<node name="Node2">
<server id="EncoderServer2"
exe="/opt/ripper/bin/server"
activation="on-demand">
<adapter name="EncoderAdapter"
endpoints="tcp">
<object identity="EncoderFactory2"
type="::Ripper::MP3EncoderFactory"/>
</adapter>
</server>
</node>
</application>
</icegrid>
客户端查找,
1)使用findAllObjectsByType函数
Ice::ObjectPrx proxy =
communicator->stringToProxy("IceGrid/Query");
IceGrid::QueryPrx query = IceGrid::QueryPrx::checkedCast(proxy);
Ice::ObjectProxySeq seq;
string type = Ripper::MP3EncoderFactory::ice_staticId();
seq = query->findAllObjectsByType(type);
if (seq.empty()) {
// no match
}
Ice::ObjectProxySeq::size_type index = ... // random number
Ripper::MP3EncoderFactoryPrx factory =
Ripper::MP3EncoderFactoryPrx::checkedCast(seq[index]);
Ripper::MP3EncoderPrx encoder = factory->createEncoder();
2)使用findObjectByTypeOnLeastLoadedNode函数
Ice::ObjectPrx proxy =
communicator->stringToProxy("IceGrid/Query");
IceGrid::QueryPrx query = IceGrid::QueryPrx::checkedCast(proxy);
Ice::ObjectPrx obj;
string type = Ripper::MP3EncoderFactory::ice_staticId();
obj = query->findObjectByTypeOnLeastLoadedNode(type,
IceGrid::LoadSample1);
if (!obj) {
// no match
}
Ripper::MP3EncoderFactoryPrx factory =
Ripper::MP3EncoderFactoryPrx::checkedCast(obj);
Ripper::MP3EncoderPrx encoder = factory->createEncoder();
到底怎样才是well-known对象?
1.1 replica group(对象适配器复制集群)
(1) 概念
一个复制集群是一组复制的对象适配器;有一个唯一的标识。
一个复制集群被确定之后,他的标识就可以被用在间接代理中替代适配器标识;比如,一个标识为PrinterAdapters的复制集群可以被用在如下的代理:
SimplePrinter@PrinterAdapters
(2)示例
<replica-group id="ReplicatedAdapter">
<load-balancing type="adaptive" load-sample="5" n-replicas="2"/>
</replica-group>
load-balancing type 表示负载均衡策略;
load-sample 负载采样时间间隔,以分钟计;
n-replicas 返回两个负载最小的对象适配器的端点地址
负载平衡策略包括四种:Random ,Adaptive,Round Robin,Ordered。
(3)问题
采样的时候,linux系统采样的是load average,这样当机器cpu数目不同时,岂不是无法有效利用cpu了?
问题:
(1)既然registry location服务,那么是不是说一个client连接上之后,请求只会被发送到一个node的server上?没错。
但是通过设置,可以指定server,这样就可以发送到不同的node上的server 了
(2) adapter_ = communicator->createObjectAdapter(name); //objectadapter名字
Ice::PropertiesPtr properties = communicator->getProperties();
const string& locator = properties->getProperty("Ice.Default.Locator");
LOG(INFO, "locator: " << locator);
BunnyConf::instance().set_locator(locator);
Ice::ObjectPtr object = new HandlerI(); //ice对象
adapter_->add(object, communicator->stringToIdentity("M")); // 这个ice对象的标识是“M”
adapter_->activate();
(3)当使用registry 时,object id 可以同时使用object:tcp -p 10001 和 object@adapter 两种形式
(4)replica-group意思?
(5)ice box代替了原来的server,包含程序的真正入口。它可以包含多个service,即多个真正的服务。
貌似有了ice box后,server就是ice box ,详细来说,就是 ice box id。
但是server 又可以包含 ice box
(6)对象适配器的意思
顾名思义,还是对象,不过改变了形态,
(7)icebox service entry 后边的参数的规定是--name=value这种形式的视为communicator的属性,其余才视为start的参数。可是事实上input服务中是可以通过args读取到这种类型的参数的
规定:Any arguments following the entry point specification are examined. If an
argument has the form --name=value, then it is interpreted as a property definition
that appears in the property set of the communicator passed to the service
start operation. These arguments are removed, and any remaining arguments are
passed to the start operation in the args parameter.
start函数:
void start(string name,
Ice::Communicator communicator,
Ice::StringSeq args)
ice grid 第一篇的更多相关文章
- ice grid配置使用第二篇------实际使用
一 首先,启动ice grid 1 修改配置文件 node.cfg,appication.xml 修改registry.cfg 配置注册表信息: IceGrid.Registry.Client. ...
- ImageJ 学习第一篇
ImageJ是世界上最快的纯Java的图像处理程序.它可以过滤一个2048x2048的图像在0.1秒内(*).这是每秒40万像素!ImageJ的扩展通过使用内置的文本编辑器和Java编译器的Image ...
- 第一篇 入门必备 (Android学习笔记)
第一篇 入门必备 第1章 初识Android 第2章 搭建你的开发环境 第3章 创建第一个程序--HelloWorld 第4章 使用Android工具 ●Android之父 Android安迪·罗 ...
- Java图像处理最快技术:ImageJ 学习第一篇
ImageJ是世界上最快的纯Java的图像处理程序. 它能够过滤一个2048x2048的图像在0.1秒内(*). 这是每秒40万像素!ImageJ的扩展通过使用内置的文本编辑器和Java编译器的Ima ...
- 从0开始搭建SQL Server AlwaysOn 第一篇(配置域控)
从0开始搭建SQL Server AlwaysOn 第一篇(配置域控) 第一篇http://www.cnblogs.com/lyhabc/p/4678330.html第二篇http://www.cnb ...
- Python爬虫小白入门(四)PhatomJS+Selenium第一篇
一.前言 在上一篇博文中,我们的爬虫面临着一个问题,在爬取Unsplash网站的时候,由于网站是下拉刷新,并没有分页.所以不能够通过页码获取页面的url来分别发送网络请求.我也尝试了其他方式,比如下拉 ...
- Three.js 第一篇:绘制一个静态的3D球体
第一篇就画一个球体吧 首先我们知道Three.js其实是一个3D的JS引擎,其中的强大之处就在于这个JS框架并不是依托于JQUERY来写的.那么,我们在写这一篇绘制3D球体的文章的时候,应该注意哪些地 ...
- 深入学习jQuery选择器系列第一篇——基础选择器和层级选择器
× 目录 [1]id选择器 [2]元素选择器 [3]类选择器[4]通配选择器[5]群组选择器[6]后代选择器[7]兄弟选择器 前面的话 选择器是jQuery的根基,在jQuery中,对事件处理.遍历D ...
- 【第一篇】ASP.NET MVC快速入门之数据库操作(MVC5+EF6)
目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...
随机推荐
- caffe层解读系列-softmax_loss
转自:http://blog.csdn.net/shuzfan/article/details/51460895 Loss Function softmax_loss的计算包含2步: (1)计算sof ...
- phabricator 搭建
os:debian7 Installation Guide :https://secure.phabricator.com/book/phabricator/ $ cd /data # 安装目录 da ...
- C++内存申请容易产生的错误
1.起因 前两天用python写了一款工具用来把excel文件转换成json文件,今天给他们用的时候发现在文本下看正常,但是在程序中使用就是会多出一些莫名其妙的字符. 2. 调查 原来主要是我写的工具 ...
- log4j2配置MDC分线程写日志
1.MDC是一个高级一些的工具,可以配置分用户(userid)写日志,也可以分线程 2.方法和道理都是相似的,在写入日志之前配置线程名或者用户id 3.如果将线程名配置为目录,可以将不同线程的日志输送 ...
- Hibernate框架--对象的状态,缓存, 映射
回顾Hibernate第二天: 1. 一对多与多对一 2. 多对多 3. inverse/cascade 4. 关联关系的维护 一对多: <set name="映射的集合属性&quo ...
- Hbase查看
Client HBase Client使用HBase的RPC机制与HMaster和HRegionServer进行通信,对于管理类操作,Client与HMaster进行RPC:对于数据读写类操作,Cli ...
- ios xcode中所有自带的字体如下(最好结合NSMutableAttributedString相结合使用)
// 打印系统中所有字体的类型名字 NSArray *familyNames = [UIFont familyNames]; for(NSString *familyName in familyNam ...
- 2012-11-17 12:28 用MFC实现的计算器(详细版)
这篇文章里通过计算器的简单实现,让大家能够了解一般对话框应用程序开发的基本流程 要求:编写简单的计算器应用程序,要求利用按钮进行加.减.乘,除操作,在对话框输出计算机结果. 下面结合操作步骤,讲解对话 ...
- VS中的快捷键快速格式化代码,使好看,整齐
在VC2005中,快捷键是Ctrl + K, Ctrl + F, 这是一个组合键,即先按Ctrl + K, 这时候编辑器会等待下一个按键动作,此时再按Ctrl + F, 即可以格式化代码了,当然,也可 ...
- gets()
C: #include <stdio.h> //这个头文件包含gets()函数,这个函数在ISO/IEC 9899 2011(C11)标准中被移除 int main(void) { ...