概述

  Ice是一个开源的综合性RPC框架,以高性能和原生支持微服务的架构而著称。提供了很多可以直接使用的组件,如注册中心IceGrid,部署工具IcePatch2,防火墙穿透Glacier2,发布订阅服务IceStorm等。这样的好处就是降低了学习成本和基于中间件的二次开发工作量。同时弊端也很明显就是生态比较封闭,缺乏像Spring Cloud那样全面的技术栈,如服务网关,链路追踪等,因此替换引入组件成本会比较高。
  在国内开源社区和技术论坛的讨论很少见,资料也比较少,基本参考就是官方英文技术文档和源码。有人可能头已经大了,话说看官方技术文档和阅读源码不也是程序猿应该修炼的基本功嘛,英文不行只能边看边学了。

以下是Ice框架的特点:

  • 可压缩,高效的二进制协议
  • 支持同步,异步调用和多种通信协议,如TCP,UDP,WebSockets,Buletooth;
  • 支持多语言实现,如C++,C#,Java,Python等,和跨操作系统,跨平台部署;
  • 支持基于原生的SSL/TLS的安全加密通信;
  • 支持自动的服务发现;
  • 支持面向对象编程模型;

架构

重要抽象概念

Ice有很多抽象概念和术语,基本上这些概念都是继承现有的概念,新增加的抽象很少。所以学习其他RPC架构的同学很容易理解这些概念。

客户端服务端(Client and Server)

客户端和服务端都是相对,可以转换的;

在一次请求交互中,发请求一方为客户端,处理请求的一方为服务端,同时服务端也能是请求的发起方,这时它充当的角色就是客户端。

Ice对象(Ice Object)

这里的Ice对象是特指提供接口服务的对象,而不是我们面向对象编程时的泛指对象。

它有几个特征:

  • 一个Ice对象可能有多个接口类(interface),一个接口类可能包含一系列操作(operation)即函数。
  • 一个Ice对象应该有全局唯一的标识。

对象适配器(Object Adaptor)

可以看做一个Ice对象集合,维护对象ID与对象的映射关系。

代理(Proxies)

是Ice对象在客户端本地的代理,包含向下调用接口和服务地址信息,客户端通过调用接口将请求发送到指定服务端的Ice对象。

一般代理信息以“对象ID:服务地址”的形式表示,其中服务地址是以协议+地址+端口表示。如

SimplePrinter:default -p 10000

上面这种固定ip端口的形式,又称为直接代理(Direct Proxies)

还有一种间接代理(Indirect Proxies)是通过定位服务来获取服务的路由信息。定位服务类似于DNS的域名服务,间接代理的代理信息就相当于URL。

间接代理有两种形式,对象ID或者对象适配器ID;这种通过对象ID就可以访问的对象又称为众所周知的对象(well-known object)

SimplePrinter
SimplePrinter@PrinterAdapter

服务者(Servants)

服务端的人工实现的实际服务对象

复制(Replication)

Ice的复制就是将对象适配器(Object Adaptor)与多个地址关联。就是同个服务在多个机器上运行着实例,以避免单机故障。

客户端的代理支持复制的格式,一个对象ID对应多个连接端点。如下

SimplePrinter:tcp -h server1 -p 10001:tcp -h server2 -p 10002

复制组(Replica Groups)

上面基于直接代理的复制,缺点很明显,对象到服务端点的映射关系是固定。Ice支持一种更有用的复制形式--复制组。

复制组可以看做是一个有动态复制功能的适配器集合。动态复制的能力来自于定位服务,因为定位服务提供了复制组与路由的动态映射关系查询。

复制组有唯一的标识符,由一系列对象适配器组成,一个对象适配器最多属于一个复制组。当一个复制组创建之后,它的标识符可以用来替换间接代理中的适配器标识符。

例如一个标识符为PrinterAdapters的复制组用在代理中:

SimplePrinter@PrinterAdapters

至多一次语义(At-Most-Once Semantics)

就是说一个请求操作至多被执行一次,如果请求传递失败,将会抛一个异常,而不会去重试。只有确认失败了,才会重试。

这个语义对于不是幂等性的操作是安全的,比如++i,操作一次和操作两次得到结果是不一样的。

同步方法调用

调用RPC时,线程被挂起,直到结果返回。

异步方法调用(AMI)

调用RPC时,立即返回,线程可以处理其他工作,等结果返回时会通知该线程

异步方法处理

相当于服务端的AMI,这个请求可能不会被立即处理。适用于需要等待数据,耗时较长的调用过程。

单向调用

就是没有出参的RPC,调用方不需要知道执行的结果。

描述性语言Slice

这是专门为ICE提供的描述性语言,主要是为了定义接口,数据类型。使客户端服务端的开发独立于语言,

可以通过slice工具生成你想要使用的语言,如C++,C#,Java等,生成的这些代码使你只需要关注接口的实现,而不需要关注底层逻辑。

客户端和服务端的结构

Ice客户端和服务端的内部逻辑结构:

客户端和服务端程序是由应用代码、Ice库代码和由slice生成的代码构成的。

  • Ice Core包含支撑通讯的运行时代码,对应用开发屏蔽了底层的网络通信,线程,数据编解码,以及很多网络相关的问题。Ice Core是以一系列库的形式提供给客户端,服务端使用。Ice Core的配置管理是通过Ice API来操作的。
  • Proxy Code代理代码由slice定义产生,是服务端Ice对象的代理。它主要有两个功能,一是为客户端应用提供向下调用接口,以请求消息的形式发给服务端,然后服务端调用相关联的接口;二是数据结构的编解码,以便于网络传输。
  • Skeleton Code 骨架代码由slice定义产生,提供向上调用接口,允许Ice运行时将客户端请求传递到你实现的服务端代码。同时也包含了对参数的解码,返回结果合异常的编码。

环境部署

参考官方文档:https://doc.zeroc.com/ice/3.7/release-notes/using-the-linux-binary-distributions

HelloWord

以下简单demo是以c++11实现的。完成源码见:https://github.com/GodMonking/ice-demo/tree/main/simple

定义slice文件

slice文件命名必须以.ice结尾。如Printer.ice

module Demo
{
interface Printer
{
void printString(string s);
}
}

编译slice文件生成c++代码:

slice2cpp Printer.ice

服务端代码

#include <Ice/Ice.h>
#include <Printer.h>
using namespace std;
using namespace Demo;
class PrinterI : public Printer
{
public:
virtual void printString(string s, const Ice::Current&) override;
};
void
PrinterI::printString(string s, const Ice::Current&)
{
cout << s << endl;
}
int
main(int argc, char* argv[])
{
try
{
//初始化通信器
Ice::CommunicatorHolder ich(argc, argv);
//根据名称、连接端点创建一个对象适配器
auto adapter = ich->createObjectAdapterWithEndpoints("SimplePrinterAdapter", "default
-p 10000");
//创建一个servant对象,将其添加到对象适配器
auto servant = make_shared<PrinterI>();
adapter->add(servant, Ice::stringToIdentity("SimplePrinter"));
//激活对象适配器,监听服务请求
adapter->activate();
ich->waitForShutdown();
}
catch(const std::exception& e)
{
cerr << e.what() << endl;
return 1;
}
return 0;
}

由Printer.ice生成的Printer.h包含骨架代码(Skeleton Code),一个接口类包含一个纯虚接口如下,详细代码省略:

#include <Ice/Ice.h>
#include <Printer.h>
using namespace std;
using namespace Demo;

namespace Demo
{
class Printer : public virtual Ice::Object
{
public:
virtual void printString(std::string, const Ice::Current&) = 0;
};
}

编译服务端代码:

c++ -I. -DICE_CPP11_MAPPING -c Printer.cpp Server.cpp
c++ -o server Printer.o Server.o -lIce++11

客户端代码

#include <Ice/Ice.h>
#include <Printer.h>
#include <stdexcept>
using namespace std;
using namespace Demo;
int
main(int argc, char* argv[])
{
try
{
//初始化通信器
Ice::CommunicatorHolder ich(argc, argv);
//通过 “对象ID:对象适配器连接端点” 获取代理对象
auto base = ich->stringToProxy("SimplePrinter:default -p 10000");
//转类型校验是否合法
auto printer = Ice::checkedCast<PrinterPrx>(base);
if(!printer)
{
throw std::runtime_error("Invalid proxy");
}
//通过代理对象调用接口
printer->printString("Hello World!");
}
catch(const std::exception& e)
{
cerr << e.what() << endl;
return 1;
}
return 0;
}

编译客户端代码:

c++ -I. -DICE_CPP11_MAPPING -c Printer.cpp Client.cpp
c++ -o client Printer.o Client.o -lIce++11

运行程序

运行服务端程序:

./server

执行客户端程序:

./client

服务显示结果:

结尾

这篇文章主要是介绍了Ice框架的优缺点,架构组成以及一个简单Demo。后续文章会介绍几种服务部署方案。

Ice框架介绍的更多相关文章

  1. ICE简单介绍及使用示例

    转自:http://blog.csdn.net/zhu2695/article/details/51494664 1.ICE是什么? ICE是ZEROC的开源通信协议产品,它的全称是:The Inte ...

  2. [连载]《C#通讯(串口和网络)框架的设计与实现》-1.通讯框架介绍

    [连载]<C#通讯(串口和网络)框架的设计与实现>- 0.前言 目       录 第一章           通讯框架介绍... 2 1.1           通讯的本质... 2 1 ...

  3. YARN基本框架介绍

    YARN基本框架介绍 转载请注明出处:http://www.cnblogs.com/BYRans/ 在之前的博客<YARN与MRv1的对比>中介绍了YARN对Hadoop 1.0的完善.本 ...

  4. Selenium自动化测试框架介绍

    Selenium自动化测试框架介绍 1.测试架构作用 a.可维护性 b.提高编写脚本效率 c.提高脚本的可读性 2.框架的几大要素: Driver管理,脚本,数据,元素对象,LOG,报告,运行机制,失 ...

  5. UiAutomator自动化测试框架介绍

    UiAutomator自动化测试框架介绍 环境搭建 1         必要条件 1.1       JDK 1.2       SDK(API高于15) 1.3       Eclipse 2    ...

  6. [翻译]Spring框架参考文档(V4.3.3)-第二章Spring框架介绍 2.1 2.2 翻译--2.3待继续

    英文链接:http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/overview.ht ...

  7. MJExtension框架介绍

    MJExtension框架介绍 标签: MJExtension 2015-05-01 08:22 1120人阅读 评论(0) 收藏 举报  分类: Foundation(14)  版权声明:本文为博主 ...

  8. 人工智能深度学习Caffe框架介绍,优秀的深度学习架构

    人工智能深度学习Caffe框架介绍,优秀的深度学习架构 在深度学习领域,Caffe框架是人们无法绕过的一座山.这不仅是因为它无论在结构.性能上,还是在代码质量上,都称得上一款十分出色的开源框架.更重要 ...

  9. 挑战EXT——QUI框架介绍与下载

    挑战EXT——QUI框架介绍与下载 为庆祝新版QUI问世特写此文: 提起EXTJS的大名,恐怕WEB开发界无人不晓吧.EXTJS框架发展到现在,已经非常成熟和全面了.它的组件库尤其是DataGrid组 ...

随机推荐

  1. mini-web框架-装饰器-总结2(5.3.2)

    @ 目录 1.说明 2.代码 关于作者 1.说明 多级装饰器嵌套 带参数的装饰器 这里打印print(index) 会在函数定义的时候@test(222) 就被调用,返回一个test2继续装饰 2.代 ...

  2. 安装nodejs 版本控制器

    安装下载地址: https://pan.baidu.com/s/1Ed_IPDTOHxR9NShUEau-ZA 下载好后,放在安装nodejs的文件夹下 然后敲cmd,进入安装nodejs的文件夹下. ...

  3. 豆瓣读书top250数据爬取与可视化

    爬虫–scrapy 题目:根据豆瓣读书top250,根据出版社对书籍数量分类,绘制饼图 搭建环境 import scrapy import numpy as np import pandas as p ...

  4. 浅析Python闭包

    1.什么是闭包 在介绍闭包概念前,我们先来看一段简短的代码 def sum_calc(*args): def wrapper(): sum = 0 for n in args: sum += n; r ...

  5. Gitlab+Jenkins构建一个Go项目

    部署Go项目简介 对于golang的发布,之前一直没有一套规范的发布流程,来看看之前发布流程: 方案一 • 开发者本地环境需要将环境变量文件改为正式环境配置 • 编译成可执行文件 • 发送给运维 • ...

  6. MM-采购模块相关业务

    采购模块主要业务流程: 1.收集采购需求(采购申请单),系统采购申请单单据可以由需求部门手工产生,也可以由系统的MRP(物料需求计划)来产生. 2,货源确定,用来确定所申请的物料,通过何种方式向供应商 ...

  7. [LeetCode]100. Same Tree判断树相同

    dfs遍历一下判断 public boolean isSameTree(TreeNode p, TreeNode q) { if (p==null) { return q == null; } els ...

  8. 【探索之路】机器人篇(2)-ROS系统并创建工作空间和项目

    在ROS官网,已经给出了详细的教程.下面我就般一下砖,把相应的操作写到这里.官方网址:http://wiki.ros.org/cn/ 安装ROS系统 indigo在ubuntu上的安装教程.官网:ht ...

  9. java函数方法学习

    1.函数(方法)定义 类中特定功能小程序 2.函数定义格式 修饰符 返回值类型 函数名 (参数类型 形式参数) { 执行语句; return 返回值 } 函数功能实现的2个明确 1.这个功能的结果是什 ...

  10. mysql性能调优注意事项

    1.最左原则  注意遇到> < like  between失效 2.对于like 查询  遇到最左%索引无效 3.SQL性能优化目标:至少要达到range(对索引进行范围查找)级别,要求是 ...