当前位置: 首页 > news >正文

java和c#通过esb服务互调用组件

场景:java和c#写的服务、站点,互相任意调用。实现一切即服务。

解决方案:使用这种轻量级的esb架构,通过tcp通信解决通信传输问题,总线服务解决服务地址问题,契约解决数据交互问题。由于组件封装了底层细节,比较方便好用,所以开发效率还是挺高的。

 

 

主组件:

Java: Ljc.JFramework.jar(jre1.8)

C#:Ljc.Framework.dll(.net4.5)

LJC.FrameWork.SOA.dll

依赖组件:无

 

使用方法:

前提:

需要一个总线服务。总线服务的作用就是接收服务注册,并转发请求,客户端口不需要关心服务的地址。总线服务可以发布在任何地方,只需要ip端口能访问。

ESBServer _esb = new ESBServer(20000); //总线使用的tcp端口

_esb.StartServer(); //启动

 

开发跨语言服务

1、添加配置文件

 

2、设计服务契约

这个是服务请求和响应的需要的类,见后面契约部分。

 

3、编写服务

增加一个服务,继承类ESBService,并且增加一个构造函数,然后重写方法DoResponse,获取请求参数,响应服务调用。

Java的demo:

public final class SparkService extends ESBService {

 

public SparkService(int sNo, boolean supportTcpServiceRidrect) throws Exception {

super(sNo, supportTcpServiceRidrect);

// TODO Auto-generated constructor stub

}

 

@Override

 public Object DoResponse(Tuple<Integer,byte[]> tup) throws java.lang.Exception{

 int funid=tup.GetItem1();

 byte[] buffer=tup.GetItem2();

 

 switch(funid) {

 case 1:

 {

              //解析出请求参数

 SubmitSparkRequest request=EntityBufCore.DeSerialize(SubmitSparkRequest.class, buffer, true);

 

 //使用请求处理业务

              ...

 

 SubmitSparkResponse resp= new SubmitSparkResponse();

 resp.setSuccess(true);

 

             //返回结果

 return resp;

 }

 }

 

 return super.DoResponse(tup);

 }

}

 

C#的demo:

class SparkTaskCallBackService:ESBService

    {

        public SparkTaskCallBackService()

            : base(101)

        {

        }

 

        public override object DoResponse(int funcId, byte[] Param)

        {

 

            switch(funcId){

                case 1:

                    {

                        //这里获取请求参数

                        var request = EntityBufCore.DeSerialize<CallBackRequest>(Param);

                        

 

                        //响应

                        return new CallBackResponse

                        {

                            Success=true

                        };

                    }

            }

            return base.DoResponse(funcId, Param);

        }

}

 

4、注册服务到总线

 

//100是要注册到总线的服务号

//由于只通过总线转发,不接受客户端直调,所以第二个参数为false,如果要接收客户端直接调用,第二个参数为true,但需要把服务加到防火墙白名单,

//这种模式下,服务会随机起一个端口,注册时会告知总线该服务端口,但客户端要通过DoSOARequest2调用,DoSOARequest2是DoSOARequest的增强版本,支持不通过总线自动直连服务

SparkService _sparkservice = new SparkService(100, false);

_sparkservice.StartService();

 

 

 

5、服务关闭后注销服务

Java

try {

_sparkservice.UnRegisterService();

catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

_sparkservice.CloseClient();

C#

     service.UnRegisterService();

     service.Dispose();



客户端调用服务

1、添加配置文件

2、添加或者引用目标服务提供的契约,具体看下面契约部分

3、调用方法

 //仅通过总线调

 响应契约=ESBClient.DoSOARequest(服务号,功能号,请求契约)

//如果能直调目标服务就直调,不支持就通过总线调

 响应契约=ESBClient.DoSOARequest2(服务号,功能号,请求契约)

Java:

Date end=new Date();

      CallBackRequest request=new CallBackRequest();

      request.setSparkTaskId(sparktaskid);

      request.setStartTime(start);

      request.setEndTime(end);

      request.setErrorOutPut(errinfo);

      request.setStdOutPut(stdinfo);

      request.setSuccess(errinfo=="");

 

CallBackResponse resp= Ljc.JFramework.SOA.ESBClient.DoSOARequest(CallBackResponse.class, Statics.CallBackServiceNo, Statics.Fun_CallBack, request);

 

C#:

 var resp = ESBClient.DoSOARequest<SubmitSparkResponse>(SubmitContract.Consts.SparkServiceNo,

Consts.Fun_SubmitSpark, new SubmitSparkRequest()

                                {

                                    Context = new SparkLauncherContext

                                    {

                                        AppResource = item.AppResource,

                                        MainClass = item.MainClass,

                                        Master = item.Master,

                                        SparkHome = item.SparkHome,

                                    },

                                    TaskId = item._id.ToString()

                                });

 

 

配置文件

配置文件名称:ESBConfig.xml

   内容:

   <?xml version="1.0" encoding="utf-16"?>

<ESBConfig>

  <ESBServer>127.0.0.1</ESBServer>

  <ESBPort>20000</ESBPort>

  <AutoStart>true</AutoStart>

</ESBConfig>

   

字段

含义

说明

ESBServer

总线地址

支持ipv4,和计算机名

ESBPort

总线端口

 

AutoStart

是否自动启动

固定为true

  说明:java服务放到程序执行目录下,net服务放到程序目录下,net web放到网站根目录下。

 

关于契约

Esb组件仅使用内置的序列化和反序列化机制,不依赖外部其它的如json/pb的序列化器工作。

契约包括请求契约和响应契约,调用方发送请求契约,服务方返回响应契约。

契约可以是简单的数据类型如int,string等,也可以是复杂的结构化类型,建议不要用简单的类型来作契约,后期扩展性差,且建议使用一对xxxRequest/xxxResponse规范命名。由于契约是要被序列化和反序列化的,类型有限制。简单类型目前只支持以下类型:

Java类型

Net类型

 

java.lang.Short/short

Short

 

java.lang.Integer/int

Int16/int

 

不支持

UInt16

 

不支持

Ushort

 

java.lang.Long/long

Int32/long/Int64

 

java.lang.Byte/byte

Byte

 

char/java.lang.Character

Char

 

java.lang.Double/double

Double

 

java.lang.Float/float

Float

 

java.lang.String

String

 

java.util.Date

DateTime

 

Boolean/boolean

bool

 

java.util.HashMap

Dictionary

 

java.util.List

List

 

Array

Array

 

不支持

enum

 

不支持

Decimal

 

Complex(复杂对象)

Complex(复杂对象)

成员类型必须是上面支持的类型,或者也是Complex及Complext的数组,Complext的列表或字典

 

说明:跨越java和c#的契约字段类型按上面对照,list和array是两种数据类型,不能对应。有些字段java不支持,如果c#服务要求的契约包含这种数据,java无法调成功。字段名称不一样,但字段类型要一致,顺序也要对应,字段要写成属性,java用getxxx和setxxx,net写成public 类型 xxx{get;set;}。

Java:

public class SubmitSparkRequest {

   private SparkLauncherContext _context;

   private String _taskId;

   

   public SparkLauncherContext getContext()

   {

   return this._context;

   }

   

   public void setContext(SparkLauncherContext value) {

   this._context=value;

   }

   

   public String getTaskId()

   {

   return this._taskId;

   }

   

   public void setTaskId(String value) {

   this._taskId=value;

   }

}

 

C#:

public class SubmitSparkRequest

    {

        public SparkLauncherContext Context

        {

            get;

            set;

        }

 

        public String TaskId

        {

            get;

            set;

        }

    }

 

跨语言情况下,服务端契约和客户端契约应该单独写成文件最好不要混合其它无关的字段和方法,防止干扰出错,下面列出服务端契约变动的影响:

情况

影响

必须同步契约

服务端改契约字段名或者类名

无影响

不需要

服务端改契约字段类型

调方失败

需要

服务端在响应契约末尾增加字段

调方获取不了新字段,旧的无影响

不一定需要

服务端删除字段

调方失败

需要

 

关于性能问题:

1、c#服务使用的是iocp技术,java使用的是iocp/epoll保证了服务端性能,服务端内部全异步操作,没有等待线程,服务端与客户端保持长连接并且自动断线重连,定时心跳。简单起见,一般情况下使用总线转发就行了,粗略测试情况下吞吐量10000左右,java作总线性能高30%左右,如果要求较高,可以使用服务端直接调用方式,不通过总线转发,且多个相同的服务可以实现简单负载均衡(须部署在不同机器上),c#之间实现通过udp调用,吞吐量可达30000左右(传输速度1.5GB/s)。序列化为了使用方便采用的是内置自己实现的,尽量通明化和傻瓜化,性能上c#单线程序列化反序化十个字段小对象可达百万每秒。目前网站http://106.14.193.150/blog/ 和http://106.14.193.150/cjzf 及其管理后台都是通过这种技术实现的,仅花钱购买一台低配置的阿里云作前端服务器,调用后端十几个轻重服务搭建而成的(部署在自有机器上)。

 

附件下载:

dotnet.rar

Ljc.JFramework.jar.rar

  本文章转自 http://106.14.193.150/blog/Detail.cshtml?id=59fab9622e0ee312904afcf8#_配置文件

转载于:https://www.cnblogs.com/lhxsoft/p/8609558.html

相关文章:

  • 4、自定义cookieHandler发送请求
  • python 魔法方法补充(__setattr__,__getattr__,__getattribute__)
  • /*在DataTable中更新、删除数据*/
  • A* 简介(Amit's A star Page中译文)
  • 文本挖掘的基本过程
  • python web开发-flask读取txt文件内容
  • (C#)获取字符编码的类
  • codefroces 911G Mass Change Queries
  • Chrome浏览器几个好用的插件
  • SQL——两个表之间的更新:用一个表的字段更新另一个表的字段
  • [root]既然sudo 可以暂时获取root权限,那么为何还需要root这个用户呢
  • A*,IDA*,Dijkstra
  • AES对上传文件解密并加密的实现(JAVA实现)
  • Utilities之EXPIMP小结
  • HPU 1166: 阶乘问题(一)
  • 2017 前端面试准备 - 收藏集 - 掘金
  • create-react-app做的留言板
  • gf框架之分页模块(五) - 自定义分页
  • iOS 颜色设置看我就够了
  • JWT究竟是什么呢?
  • markdown编辑器简评
  • Mocha测试初探
  • MQ框架的比较
  • mysql中InnoDB引擎中页的概念
  • nfs客户端进程变D,延伸linux的lock
  • October CMS - 快速入门 9 Images And Galleries
  • python_bomb----数据类型总结
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • RedisSerializer之JdkSerializationRedisSerializer分析
  • redis学习笔记(三):列表、集合、有序集合
  • 仿天猫超市收藏抛物线动画工具库
  • 给第三方使用接口的 URL 签名实现
  • 观察者模式实现非直接耦合
  • 基于Dubbo+ZooKeeper的分布式服务的实现
  • 紧急通知:《观止-微软》请在经管柜购买!
  • 力扣(LeetCode)56
  • 面试总结JavaScript篇
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 数据结构java版之冒泡排序及优化
  • 数组的操作
  • 算法之不定期更新(一)(2018-04-12)
  • 通信类
  • 微信支付JSAPI,实测!终极方案
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • ​​​​​​​ubuntu16.04 fastreid训练过程
  • # 安徽锐锋科技IDMS系统简介
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • $emit传递多个参数_PPC和MIPS指令集下二进制代码中函数参数个数的识别方法
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (一)Java算法:二分查找
  • (转)使用VMware vSphere标准交换机设置网络连接
  • (转)真正的中国天气api接口xml,json(求加精) ...
  • (转载)hibernate缓存