前言
架构说简单点就是一堆技术、框架、工具的组合,至于怎么组合,这就非常考验架构师的经验和水平。一个优秀的架构,可以让开发效率变得更加高效,为企业节省更多的成本。程序员可将自己更多的精力放在业务需求的实现上,不会被底层的复杂技术细节所干扰。
架构师(或从事架构工作的人)就像是探险者一样,他们走在团队的前面,为大家铺.路,带领大家找到成功捷径。此外,做架构工作不能照搬别人所谓的最佳实践,而要根据自身实际情况,因地制宜地灵活选择,设计最为合理的架构。架构的目的是为了让业务变得更加容易落地,降低开发成本与统--开发规范。架构师的职责就是避免大家踩坑,他们需要将自己的经验总结下来,并带领大家走最正确的路。架构师不只是在体验探险的凶险和快乐,而是把探险所积累的经验沉淀下来,让后面更多的人从中受益。
随着互联网浪潮风起云涌,互联网行业发展非常迅猛。此时将所有业务集中实现在一个应用上的做法已经满足不了公司及业务发展的需要了。基于面向服务体系架构来构建系统成了互联网架构师构建系统的不二选择,而面向服务体系架构能够落地的基础技术之一就是分布式服务框架。
RPC框架原理
RPC ( Remote Procedure Call,远程过程调用)一般用来实现部署在不同机器上的系统之间的方法调用,使得程序能够像访问本地系统资源一样,通过网络传输去访问远端系统资源。RPC框架实现的架构原理都是类似的,如下图所示。
在该架构中,下面几个方面是重点。
- Client Code: 客户端调用方代码实现,负责发起RPC调用,为调用方用户提供使用API。
- Serialization/Deserialization: 负责对RPC调用通过网络传输的内容进行序列化与反序列化,不同的RPC框架有不同的实现机制。主要分为文本与二进制两大类。文本类别的序列化机制主要有XML与JSON两种格式,二进制类别的序列化机制常见的有Java原生的序列化机制,以及Hessian. protobuf、Thrift. Avro、 Kryo、MessagePack等,不同的序列化方式在可读性、码流大小、支持的数据类型及性能等方面都存在较大差异,需要用户根据自己的实际情况进行甄别与筛选。
- Stub Proxy:可以看作是一-种代理对象,屏蔽RPC调用过程中复杂的网络处理逻辑,使得PRC调用透明化,能够保持与本地调用一样的代码风格。
- Transport:作为RPC框架底层的通信传输模块,- -般通过Socket 在客户端与服务端之间传递请求与应答消息。
- ServerCode:服务端服务业务逻辑具体的实现。下面几节分别针对目前常用的几类RPC框架做介绍。
RMI介绍
Java RMI ( Remote Method Invocation)是一种基于Java的远程方法调用技术,是Java特有的一-种RPC实现。它能够使部署在不同主机上的Java对象之间进行透明的通信与方法调用,如下图所示。
RMI特性总结如下所述。
支持真正的面向对象的多态性。 而完全支持面向对象也是RMI相对于其他RPC框架的优势之一。
- Java 语言独有,不支持其他语言,能够完美地支持Java语言所独有的特性。
- 使用了 Java原生的序列化机制,所有序列化对象必须实现java.io.Serializable接口。
- 底层通信基于BIO (同步阻塞I/O) 实现的Socket完成。
因Java原生序列化机制与BIO通信机制本身存在性能问题,导致RMI的性能较差, .对性能要求高的使用场景不推荐该方案。
原生RMI代码示例
RMI使用示例如下所述
定义RMI对外服务接口HelloService:
import java. rmi . Remote;
import java. rmi . RemoteException;
public interface HelloService extends Remote {
String sayHello (String someOne) throws RemoteException;
}
RMI接口方法定义必须显式声明抛出RemoteException异常
服务端接口实现HelloServicelmpl:
import java. rmi . RemoteException;
import java. rmi . server .Unicas tRemoteobject;
public class Hel loServiceImpl extends UnicastRemoteobject implements
HelloService {
private static final long serialVersionUID = -6190513770400890033L;
public HelloServiceImpl () throws RemoteException {
super() ;
}
@Override
public String sayHe11o (String someOne) throws RemoteException {
return "Hello," + someOne;
}
服务端方法实现必须继承UnicastRemoteObject 类,该类定义了服务调用方与服务提供方对象实例,并建立一对一的连接。
服务端RMI服务启动代码:
import java . rmi . Naming;
import java. rmi . registry . LocateRegistry;
public class ServerMain {
public static void main(String[] args) throws Exception {
//创建服务
HelloService helloService = new HelloServiceImpl () ;
//注册服务
LocateRegistry . createRegistry(8801) ;
Naming . bind ("rmi://localhost: 8801 /helloService", helloService) ;
System. out.println ("ServerMain provide RPC service now") ;
}
}
客户端远程调用RMI服务代码:
import rmi .