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 及其管理后台都是通过这种技术实现的,仅花钱购买一台低配置的阿里云作前端服务器,调用后端十几个轻重服务搭建而成的(部署在自有机器上)。
附件下载:
本文章转自 http://106.14.193.150/blog/Detail.cshtml?id=59fab9622e0ee312904afcf8#_配置文件
java和c#通过esb服务互调用组件的更多相关文章
- ESB服务号列表
用于以下两个网址: -浙商ESB调用规范- xml格式 -浙商ESB调用规范- json格式 ESB服务号<SERVICE_NO>{serviceNo} 接口中文意思 42000000 ...
- 使用wrapper将java程序注册程windows服务后不生效
使用wrapper将java程序注册程windows服务后不生效 使用add.bat或test***.bat测试通过了, 然后使用install***.bat注册后cmd显示注册成功. 但是程序到了运 ...
- Java进阶(三十一) Web服务调用
Java进阶(三十一) Web服务调用 前言 有朋友问了一个问题:如何调用已知的音乐服务接口,服务文档如下: https://www.evernote.com/shard/s744/sh/c37cd5 ...
- ceph rgw java sdk 使用域名访问服务时需要设置s3client的配置项 PathStyleAccess 为true, 负责将报域名异常
Caused by: java.net.UnknownHostException: my-new-bucket.s3.yyclouds.com at java.net.InetAddress.getA ...
- 使用nodejs和Java访问远程服务器的服务
既然这篇文章用的是nodejs和Java访问远程服务器的服务,那么咱们先用另一门编程语言,SAP的ABAP(我日常工作使用得最多的编程语言)来开发一个服务吧. 这是我用ABAP编程语言实现服务的类:Z ...
- 用 Java 技术创建 RESTful Web (服务 JAX-RS:一种更为简单、可移植性更好的替代方式)
作者: Dustin Amrhein, 软件工程师, IBM Nick Gallardo, 软件工程师, IBM 出处: http://www.ibm.com/developerworks/cn/we ...
- Java生鲜电商平台-深入理解微服务SpringCloud各个组件的关联与架构
Java生鲜电商平台-深入理解微服务SpringCloud各个组件的关联与架构 概述 毫无疑问,Spring Cloud是目前微服务架构领域的翘楚,无数的书籍博客都在讲解这个技术.不过大多数讲解还停留 ...
- Java 实现Redis客户端,服务端
Java 实现Redis客户端,服务端 1.Java实现Redis发布订阅 1.1实例 2.[Redis]Java实现redis消息订阅/发布(PubSub) 3.java实现 redis的发布订阅 ...
- 【微服务】之五:轻松搞定SpringCloud微服务-调用远程组件Feign
上一篇文章讲到了负载均衡在Spring Cloud体系中的体现,其实Spring Cloud是提供了多种客户端调用的组件,各个微服务都是以HTTP接口的形式暴露自身服务的,因此在调用远程服务时就必须使 ...
随机推荐
- python爬取豆瓣前25个影片内容的正则表达式练习
通过python正则表达式获取豆瓣top250的第一页的25个影片排名,影片名字,影片连接,导演,主演,上映日期,国家,剧情,评分,评价人数的内容 网页html内容: <ol class=&qu ...
- [AHOI2008]紧急集合 / 聚会
题目描述 欢乐岛上有个非常好玩的游戏,叫做“紧急集合”.在岛上分散有N个等待点,有N-1条道路连接着它们,每一条道路都连接某两个等待点,且通过这些道路可以走遍所有的等待点,通过道路从一个点到另一个点要 ...
- MT【270】含参绝对值函数最大之二
已知$f(x)=2ax\cos^2x+(a-1)\cos x-1,a>0$,记$|f(x)|$的最大值为$A$,1)求A.2)证明:$|-2a\sin 2x+(1-a)\sin x|\le 2A ...
- Java 枚举 的学习
在JDK5.0之后,引进了一种与C语言相通的枚举类型. 所谓枚举类型就是指含有一组具有固定值, 并且容量有限的数据集合. 例如,定义一个星期的枚举类型, 从周一到周日是具有固定大小和固定值的集合 pu ...
- 【BZOJ5302】[HAOI2018]奇怪的背包(动态规划,容斥原理)
[BZOJ5302][HAOI2018]奇怪的背包(动态规划,容斥原理) 题面 BZOJ 洛谷 题解 为啥泥萌做法和我都不一样啊 一个重量为\(V_i\)的物品,可以放出所有\(gcd(V_i,P)\ ...
- [luogu1972][bzoj1878][SDOI2009]HH的项链【莫队+玄学卡常】
题目大意 静态区间查询不同数的个数. 分析 好了,成功被这道题目拉低了AC率... 打了莫队T飞掉了,真的是飞掉了QwQ. 蒟蒻想不出主席树的做法,就换成了莫队... 很多人都不知道莫队是什么... ...
- emwin 存在多个窗口时,如何获取当前所在窗口
@2019-02-20 [小记] emwin存在多个窗口时,如何获取当前所在窗口 > emwin 之获取当前窗口的一种方法 [需求] 用于在代码中获知当前呈现的是哪个窗口 [方法] 进入新窗口将 ...
- A/D和D/A的学习
从我们学到的知识了解到,我们的单片机是一个典型的数字系统.数字系统只能对输入的数字信号进行处理,其输出信号也是数字信号.但是在工业检测系统和日常生活中的许多物理量都是模拟量,比如温度.长度.压力.速度 ...
- javascript的性能优化tips
谈到javascript的性能优化,有好多点,比如把script放到离body闭合标签附近,合并多个script标签等等,还有一些代码的性能,for的性能不如while的性能好,用while模拟for ...
- jconsole 连接 wildfly 10 监控
1,远程wildfly服务器: 访问:http://211.100.75.242:9990 按照提示添加用户,重启后可以登录进入.成功. 2,省事做法.本地解压wildfly服务器,进入wildfly ...
