分布式RPC框架ZeroC Ice简介

摘要:
在开发分布式或大型软件时,需要进行系统间通信。目前,常用的框架包括HttpRestFul、Thrift、gRPC等。今天分享的ZeroCICe也是其中之一。为了体现Ice的跨语言和跨平台功能,我们使用Java实现服务器端,使用C#实现客户端。

开发分布式或较大型的软件时,必不可少的要进行系统间通信,目前比较常用的框架有Http RestFul,Thrift,gRPC等等,今天分享的ZeroC Ice也是其中一员。

ZeroC公司出品的Ice(Internet Communication Engine)框架专注于RPC通信,经过了10多年的发展,已经非常的成熟,它的主要优点是高性能,跨语言,跨平台,面向对象,开源等等,可以查看其官方网站(https://zeroc.com/products/ice) 了解更多。这里简单介绍一下它的架构和使用方法。

架构和基本概念

先上一张从ZeroC官方网站上截的图:

ZeroC Ice Arch

从图中可以看出,使用Ice的程序分为客户端和服务器端,而两端的代码都由以下三部分组成:

  1. 应用程序代码,这是由使用者编写的部分
  2. 自动生成的代码,由Ice提供的工具自动生成的,为client端生成的叫proxy,为server端生成的叫skeleton
  3. Ice库代码,这部分是Ice框架的核心部分,各个平台都有对应的库

从整体来看,Ice框架的结构还是很清晰的,下面介绍几个关键的概念:

  • Slice(Specification Language for Ice):用于定义client和server通信接口的领域特定语言(DSL),在 https://doc.zeroc.com/ice/3.7/the-slice-language 中有关于它的详细信息
  • Communicator:Ice运行时的入口点,它所关联的资源包括:线程池,运行时的配置属性,对象工厂,Logger(用于处理Ice运行时产生的log消息),Plug-in manager,Object Adapters等
  • Ice Object:是一个抽象的概念,它具有类型,标识等信息,有点像C#或Java里类的概念
  • Servants:上面说到Ice Object是抽象概念,而这里的Servant就是提供具体操作的实体,它负责响应client请求的,一个Servant可以对应一个或者多个Ice Object
  • Proxy:代表Ice Object,client使用proxy来和server交互
  • Ice Object Adapter:存在服务端的communicator中,负责Ice运行时和Server端应用代码的交互,它会和一个或多个Endpoint绑定并接收client端的请求,然后把请求转给对应的Servant从而执行应用代码

使用方法

在了解了Ice的结构和基本概念之后,让我们动手写个demo看看具体怎么使用吧。为了体现Ice的跨语言和跨平台功能,我们这里用Java实现server端,用C#实现client端。程序的主要功能:client可以通过向sever发送A股的股票代码来获得其对应公司的详细信息, 下面我们一起看看具体的步骤。(注:这里的公司信息都是dummy的)

  1. 下载并安装Ice

    https://zeroc.com/download/Ice/3.7/Ice-3.7.4.msi 下载Ice 3.7.4并安装,笔者把它安装在了D:Program Files下面,打开D:Program FilesZeroCIce-3.7.4in文件夹,我们可以看到有名为slice2java.exe, slice2cs.exe的程序,这些就是用来自动生成Java和C#代码的,我们在下面会用到。除了Java和C#的代码生成器,还有许多其他语言的,如:cpp, php等等
    install dir

  2. 定义client和service的交互接口:这里我们定义两个class:CompanyInfo和AStockService:

   module com
   {
      module astock
      {
          class CompanyInfo
          {
              int id;
              string name;
              string addr;
          }
      }
  }

  module com
  {
      module astock
      {
          interface AStockService
          {
              CompanyInfo GetCompanyInfo(int id);
          }
      }
  }   
  1. 使用1中的工具把2中定义的类生成C#和Java对应的代码

    打开cmd,执行下图中的命令,通过执行slice2java和slice2cs程序,我生成了如下图所示的代码,其中C# code只有一个文件,而Java code有四个文件
    分布式RPC框架ZeroC Ice简介第3张

  2. 生成Code的简单介绍

    C#虽然只有一个文件,但是里面包含了三个接口,三个类,一个委托,如下图:
    分布式RPC框架ZeroC Ice简介第4张

    • AStockServiceOperations_接口:包含了我们定义的操作即GetCompanyInfo
    • AStockService接口:我们定义的接口,它继承自AStockServiceOperations_
    • AStockServicePrx接口:客户端代理接口
    • CompanyInfo类: 用于传递数据的DTO
    • AStockServiceDisp_类: 服务端的dispatch抽象类,即上文中说到的skeleton,它实现了我们定义的接口AStockService
    • AStockServicePrxHelper: 客户端的代理类,它实现了AStockServicePrx接口

    Java的code生成了两个类,两个接口

    • AStockService接口:我们定义的接口,也是服务端的skeleton
    • AStockServicePrx接口:客户端代理接口
    • CompanyInfo类: 用于传递数据的DTO
    • _AStockServicePrxI类:客户端代理类
  3. 编写服务端代码

    用熟悉的IDE新建一个工程,笔者使用的Intelij Idea,把上面生成的Java代码加到项目中,并添加Ice的Maven依赖,如下图所示,当然也可以手动下载ice jar包,并手动添加。
    分布式RPC框架ZeroC Ice简介第5张

    下面创建一个类AStockServiceServer,实现AStockService接口,其GetCompanyInfo方法返回一个dummy CompanyInfo对象,如下所示

    
     public class AStockServiceServer implements AStockService {
         @Override
         public CompanyInfo GetCompanyInfo(int id, Current current) {
             CompanyInfo info = new CompanyInfo();
             info.id = 1234;
             info.name = "中国平安";
             info.addr = "深圳";
             return info;
         }
     }
    
    

    创建包含main的class AStockServiceServerMain,如下所示:

    public class AStockServiceServerMain {
        public static void main(String[] args) {
            try (Communicator communicator = Util.initialize()) {//创建communicator
            ObjectAdapter oa = communicator.createObjectAdapterWithEndpoints("AStockServiceAdapter", "default -p 10000");//创建一个Adatper,Id是AStockServiceAdapter,绑定到10000端口

            AStockServiceServer servant = new AStockServiceServer();//我们的服务
            oa.add(servant, Util.stringToIdentity("AStockService"));//把我们创建的服务加到上面创建的adapter里
            oa.activate();//激活adapter
            System.out.println("AStock Service Server is running");//输出启动log
            communicator.waitForShutdown();//等待结束
        }
    }
}
  1. 编写客户端代码

    用VS新建一个控制台程序,并把上面生成的C#代码加入项目中,然后添加Ice的nuget包,如下图所示:
    分布式RPC框架ZeroC Ice简介第6张

    在main函数中编写如下代码:


    class Program
    {
        static void Main(string[] args)
        {
            using (var communicator = Util.initialize(ref args))//创建Communicator对象
            {
                ObjectPrx basePrx = communicator.stringToProxy("AStockService:default -p 10000");//创建客户端基类代理

                AStockServicePrx aStockServicePrx = AStockServicePrxHelper.checkedCast(basePrx);//把基类代理转换为子类代理
                var companyInfo = aStockServicePrx.GetCompanyInfo(1000);//调用GetCompanyInfo方法

                Console.WriteLine($"id:{companyInfo.id} name:{companyInfo.name} addr:{companyInfo.addr}");//输出返回结果
            }
        }
    }

  1. 联调

先运行Java服务端,然后再启动C#程序可以得到如下结果,可以看到Client端成功的获取到了CompanyInfo对象。
分布式RPC框架ZeroC Ice简介第7张

总结

本文介绍了ZeroC Ice的概念并用一个demo详细说明了具体使用方法,完整代码请参考 https://github.com/DerekLoveCC/Writings/tree/master/Article/zerocIce/code ,期望对读者能够有所帮助

Fintech技术汇

免责声明:文章转载自《分布式RPC框架ZeroC Ice简介》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Oracle 获取当前日期及日期格式WPF 中动态创建和删除控件下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

centos7之NFS使用

NFS是Network File System的缩写,即网络文件系统。客户端通过挂载的方式将NFS服务器端共享的数据目录挂载到本地目录下。 一、nfs为什么需要RPC? 因为NFS支持的功能很多,不同功能会使用不同程序来启动,因此,NFS对应的功能所对应的端口无法固定。 端口不固定造成客户端与服务端之间的通信障碍,所以需要RPC来从中帮忙。 NFS启动时会...

Linux远程目录挂载

原文内容来自于LZ(楼主)的印象笔记,如出现排版异常或图片丢失等问题,可查看当前链接:https://app.yinxiang.com/shard/s17/nl/19391737/ad99ab1d-1040-45e0-aaf6-f5d69c247862 问题: 1、如何使A服务器的某个目录挂载到B服务器的某个目录下,使其达到B服务下的目录文件一旦变更,...

RPC框架简单入门之spring-boot整合dubbo

前言 现阶段,web后端开发主流的接口协议类型主要有两种,一种就是我们传统的rest接口,另一种比较流行的就是rpc,今天我们就来简单说下rpc接口,同时我们会通过一个简单示例,来分享dubbo框架的基本用法。 rpc全称Remote Procedure Call,中文的意思是远程程序调用。简单来说,rpc就是一种基于socket的调用方式,一种有别于re...

git clone error:RPC failed; curl 18 transfer closed with outstanding read data remaining

git clone时报RPC failed; curl 18 transfer closed with outstanding read data remaining 错误 error: RPC failed; curl 18 transfer closed withoutstanding read data remaining fatal: The re...

RPC服务和HTTP服务对比

很长时间以来都没有怎么好好搞清楚RPC(即Remote Procedure Call,远程过程调用)和HTTP调用的区别,不都是写一个服务然后在客户端调用么?这里请允许我迷之一笑~Naive!本文简单地介绍一下两种形式的C/S架构,先说一下他们最本质的区别,就是RPC主要是基于TCP/IP协议的,而HTTP服务主要是基于HTTP协议的,我们都知道H...

ICE框架之Slice2CSharp映射---异常的映射

下图显示了异常的继承关系: 下图显示了异常的继承关系: 图中所有的异常都继承自System.ApplicationException异常类,Ice.Exception是System.ApplicationException的子类,而分别用来表示ice run time异常和用户异常的Ice.LocalException、Ice.UserException...