RPC实现原理(HSF、dubbo) 从头开始(一)
前言
阔别了很久博客园,虽然看了以前写的很多东西感觉好幼稚,但是还是觉得应该把一些自己觉得有用的东西和大家分享。废话不多说,现在开始进入正题。
之前的六年工作经验,呆过了一些大公司,每个在大公司呆过的人应该知道,在一个大型应用中不断的增加业务和功能,还有基于性能的考虑,使得很多基础服务必须进行模块化,从而让各子系统方便使用而不是每个系统重新再实现一套,也可以使可能成为瓶颈的基础功能可以单独进行扩展,比如(以电商系统举例)用户信息管理、交易管理中心、商品管理中心等等。 在rpc发展最初,服务进行模块块以后,各个子系统、模块实现的技术五花八门,如:hessian、WebService、Socket、http等进行互相调用,各个子系统之间的交互方式和方法不统一,使得各系统间很难很好的整合。并且这些方式还涉及超时、加密解密、参数的传递等各种问题。 在这种情况下,hsf、dubbo这种高性能rpc中间件出现了。 现在我就已最简单的方式从头开始讲起其中的原理。
我将分为一个系列为大家进行解剖
一、RPC实现原理(HSF、dubbo) 从头开始(一)
二、RPC实现原理(HSF、dubbo)发布一个服务与订阅一个服务(三)
三、RPC实现原理(HSF、dubbo)zookeeper进行集群配置管理(二)
四、RPC实现原理(HSF、dubbo)netty替换java socket(四)
五、待补充
NO.1 TCP传输协议
为什么选择TCP作为传输协议?HTTP在TCP的上一层,位于应用层,TCP位于网络层,以越往底层越快的原理,我就不过多解释为什么选择tcp作为传输协议了。 那么在项目中我们怎么使用tcp进行调用呢?直接上个例子代码:
socket服务端:
import java.net.*;
import java.io.*; /**
* socket编程之:简单socket server
*
* @author chengwei.lcw 2016-11-27
*/
public class SocketServer {
private ServerSocket serverSocket;
private Socket socket;
private BufferedReader in;
private PrintWriter out; public SocketServer() {
try {
serverSocket = new ServerSocket(9999);
while (true) {
// 此处会阻塞,后面会讲到nio的作用
socket = serverSocket.accept();
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
String line = in.readLine();
// 打印出来看看结果
System.out.println("line:" + line); // 返回给client端,通知我已收到数据
out.println("you input is :" + line);
out.close();
in.close();
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
} public static void main(String[] args) {
new SocketServer();
}
}
scoket客户端:
import java.io.*;
import java.net.*; /**
* socket编程之:简单socket client
*
* @author chengwei.lcw 2016-11-27
*/
public class SocketClient {
private Socket socket;
private BufferedReader in;
private PrintWriter out; public SocketClient() {
try {
socket = new Socket("127.0.0.1", 9999);
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// 向服务端写数据
BufferedReader line = new BufferedReader(new InputStreamReader(
System.in)); out.println(line.readLine());
line.close();
// 打印出来服务端发回来的回执
System.out.println(in.readLine()); in.close();
out.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
} public static void main(String[] args) {
new SocketClient();
}
}
先启动server,再启动client,输入参数,回车,两者第一次会话完成。
小结总结:
目前例子中我们使用了标准io socket,这里的很多时候会阻塞,如accept()、read()时都会阻塞。测试的时候可以让客户端睡眠几秒,在这期间启动第二个客户端,这个时候第一个客户端未完成前,第二个客户端是被阻塞在accept()中的。 这种情况可以给每个客户端都单独分配一个线程,但是这样创建过多的线程,可能会严重影响服务器的性能。 第二种解决方案就是使用NIO 非阻塞的通信方式,jdk1.4之后已经引入了这个功能,这样可以使得服务器只要启动一个线程就能处理所有的客户端socket请求。netty就是基于NIO的高性能框架,相比jdk nio做了很多改进,修复了一些缺陷。 (这里不对netty与jdk nio做过多赘述,这不在我们讨论原理细节里,如果大家对这方面有兴趣,我会单独写篇随笔进行深度讲解)
NO.2 序列化方式
在真正的项目中,很多时候我们传的都是自己定义的类。在远程通讯中,类的传输我们需要对类进行序列化和反序列化。序列化的方式有多种,如二进制、xml、soap。我们就以用的最多的二进制进行举例:
socket服务端:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket; /**
* socket编程之:传输对象server
*
* @author chengwei.lcw 2016-11-27
*/
public class SocketObjectSever { private ServerSocket serverSocket;
private ObjectInputStream in;
private ObjectOutputStream out; public SocketObjectSever() {
try {
serverSocket = new ServerSocket(9999); while (true) {
// 此处会阻塞,后面会讲到nio的作用
Socket socket = serverSocket.accept(); in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream()); // 接收server端传来的数据,并转为Student
Student student = (Student) in.readObject();
// 重写了toString()方法,打印出来看看
System.out.println("Server: " + student); // 返回给client端,通知我已收到数据
out.writeObject("yes client, I receive");
out.flush(); } } catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} public static void main(String[] args) {
new SocketObjectSever();
} }
socket客户端:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException; /**
* socket编程之:传输对象client
*
* @author chengwei.lcw 2016-11-27
*/
public class SocketObjectClient {
private Socket socket;
private ObjectInputStream in;
private ObjectOutputStream out; public SocketObjectClient() {
try {
socket = new Socket("127.0.0.1",9999);
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream()); /*
* 建一个student对象,用于传输
*/
Student s = new Student("chengwei.lcw", 28); // 把对象写到管道中,client端进行接收
out.writeObject(s);
out.flush(); String receive = (String) in.readObject();
System.out.println("Client Receive :"+receive); in.close();
out.close();
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} public static void main(String[] args) {
new SocketObjectClient();
} }
另外定义一个要传输的类:
import java.io.Serializable; /**
* socket编程之:要进行传输的类,需要继承Serializable接口
*
* @author chengwei.lcw 2016-11-27
*
*/
public class Student implements Serializable { private static final long serialVersionUID = 1L;
private String name;
private int age; public Student(String name, int age) {
this.name = name;
this.age = age;
} public String toString() {
return "name=" + this.name + ", age=" + this.age;
}
}
依然先启动server,再启动client,server端控制台输出:
Server: name=chengwei.lcw, age=
这样为止,我们的socket可以传输对象了。
这里我们使用的序列化方式为java直接进行序列化,而hessian序列化比Java序列化高效很多,生成的字节流也要短很多,因为hessian在序列化时会把字节流进行压缩。在后面的升级版中我会使用hessian序列化的方式进行序列化。
公司里还有事,而且我不知道这些是不是各位朋友想看到的内容,忙完今天我会继续进行补充。 哪里有讲的不对的希望大家来矫正。
RPC实现原理(HSF、dubbo) 从头开始(一)的更多相关文章
- 原理分析dubbo分布式应用中使用zipkin做链路追踪
zipkin是什么 Zipkin是一款开源的分布式实时数据追踪系统(Distributed Tracking System),基于 Google Dapper的论文设计而来,由 Twitter 公司开 ...
- 原理分析dubbo分布式应用中使用zipkin做链路追踪(转)
作者:@nele本文为作者原创,转载请注明出处:https://www.cnblogs.com/nele/p/10171794.html 目录 zipkin是什么为什么使用Zipkinzipkin架构 ...
- 网络编程 -- RPC实现原理 -- 目录
-- 啦啦啦 -- 网络编程 -- RPC实现原理 -- NIO单线程 网络编程 -- RPC实现原理 -- NIO多线程 -- 迭代版本V1 网络编程 -- RPC实现原理 -- NIO多线程 -- ...
- 网络编程 -- RPC实现原理 -- NIO单线程
网络编程 -- RPC实现原理 -- 目录 啦啦啦 Class : Service package lime.pri.limeNio.optimize.socket; import java.io.B ...
- 网络编程 -- RPC实现原理 -- NIO多线程 -- 迭代版本V1
网络编程 -- RPC实现原理 -- 目录 啦啦啦 V1——设置标识变量selectionKey.attach(true);只处理一次(会一直循环遍历selectionKeys,占用CPU资源). ( ...
- 网络编程 -- RPC实现原理 -- NIO多线程 -- 迭代版本V2
网络编程 -- RPC实现原理 -- 目录 啦啦啦 V2——增加WriteQueue队列,存放selectionKey.addWriteEventToQueue()添加selectionKey并唤醒阻 ...
- 网络编程 -- RPC实现原理 -- Netty -- 迭代版本V1 -- 入门应用
网络编程 -- RPC实现原理 -- 目录 啦啦啦 V1——Netty入门应用 Class : NIOServerBootStrap package lime.pri.limeNio.netty.ne ...
- 网络编程 -- RPC实现原理 -- Netty -- 迭代版本V2 -- 对象传输
网络编程 -- RPC实现原理 -- 目录 啦啦啦 V2——Netty -- 使用序列化和反序列化在网络上传输对象:需要实现 java.io.Serializable 接口 只能传输( ByteBuf ...
- 网络编程 -- RPC实现原理 -- Netty -- 迭代版本V3 -- 编码解码
网络编程 -- RPC实现原理 -- 目录 啦啦啦 V2——Netty -- pipeline.addLast(io.netty.handler.codec.MessageToMessageCodec ...
随机推荐
- UVALive 5135 Mining Your Own Business 双连通分量 2011final
题意:n条隧道由一些点连接而成,其中每条隧道链接两个连接点.任意两个连接点之间最多只有一条隧道.任务就是在这些连接点中,安装尽量少的太平井和逃生装置,使得不管哪个连接点倒塌,工人都能从其他太平井逃脱, ...
- c++学习_2
这里承接上一篇文章,继续记录关于继承的那些事儿... NVI(non-Virtual Interface)和strategy模式 NVI模式和strategy模式是两种不同的方法,可以用来替代virt ...
- HW3.29
import java.util.Scanner; public class Solution { public static void main(String[] args) { Scanner i ...
- Replacing JNI Crashes by Exceptions on Android
http://blog.httrack.com/blog/2013/08/23/catching-posix-signals-on-android/ To Report Or Not To Repor ...
- SecureCRT中文乱码解决方法
在windows下使用SecureCRT访问MAC主机,发现中文总是乱码.而且默认会话选项设置的字符编码就是UTF-8,和MAC主机默认字符编码一样. 后来通过设置,解决了中文乱码问题. 具体使用了两 ...
- 教程-脚本之Python
1.百度python就可以下载到最新版本(Python3.3) PS:我发现用2.7版本写的py文件用 Python3.3打开时,提示错误(print2.7不需要括号3.3必须加括号).2. ...
- windows进程间通信 .
摘 要: 随着人们对应用程序的要求越来越高,单进程应用在许多场合已不能满足人们的要求.编写多进程/多线程程序成为现代程序设计的一个重要特点,在多进程程序设计中,进程间的通信是不可避免的.Microso ...
- 细谈JavaScript中的书写规范
当你有一些感触想写下一些东西的时候,总会发现其实你想写的所有文章都有大牛已经给你写好了,而且写的比你好. https://github.com/ecomfe/spec/blob/master/java ...
- 在java中高效的计数器
在编程中,经常会用到HashMap作为计数器,本文简单介绍三种实现方式 第一种,最直观的计数器. public void naiveCounter(String sArr[]) { HashMap&l ...
- 如何判断C#的Finalizer线程有没有被阻塞
博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:如何判断C#的Finalizer线程有没有被阻塞.