Nginx
反向代理
Nginx作为一个高性能且高可用的HTTP服务器,反向代理、负载均衡和流量管控是它最拿手的三样本领。
作为反向代理的搜素引擎,可以让用户不必记住并在浏览器的地址栏上输入每种提供服务的网站网址,而只需要在搜索出来的结果上轻点鼠标,即可访问网站服务,这正是典型的反向代理服务。
Nginx作为一个高性能且高可用的HTTP服务器,反向代理、负载均衡和流量管控是它最拿手的三样本领。
作为反向代理的搜素引擎,可以让用户不必记住并在浏览器的地址栏上输入每种提供服务的网站网址,而只需要在搜索出来的结果上轻点鼠标,即可访问网站服务,这正是典型的反向代理服务。
理论
前几年,社会上逐渐兴起了一种叫做C2C
同城快递的业务模式,也就是俗称的跑腿闪送
。比如,当某人需要送个东西给朋友石昊,而路人甲刚好也要去石昊所在的地方,那么他就可以接单跑腿。这样既满足了需求,又可以顺便挣点跑腿费。
说了这么多理论,但最终还是只有通过代码才能更好地体现NIO技术的优势,下面来看看NIO
的Channel
和Buffer
是不是会比BIO
更有效率。
package cn.javabook.chapter11.nio;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
* NIO中的Channel和Buffer
*
*/
public class TestNIO {
public static void main(String[] args) throws IOException {
// 传统I/O
long start = System.currentTimeMillis();
FileInputStream fis1 = new FileInputStream("/testfile1");
FileOutputStream fos1 = new FileOutputStream("/testfile2");
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fis1), 1024);
String line = null;
while ((line = bufferedReader.readLine()) != null) {
fos1.write(line.getBytes());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
fis1.close();
fos1.close();
}
long end = System.currentTimeMillis();
System.out.println("传统IO耗时:" + (end - start) + " 毫秒");
// 改进的I/O
start = System.currentTimeMillis();
FileInputStream fis2 = new FileInputStream("/testfile1");
FileOutputStream fos2 = new FileOutputStream("/testfile3");
try {
byte[] b = new byte[1024];
int len = 0;
while ((len = fis2.read(b)) != -1) {
fos2.write(b, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
fis2.close();
fos2.close();
}
end = System.currentTimeMillis();
System.out.println("改进的IO耗时:" + (end - start) + " 毫秒");
// NIO
start = System.currentTimeMillis();
FileChannel fis3 = new FileInputStream("/testfile1").getChannel();
FileChannel fos3 = new FileOutputStream("/testfile4").getChannel();
try {
ByteBuffer bytedata = ByteBuffer.allocate(1024);
while (fis3.read(bytedata) != -1) {
// 读写交叉进行
bytedata.flip();
fos3.write(bytedata);
bytedata.clear();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
fis3.close();
fos3.close();
}
end = System.currentTimeMillis();
System.out.println("NIO耗时:" + (end - start) + " 毫秒");
// // Scattering reads
// ByteBuffer buffer1 = ByteBuffer.allocate(1024);
// ByteBuffer buffer2 = ByteBuffer.allocate(1024);
// ByteBuffer[] bufferArray1 = { buffer1, buffer2 };
// FileChannel channel1 = new FileInputStream("/Users/bear/home/work/testfile1").getChannel();
// channel1.read(bufferArray1);
//
// // Gathering writes
// ByteBuffer buffer3 = ByteBuffer.allocate(1024);
// ByteBuffer buffer4 = ByteBuffer.allocate(1024);
// ByteBuffer[] bufferArray2 = { buffer1, buffer2 };
// FileChannel channel2 = new FileInputStream("/Users/bear/home/work/testfile1").getChannel();
// channel2.write(bufferArray2);
}
}
注意
这一章的节略内容需要结合Spring Security一起来看。
权限设计是一件比较抽象的思考活动。有时候一些复杂的权限、角色、组织、用户等内容交织在一起,会让人觉得无从下手。不过只要通过适当的方法来解构,慢慢地抽丝剥茧,就不那么难做了。
例如,笔者比较喜欢用汉堡包
法来做权限设计。所谓汉堡包
法,顾名思义,就是权限系统像汉堡包那样直观、清晰。
Reactor是第四代反应式库,它围绕Reactive Streams标准,在JVM之上构建出一组非阻塞、事件驱动风格的API
。
Spring WebFlux是一款专用于Web服务端的反应式编程框架。WebFlux
在Spring Framework 5.0中引入。从名字中带Flux
就能看出来,它的底层正是通过Reactor来实现Reactive Streams规范的。
Vert.x诞生于2011年,比RxJava还要早,可以说是目前最古老的反应式编程框架之一。当时叫做`node.x,但之后改为了现在的名字,可能是因为和Node.js冲突吧。Vert.x是Eclipse软件基金会顶级Java开源项目之一,截止本书出版前,Vert.x已经发展到了4.5.x版。
正如面向对象的编程语言Java号称一切皆是对象
那样,在反应式编程范式中,一切皆是流
。
大部分碳基生物,时时刻刻都要吸入和呼出氧气,也就是气流;除了呼吸,还需要通过吃东西来补充能量,这是食物流;我们平常看到的风景、人物、短视频之类的,都属于视觉流,还包括语音流等。
流的筛选和切片操作。
// 筛选与切片
List<Integer> list1 = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
list1.stream().filter(i -> i < 3)
.distinct()
.skip(1)
.forEach(System.out::println);
当工程师们准备将写好的源代码变成可执行的程序时,在JVM中会经历这样一个过程。
首先,将源代码文件xxxx.java
编译成.class
字节码,或者是打成jar
包(或war
包)。
然后,通过类加载器ClassLoader
将类的字节码加载到JVM中执行。