发表于: 2019-10-24 19:28:04

1 949


一、今天完成的事
1.初步了解Tuscany,写了demo未通过

2.任务八深度思考

1.部署两台Service,如何在WEB中随机访问任意一台Service?  

通过获取一个随机数(1或2),根据随机数的不同去访问(getbean)不同的service。

2.RMI的简单介绍 

RMI:远程方法调用(Remote Method Invocation)。能够让在客户端Java虚拟机上的对象像调用本地对象一样调用服务端java 虚拟机中的对象上的方法。
RMI远程调用步骤:
(1)客户调用客户端辅助对象stub上的方法
(2)客户端辅助对象stub打包调用信息(变量,方法名),通过网络发送给服务端辅助对象skeleton
(3)服务端辅助对象skeleton将客户端辅助对象发送来的信息解包,找出真正被调用的方法以及该方法所在对象
(4)调用真正服务对象上的真正方法,并将结果返回给服务端辅助对象skeleton
(5)服务端辅助对象将结果打包,发送给客户端辅助对象stub
(6)客户端辅助对象将返回值解包,返回给调用者
(7)客户获得返回值
RMI的使用局限
(1)RMI目前使用Java远程消息交换协议JRMP(Java Remote Messaging Protocol)进行通信。JRMP是专为Java的远程对象制定的协议,由于JRMP是专为Java对象制定的,因此,RMI对于用非Java语言开发的应用系统的支持不足。不能与用非Java语言书写的对象进行通信(意思是只支持客户端和服务器端都是Java程序的代码的远程调用)。
(2)由于客户机和服务器都是使用Java编写的,二者平台兼容性的要求仅仅是双方都运行在版本兼容的Java虚拟机上。
RMI调用远程方法的参数和返回值
当调用远程对象上的方法时,客户机除了可以将原始类型的数据作为参数一外,还可以将对象作为参数来传递,与之相对应的是返回值,可以返回原始类型或对象,这些都是通过Java的对象序列化(serialization)技术来实现的。(换而言之:参数或者返回值如果是对象的话必须实现Serializable接口)

3.什么是RMI,什么是RPC,两者之间的区别是什么?

RPC(Remote Procedure Call Protocol)远程过程调用协议,通过网络从远程计算机上请求调用某种服务。

RPC要解决的问题:
解决分布式系统中,服务之间的调用问题。
远程调用时,要能够像本地调用一样方便,让调用者感知不到远程调用的逻辑。
RMI可以理解为是RPC在java中的一种实现,是一种面向对象的RPC。

区别:

(1)方法调用方式不同:
 RMI中是通过在客户端的Stub对象作为远程接口进行远程方法的调用每个远程方法都具有方法签名。如果一个方法在服务器上执行,但是没有相匹配的签名被添加到这个远程接口(stub)上,那么这个新方法就不能被RMI客户方所调用
  RPC中是通过网络服务协议向远程主机发送请求,请求包含了一个参数集和一个文本值,通常形成“classname.methodname(参数集)”的形式。RPC远程主机就去搜索与之相匹配的类和方法,找到后就执行方法并把结果编码,通过网络协议发回。
(2)适用语言范围不同:
RMI只用于Java;
RPC是网络服务协议,与操作系统和语言无关。
(3)调用结果的返回形式不同:
Java是面向对象的,所以RMI的调用结果可以是对象类型或者基本数据类型;
RMI的结果统一由外部数据表示 (External Data Representation, XDR) 语言表示,这种语言抽象了字节序类和数据类型结构之间的差异。

4.Service和Service之间可以互相调用吗?是应该统一Controller调用Service,还是应该Service调用Service?

可以,只要service对外暴露了接口,就可以service访问.统一由controller调用service.

5.Service对外暴露的接口粒度应该是怎么样的,是只提供基础的CRUD服务,还是应该将业务逻辑包含进去?

只提供基础的CRUD服务,业务逻辑在controller里

6.Thrift,Protobuffer分别是什么,一般用于什么场景?

Thrift是一种接口描述语言和二进制通讯协议,它被用来定义和创建跨语言的服务。它被当作一个远程过程调用(RPC)框架来使用,是由Facebook为“大规模跨语言服务开发”而开发的。

Thrift主要功能是:通过自定义的Interface Definition Language(IDL),可以创建基于RPC的客户端和服务端的服务代码。数据和服务代码的生成是通过Thrift内置的代码生成器来实现的。Thrift 的跨语言性体现在,它可以生成C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml , Delphi等语言的代码,且它们之间可以进行透明的通信。

Thrift实际上是实现了C/S模式,通过代码生成工具将接口定义文件生成服务器端和客户端代码(可以为不同语言),从而实现服务端和客户端跨语言的支持。用户在Thirft描述文件中声明自己的服务,这些服务经过编译后会生成相应语言的代码文件,然后用户实现服务(客户端调用服务,服务器端提服务)便可以了。其中protocol(协议层, 定义数据传输格式,可以为二进制或者XML等)和transport(传输层,定义数据传输方式,可以为TCP/IP传输,内存共享或者文件共享等)被用作运行时库。

Thrift支持二进制,压缩格式,以及json格式数据的序列化和反序列化。这让用户可以更加灵活的选择协议的具体形式。更完美的是,协议是可自由扩展的,新版本的协议,完全兼容老的版本!


protobuffer是google提供的一个开源序列化框架,类似于XML,JSON这样的数据表示语言,其最大的特点是基于二进制,因此比传统的XML表示高效短小得多。虽然是二进制数据格式,但并没有因此变得复杂,开发人员通过按照一定的语法定义结构化的消息格式,然后送给命令行工具,工具将自动生成相关的类,可以支持php、java、c++、python等语言环境。通过将这些类包含在项目中,可以很轻松的调用相关方法来完成业务消息的序列化与反序列化工作。
     protobuf在google中是一个比较核心的基础库,作为分布式运算涉及到大量的不同业务消息的传递,如何高效简洁的表示、操作这些业务消息在google这样的大规模应用中是至关重要的。而protobuf这样的库正好是在效率、数据大小、易用性之间取得了很好的平衡。

7.什么是序列化和反序列化,在RMI中是否要实现 Serializable 接口, serialVersionUID的用处是什么?

把对象转换为字节序列的过程称为对象的序列化
把字节序列恢复为对象的过程称为对象的反序列化

电脑数据通过二进制序列进行传输的,那么如果我们需要将Java对象进行传输的时候,肯定也要先将对象进行序列化,然后通过网络,IO进行传输,当完成之后,再进行反序列化获取到我们想要的对象,最后完成通信。

当然要实现Serializable接口;serialVersionUID是使用于java的序列化机制,java的序列化机制是通过判断类的SerialVersionUID来验证版本的一致性。进行反序列化时,JVM会将将传进来的字节流中的serialVersionUID与本地相应的实体类的SerialVersionUID进行比较,相同就认为是一致的,可以进行反序列化。而且要设置该属性,如果不设置会随机生成默认的SerialVersionUID,序列化和反序列时的SerialVersionUID就会不一致,反序列化会失败

8.Controller通过RMI调用服务是否有延迟?10条Long型的ID循环调用1000次,和本地调用之间的时间相差多少?

远程调用肯定有延迟了




二、遇到的问题
创建Tuscany.composite文件需要改一下idea设置
在这里删掉*.composite
然后在这里再添加*.composite
测试的时候报错

换classpath还是没解决
三、收获
1.tuscany是什么
Tuscany 是 Apache 的开源项目,它是 IBM、Oracle、SAP 等厂商联合成立的 SOA 标准化组织 -OSOA 支持下开发出的 SCA 框架,它既是开源界 SCA 的试金石,也是当前开源界最成熟的 SCA 框架之一。
tuscany是一套开源的SCA框架模型,是做SOA的基础架构
SCA是什么?
SCA为构建基于SOA的应用和解决方案提供了编程模型。它基于这样的理念:将业务功能作为一系列的服务而提供,并由这一系列的服务组装起来的解决方案来满足特定业务需求。这些组合的应用既包括为应用而新创建的特定服务,也包括源自已已存在系统和应用的业务逻辑,这些业务逻辑作为组合构件的一部分被复用。SCA既为服务的组合也为服务构件的创建提供了模型,包括对SCA组组合构件中对已存在应用功能的复用。
SCA的基础工件就是component,它是SCA的构成单元。构件(component)由一个实现的可配置(implementation)实例所组成。在该构件中,实现是提供业务功能的程序代码片段。该业务功能作为服务(service)而提供,为其他构件所使用。实现也许依赖于由其他构件所提供的服务,这些依赖被称作”引用”(reference)。实现可以有一个可设置的属性(properties),该属性是可以影响业务功能操作的数据值。构件通过提供属性值和连线(wire)到由其他构件提供服务的引用来配置实现。
看一下发布一个基本的加减乘除的示例,这个是tuscany的官方示例
public interface CalculatorService {
double add(double n1, double n2);
double subtract(double n1, double n2);
double multiply(double n1, double n2);
double divide(double n1, double n2);
}
public class CalculatorServiceImpl implements CalculatorService {
private AddService addService;
private SubtractService subtractService;
private MultiplyService multiplyService;
private DivideService divideService;
@Reference
public void setAddService(AddService addService) {
this.addService = addService;
}
@Reference
public void setSubtractService(SubtractService subtractService) {
this.subtractService = subtractService;
}
@Reference
public void setDivideService(DivideService divideService) {
this.divideService = divideService;
}
@Reference
public void setMultiplyService(MultiplyService multiplyService) {
this.multiplyService = multiplyService;
}
@Override
public double add(double n1, double n2) {
return addService.add(n1, n2);
}
@Override
public double subtract(double n1, double n2) {
return subtractService.subtract(n1, n2);
}
@Override
public double multiply(double n1, double n2) {
return multiplyService.multiply(n1, n2);
}
@Override
public double divide(double n1, double n2) {
return divideService.divide(n1, n2);
}
}
public interface AddService {
double add(double n1, double n2);
}
public class AddServiceImpl implements AddService {
@Override
public double add(double n1, double n2) {
return n1+n2;
}
}
public interface DivideService {
double divide(double n1, double n2);
}
public class DivideServiceImpl implements DivideService {
@Override
public double divide(double n1, double n2) {
return n1/n2;
}
}
public interface MultiplyService {
double multiply(double n1,double n2);
}
public class MultiplyServiceImpl implements MultiplyService {
@Override
public double multiply(double n1, double n2) {
return n1*n2;
}
}
public interface SubtractService {
double subtract(double n1, double n2);
}
public class SubtractServiceImpl implements SubtractService {
@Override
public double subtract(double n1, double n2) {
return n1 - n2;
}
}
<?xml version="1.0" encoding="UTF-8"?><composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
name="CalculatorServiceComponent"
targetNamespace="http://com.ksy.service">
<component name="CalculatorServiceComponent">
<implementation.java class="calculator.CalculatorServiceImpl"/>
<reference name="addService" target="AddServiceComponent" />
<reference name="subtractService" target="SubtractServiceComponent" />
<reference name="multiplyService" target="MultiplyServiceComponent" />
<reference name="divideService" target="DivideServiceComponent" />
</component>
<component name="AddServiceComponent">
<implementation.java class="com.ksy.service.serviceImpl.AddServiceImpl"/>
</component>
<component name="SubtractServiceComponent">
<implementation.java class="com.ksy.service.serviceImpl.SubtractServiceImpl"/>
</component>
<component name="MultiplyServiceComponent">
<implementation.java class="com.ksy.service.serviceImpl.MultiplyServiceImpl"/>
</component>
<component name="DivideServiceComponent">
<implementation.java class="com.ksy.service.serviceImpl.DivideServiceImpl"/>
</component>
</composite>
public class CalculateClient {
public static void main(String[] args) {
Node node = NodeFactory.newInstance().createNode("Tuscany.composite");
node.start();
CalculatorService c = node.getService(CalculatorServiceImpl.class,"CalculatorServiceComponent");
System.out.println("服务已启动!");
System.out.println(c.add(2, 2));
System.out.println("3 + 2 = " + c.add(3, 2));
System.out.println("3 - 2 = " + c.subtract(3, 2));
System.out.println("3 * 2 = " + c.multiply(3, 2));
System.out.println("3 / 2 = " + c.divide(3, 2));
node.stop();
}
}

@Reference和@Resource区别

前者是dubbo注解,后者是spring 的。

后者@resource很简单就是注入资源,与@Autowired比较接近,只不过是按照变量名(beanid)注入。
@reference也是注入,但是一般用来注入分布式的远程服务对象,需要配合dubbo配置使用。
他们的区别就是一个是本地spring容器,另一个是把远程服务对象当做spring容器中的对象一样注入。



四、明天的计划

查看为通过demo的原因,继续做任务


返回列表 返回列表
评论

    分享到