微服务
- 对服务进行集中管理调控。高并发互联网设计原则 —— 高负载
、高存储
、高容错
也称 AKF拆分原则
X轴
:服务水平扩展
服务具备可复制性 ,水平分割
,解决一些并发问题
(水平拓展,比性能的垂直提高成本低-摩尔定律)
Y轴
:服务间各司其职
弱耦合,垂直分割
,物理节点物尽其用
(泳道设计)
Z轴
:对x,y
打包,进行物理隔离。
X中有Y,Y中有X
x和y互相转换
y中有x:对y轴作垂直拆分,层与层间独立,为了保证每一层的可用性,每一层作水平分割java
高并发的场景问题 —— 优化思路
如何让服务支持x轴的水平扩展,利用分布式的思惟解决高并发;如何作y中的垂直拆分,是应用之间尽量隔离,弱化服务件耦合度;结合两个维度来解决高并发的场景问题。(Socket + IO)程序员
网络编程:经过编码的方式,让不一样计算机之间相互通讯(数据的传递)。web
两个核心问题:
寻址问题:ip地址+port端口号
协议问题:数据传输格式面试
OSI 七层模型(标准,了解就好)
编程
OSI 五层模型(七层的转变)tomcat
协议
http协议:应用层协议,超文本传输协议,不一样计算机间传输文本的协议(字符串),底层tcp协议
tcp/ip协议:传输层协议安全
tcp协议:传输安全,效率低
udp协议:传输不安全,效率高服务器
BIO 同步阻塞IO
传统IO 或者 Blocking IO
特色:面向流Input | Output
【每一个线程只能处理一个channel(同步的,该线程和该channel绑定)。
线程发起IO请求,无论内核是否准备好IO操做,从发起请求起,线程一直阻塞,直到操做完成。】websocket
NIO 同步非阻塞IO
New IO 或者Non Blocking IO
特色:面向缓冲区Buffer(基于通道)
【每一个线程能够处理多个channel(异步)。
线程发起IO请求,当即返回;内核在作好IO操做的准备以后,经过调用注册的回调函数通知线程作IO操做,线程开始阻塞,直到操做完成 。】网络
AIO(Async Non Blocking IO) 异步非阻塞
【线程发起IO请求,当即返回;内存作好IO操做的准备以后,作IO操做,直到操做完成或者失败,经过调用注册的回调函数通知线程作IO操做完成或者失败 。】
BIO
方向—— 输入、输出流(InputStream | OutputStream)
类型—— 字节、字符流(Reader | Writer)
功能—— 节点、过滤流(BufferedInputStream | BufferedOutputStream )
BIO网络编程
服务端:ServerSocket 【接收和响应,请求转发
- ServerSocket
、 请求响应
- Socket
】
①初始化服务器ServerSocket,绑定监听端口
②等待客户端链接serverSocket.accept();
③处理请求/响应sockect.getInputStream(); / socket.getOutputStream();
④关闭资源
客户端:Socket 【发送和接收,发送请求|接收响应:Socket
】
①初始化客户端Socket,绑定服务器IP/端口
②发起请求/获取响应socket.getOutputStream(); / socket.getInputStream();
③关闭资源
public class BIOBootstrapServer { public static void main(String[] args) throws IOException { server(); } public static void server() throws IOException { //建立服务转发ServerSocket ServerSocket ss = new ServerSocket(); ss.bind(new InetSocketAddress(9999)); //server能够省略好hostname ExecutorService threadPool= Executors.newFixedThreadPool(10); while(true) { //等待请求到来,转发产生Socket(系统内部资源) final Socket socket = ss.accept(); //没有请求就等待,阻塞 //final 匿名内部类使用局部变量要final修饰 threadPool.submit(new Runnable() { public void run() { try { //利用IO,读取用户请求 InputStream req = socket.getInputStream(); InputStreamReader isr = new InputStreamReader(req); BufferedReader br = new BufferedReader(isr); String line = null; StringBuilder sb = new StringBuilder(); while ((line = br.readLine()) != null) { sb.append(line); } System.out.println("服务器收到:" + sb.toString()); //给出用户响应 OutputStream res = socket.getOutputStream(); PrintWriter pw = new PrintWriter(res); pw.println(new Date().toLocaleString()); pw.flush(); socket.shutdownOutput(); //告知客户端写结束 //关闭系统资源 socket.close(); } catch (Exception e) { e.printStackTrace(); } } }); } } }
public class BIOBootstrapClient { public static void main(String[] args) throws IOException { send("这是一条来自client 的 message!"); } public static void send(String msg) throws IOException { //建立Socket对象 Socket s = new Socket(); s.connect(new InetSocketAddress("127.0.0.1",9999)); //因此几乎给ip和端口的,底层走的就是socket //发送请求 OutputStream req = s.getOutputStream(); PrintWriter pw=new PrintWriter(req); pw.println(msg); pw.flush(); s.shutdownOutput();//告知服务端写结束 //接收响应 InputStream res = s.getInputStream(); InputStreamReader isr = new InputStreamReader(res); BufferedReader br = new BufferedReader(isr); String line=null; StringBuilder sb=new StringBuilder(); while((line=br.readLine())!=null){ sb.append(line); } System.out.println("客户端收到:"+sb.toString()); //关闭资源 s.close(); } }
思考下,BIO模型的缺点?
accept转发产生socket资源,一次请求转发等待请求响应的过程有阻塞。main线程做accept请求转发、子线程做socket读写IO处理。
套接字
完成的。套接字,是支持TCP/IP的网络通讯的基本操做单元,能够看作是不一样主机之间的进程进行双向通讯的端点,简单的说就是通讯的两方的一种约定,用套接字中的相关函数来完成通讯过程。
简单的举例说明下:Socket = Ip address + TCP/UDP + port。
每一个socket表明一个系统的随机端口,用来在服务和客户端之间创建链接。
BIO编程诟病 :多线程模型解决服务端并发,可是没法判断当前处理的IO状态是否就绪,此时就会致使线程在作无畏等待,致使系统资源利用率不高。 先开线程 -> 在线程等待IO就绪->处理IO->线程资源释放
//可读的FileChannel FileChannel fr=new FileInputStream("xxx路径").getChannel(); //可写的FileChannel FileChannel fw=new FileOutputStream("xxx路径").getChannel();
文件操做
//读文件件 fr.read(缓冲区) //写文件 fw.write(缓冲区)
flip:pos赋值给limit,post归0
clear:恢复变量为初始状态
public class FileCopyDemo { public static void main(String[] args) throws IOException { //建立读通道 磁盘读入数据 到 ByteBuffer FileInputStream in = new FileInputStream("C:\\Users\\Administrator\\Desktop\\123.txt"); FileChannel fcr = in.getChannel(); //fileChannelRead //建立写通道 将 ByteBuffer 数据写入磁盘 FileOutputStream out = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\321.txt"); FileChannel fcw= out.getChannel(); //fileChannelWrite //建立ByteBuffer ByteBuffer buffer = ByteBuffer.wrap(new byte[1024]);//.allocate()也能够 while (true){ buffer.clear(); int n = fcr.read(buffer); if(n==-1) break; buffer.flip(); fcw.write(buffer); } //关闭资源 fcr.close(); fcw.close(); } }
public class NIOBootstrapServer_Fake { public static void main(String[] args) throws IOException { server(); } public static void server() throws IOException { //建立服务转发ServerSocket ServerSocketChannel ss = ServerSocketChannel.open(); ss.bind(new InetSocketAddress(9999)); ExecutorService threadPool= Executors.newFixedThreadPool(10); while(true) { //等待请求到来,转发产生Socket(系统内部资源) final SocketChannel socket = ss.accept();// 阻塞 threadPool.submit(new Runnable() { public void run() { try{ //读取客户端响应 ByteBuffer buffer=ByteBuffer.allocate(1024); ByteArrayOutputStream baos=new ByteArrayOutputStream();//相似stringbuilder,用来暂存用 while (true){ buffer.clear(); int n = socket.read(buffer); if(n==-1) break; buffer.flip(); baos.write(buffer.array(),0,n); } System.out.println("服务器收到:"+new String(baos.toByteArray())); //给出客户端响应 ByteBuffer respBuffer = ByteBuffer.wrap((new Date().toLocaleString()).getBytes()); socket.write(respBuffer); socket.shutdownOutput();//告知客户端写结束 //关闭系统资源 socket.close(); }catch (Exception e){ } } }); } } }
NIO核心思想,将网络编程中全部操做(转发,读请求,写响应)封装成事件Event,以后用事件形式通知程序进行计算,事件发生则通知程序,这样处理的IO都是就绪的IO,保证计算资源的充分利用。这时候,引入通道选择器
的概念。 咱们须要把通道注册到通道选择器的注册列表中,由通道选择器维护注册列表;一旦咱们所关注的事件发生了,他会把关注的事件封装到事件处理列表当中;为了防止处理空或无效IO,每一个事件处理结束后,要从列表中移除;移除不表明取消注册。只有两种可能才取消注册,一种是通道关闭,一种是主动注销。