面向服务的体系架构(SOA)

1、基于TCP协议的RPC

1.1、RPC名词解释:

RPC(Remote Process Call):远程过程调用。它应用广泛,实现方式也很多,拥有RMI(remote method invocation)、WebService等诸多成熟的方案,在业界得到广泛的应用。

RPC的实现包括客户端和服务端,即服务的调用方和服务的服务方。服务调用方发送RPC请求到服务提供方,服务提供方根据调用方提供的参数执行请求方法,将执行结果返回给调用方,一次RPC调用完成。

1.2、对象序列化:

无论是何种类型的数据,最终都需要转换成二进制流在网络上传输。在面向对象的程序设计中,如何将一个定义好的对象传输到远端呢?数据的发送方需要将对象转换为二进制流,才能在网络上进行传输,而数据的接收方则需要把二进制流转换为对象。

  • 将对象转换为二进制流的过程称为对象的序列化。
  • 将二进制流恢复为对象的过程称为对象的反序列化。

对象的序列化与反序列化有多种成熟的解决方案,较为常用的有Google的ProtocalBuffers、Java本身内置的序列化方式、Hessian以及JSON和XML等。

这里重点介绍Java内置的序列化方式和基于Java的Hessian序列化方式:

1、Java内置的序列化方式所实现对象序列化和反序列化的关键代码:

//定义一个字节数组输出流
ByteArrayOutputStream os = new ByteArrayOutputStream();
//对象输出流
ObjectOutputStream out = new ObectOutputStream(os);
//将对象写入到字节数组输出,进行序列化
out.writeObject(zhangsan);
byte[] zhangsanByte = os.toByteArray();

//字节数组输入流
ByteArrayInputStream is = new ByteArrayInputStream(zhangsanByte);
//进行反序列化,从流中读取对象
ObjectInputStream in = new ObjectInputStream(is);
Person person = (Person) in.readObject();

通过java.io包下的ObjectOutputStream的writeObject方法,将Person类的实例zhangsan序列化为字节数组,然后再通过ObjectInputStream的readObject方法将字节数组反序列化为person对象。

2、使用Hessian进行序列化,需要引入其提供的三方包Hessian-4.0.7.jar,针对基于java的Hessian的序列化和反序列化的实现:

ByteArrayOutputStream os = new ByteArrayOutputStream();
//Hessian的序列化输出
HessianOutput ho = new HessianOutput(os);
ho.writeObject(zhangsan);
byte[] zhangsanByte = os.toByteArray();

ByteArrayInputStream is = new ByteArrayInputStream(zhangsanByte);
//Hessian的反序列化读取对象
HessianInput hi = new HessianInput(is);
Person person = (Person) hi.readObject();

1.3、基于TCP协议实现RPC:

基于Java的SocketAPI,我们能够实现一个简单的RPC调用,这个例子中包含了服务的接口及接口的远端实现、服务的消费者与远端的提供方。如下图所示:

public interface SayHelloService() {
    public String sayHello(String helloArg);
}

服务的实现:

扫描二维码关注公众号,回复: 3279777 查看本文章
public class SayHelloServiceImpl implements SayHelloService {
    @Override
    pulbic String sayHello(String helloArg) {
        if(helloArg.equals("hello")) {
            return "hello";
        }else{
            return "bye bye";
        }
    }
}

服务消费者Consumer类的部分关键代码:

//接口名称
String interfacename = SayHelloService.class.getName();

//需要远程执行的方法
Method method = SayHelloService.class.getMethod("sayHello",java.lang.String.class);
//需要传递到远端的参数
Object[] arguments = = {"hello"};
Socket socket = new Socket("127.0.0.1","1234");
//将方法名称和参数传递到远端
ObjectOutputStream os = new ObjectOutputStream(socket.getOutputStream());
os.writeUTF(interfacename); //接口名称
os.writeUTF(method.getName()); //方法名称
os.writeObject(method.getParameterTypes());
os.writeObject(arguments);

//从远端读取方法执行结果
ObjectInputStream is = new ObjectInputStream(socket.getInputStream);
Object result = is.readObject();

服务提供者Provider类的部分关键代码:

ServerSocket server = new ServerSocket(1234);
while(true) {
    Socket socket = server.accept();
    
    //读取服务信息
    ObjectInputStream is = new ObjectInputStream(socket.getInputStream());
    String interfacename = is.readUTF(); //接口名称
    String methodName = is.readUTF(); //方法名称
    Class<?>[] parameterTypes = (Class<?>[]) is.readObject(); //参数类型
    Object[] arguments = (Object[]) is.readObject(); //参数对象

    //执行调用
    Class interfacenameclass = Class.forName(interfacename); //得到接口的class
    Object service = services.get(interfacename); //取得服务实现的对象
    Method method = interfacenameclass.getMethod(methodName,parameterTypes); //获得要调用                  的方法
    Object result = method.invoke(service,arguments);
    
    ObjectOutputStream os = new ObjectOutputStream(socket.getOutputStream());
    os.writeObject(result);
}

服务提供端事先将服务实例化好后放在services这个Map中,通过一个while循环,不断的接收新到来的请求,得到所需要的参数,包括接口名称、方法名称、参数类型和参数,通过java的反射取得接口中需要调用的方法,执行后将结果返回给服务的消费者。

2、基于HTTP协议的RPC

2.1、HTTP协议栈:

2.2、HTTP请求与相应:

2.3、通过HttpClient发送HTTP请求:

2.4、使用HTTP协议的优势:

2.5、JSON和XML:

2.6、RESTful和RPC:

2.7、基于HTTP协议的RPC的实现:

猜你喜欢

转载自blog.csdn.net/MyronCham/article/details/82758585