提交主题

This commit is contained in:
zhuyijun 2021-08-20 19:23:39 +08:00
parent f01372bf84
commit e0e94f087f
73 changed files with 646 additions and 85 deletions

View File

@ -9,9 +9,9 @@ npm install -g hexo-cli
安装 Hexo 完成后请执行下列命令Hexo 将会在指定文件夹中新建所需要的文件。
```
$ hexo init <folder>
$ cd <folder>
$ npm install
hexo init <folder>
cd <folder>
npm install
```
## 主题安装
@ -30,7 +30,7 @@ theme: butterfly
#### 安装插件
> 如果你沒有 pug 以及 stylus 的渲染器,请下载安裝:
> 如果你沒有 pug 以及 stylus 的渲染器,请下载安裝:
```bash
npm install hexo-renderer-pug hexo-renderer-stylus --save
@ -50,4 +50,6 @@ marked:
postAsset: true
```
#### 使用hexo生成文章时创建会文章
```bash
hexo bangumi -u
```

View File

@ -4,18 +4,18 @@
# Site
title: 逝水无痕の博客
subtitle: ''
description: ''
subtitle: "逝水无痕の博客"
description: ""
keywords: 学习笔记
author: 逝水无痕
language: zh
timezone: ''
language: zh-CN
timezone: ""
# URL
## Set your site url here. For example, if you use GitHub Page, set url as 'https://username.github.io/project'
url: https://hexo.zyjblogs.cn
# permalink: :year/:month/:day/:title/
permalink: posts/:abbrlink/
permalink: posts/:abbrlink.html
permalink_defaults:
pretty_urls:
trailing_index: true # Set to false to remove trailing 'index.html' from permalinks
@ -38,7 +38,7 @@ titlecase: false # Transform title into titlecase
external_link:
enable: true # Open external links in new tab
field: site # Apply to the whole site
exclude: ''
exclude: ""
filename_case: 0
render_drafts: false
post_asset_folder: true
@ -52,23 +52,24 @@ relative_link: false
future: true
highlight:
enable: true
line_number: true
#主题开启了highlight 渲染所以将line_number设置为false
line_number: false
auto_detect: false
tab_replace: ''
tab_replace: ""
wrap: true
hljs: false
prismjs:
enable: false
preprocess: true
line_number: true
tab_replace: ''
tab_replace: ""
# Home page setting
# path: Root path for your blogs index page. (default = '')
# per_page: Posts displayed per page. (0 = disable pagination)
# order_by: Posts order. (Order by date descending by default)
index_generator:
path: ''
path: ""
per_page: 10
order_by: -date
@ -88,7 +89,7 @@ meta_generator: true
date_format: YYYY-MM-DD
time_format: HH:mm:ss
## updated_option supports 'mtime', 'date', 'empty'
updated_option: 'mtime'
updated_option: "mtime"
# Pagination
## Set per_page to 0 to disable pagination
@ -115,9 +116,20 @@ deploy:
branch: branch
bangumi:
enable: true
enable: true
vmid: 17719291
title: '追番列表'
quote: '生命不息,追番不止!'
title: "追番列表"
quote: "生命不息,追番不止!"
show: 1
# loading: 'loading.gif'
# loading: https://butterfly.js.org/img/loading.gif
Plugins:
- hexo-generate-feed
feed:
# Generate both atom and rss2 feeds
type:
- atom
- rss2
path:
- atom.xml
- rss2.xml

23
package-lock.json generated
View File

@ -783,6 +783,15 @@
"hexo-pagination": "1.0.0"
}
},
"hexo-generator-feed": {
"version": "3.0.0",
"resolved": "https://registry.npm.taobao.org/hexo-generator-feed/download/hexo-generator-feed-3.0.0.tgz",
"integrity": "sha1-QSbvXjCCZMQlmfsO/a+I7RH6WZ4=",
"requires": {
"hexo-util": "^2.1.0",
"nunjucks": "^3.0.0"
}
},
"hexo-generator-index": {
"version": "2.0.0",
"resolved": "https://registry.npm.taobao.org/hexo-generator-index/download/hexo-generator-index-2.0.0.tgz",
@ -792,6 +801,15 @@
"timsort": "^0.3.0"
}
},
"hexo-generator-search": {
"version": "2.4.3",
"resolved": "https://registry.nlark.com/hexo-generator-search/download/hexo-generator-search-2.4.3.tgz",
"integrity": "sha1-xPNci4QpNVYS3RzfWhjeNWgWb5k=",
"requires": {
"nunjucks": "^3.0.1",
"utils-merge": "^1.0.0"
}
},
"hexo-generator-tag": {
"version": "1.0.0",
"resolved": "https://registry.npm.taobao.org/hexo-generator-tag/download/hexo-generator-tag-1.0.0.tgz",
@ -898,6 +916,11 @@
"strip-indent": "^3.0.0"
}
},
"hexo-wordcount": {
"version": "6.0.1",
"resolved": "https://registry.nlark.com/hexo-wordcount/download/hexo-wordcount-6.0.1.tgz",
"integrity": "sha1-WmDvydPI5CGVby/WaDypSop5UmQ="
},
"highlight.js": {
"version": "10.7.3",
"resolved": "https://registry.nlark.com/highlight.js/download/highlight.js-10.7.3.tgz",

View File

@ -20,7 +20,9 @@
"hexo-generator-archive": "^1.0.0",
"hexo-generator-calendar": "git://github.com/howiefh/hexo-generator-calendar.git",
"hexo-generator-category": "^1.0.0",
"hexo-generator-feed": "^3.0.0",
"hexo-generator-index": "^2.0.0",
"hexo-generator-search": "^2.4.3",
"hexo-generator-tag": "^1.0.0",
"hexo-helper-qrcode": "^1.0.2",
"hexo-renderer-ejs": "^1.0.0",
@ -29,6 +31,7 @@
"hexo-renderer-stylus": "^2.0.1",
"hexo-server": "^2.0.0",
"hexo-theme-landscape": "^0.0.3",
"hexo-wordcount": "^6.0.1",
"install": "^0.13.0"
}
}

File diff suppressed because one or more lines are too long

19
source/_data/link.yml Normal file
View File

@ -0,0 +1,19 @@
- class_name: 友情链接
class_desc: 那些人,那些事
link_list:
- name: Hexo
link: https://hexo.io/zh-tw/
avatar: https://d33wubrfki0l68.cloudfront.net/6657ba50e702d84afb32fe846bed54fba1a77add/827ae/logo.svg
descr: hexo框架
- class_name: 博客
class_desc: 值得推荐的博客
link_list:
- name: 超逸の技术博客
link: https://yangchaoyi.vip/
avatar: https://cdn.jsdelivr.net/gh/Chocolate1999/cdn/img/avatar.png
descr: 不是只会写业务代码の前端攻城狮
- name: Sakura
link: https://sakura.2heng.xin
avatar: https://sakura.2heng.xin/wp-content/uploads/2018/06/mashiro-logo.png
descr: Just Another WordPress Website

View File

@ -0,0 +1,162 @@
---
title: C++书单
date: 2021-08-09
tag: [c,c++]
categories: book
abbrlink: books/c/1
---
# C++书单
- 《C++ Primer Plus》
- 看来几章,但是对于对我来讲,太过基础了,没有什么编程知识的人适合看这个
- 不太可能继续看
- 《深入实践C++模板编程》
- 模板元编程的入门书籍,推荐
- 正在看,我想我会看它第二遍
- 《深入理解C++11》
- 推荐:⭐⭐⭐⭐
- 当前进度:正在看
- 《C++语言的设计和演化》
- 推荐:
- 评价:
- 当前进度:
- 《C++程序设计语言》
- 推荐:⭐⭐⭐⭐⭐
- 评价:
- C++之父写的,看一遍是绝对不够的!!!!!!
- 这绝对不是什么入门书籍!!!有一定基础的人再来看效果可能更好
- 当前进度第16、17章看完了。 暂停
- 《深入探索C++对象模型》
- 推荐:⭐⭐⭐⭐⭐
- 评价:这书真的写的很好,虽然中文翻译不怎么样,如果不是内容太好,我真的撑不下去,会看第二遍
- 当前进度:看完了
- 《Effective C++ 》
- 推荐:❤️❤️❤️❤️❤️
- 评价:
- 信息密度很高,推荐。
- 这是我看过的写的最好的技术书籍之一
- 第6章写的实在太好了已买书收藏。
- 会看第二遍
- 当前进度:看完了,名不虚传, 我觉得是写C++必读的书籍,就算你不打算全部看完,至少也要看完第六章
- 《More Effective C++ 》
- 推荐:⭐⭐⭐
- 评价:
- 感觉我的时间被浪费了
- 这跟《Effective C++ 》真的是一个作者吗,质量相差太大了,我很失望。
- 这是我近期读过的技术书中最难看的一本。准确评分应该是三星半。
- 当前进度:看完了大部分【近期不打算再看了,冷藏】
- 《C++ Boost程序库完全开发指南》
- 推荐:⭐⭐⭐⭐⭐
- 评价:
- 豆瓣评分居然这么多差评,至于吗,(豆瓣)对国产作者也苛刻了吧,为此加一星。
- 当然学习boost最好的资料是官方文档但是谁让我有这本📕呢我一定会看完它的
- 当前进度:正在看(暂停)
- 《Effective STL》
- 当前进度看到第3节暂停
- 《Exceptional C++ 》
- 《STL源码剖析》
------
- 2021/5.20: C++语法特性暂停,我觉得我已经学的差不多了,需要一点实践,实践完了之后再回头看。接下来打算看网络编程的书籍
------
- 《HTTP权威指南》
- 推荐:💚💚💚
- 评价对HTTP协议感兴趣的可以看看还是挺有用的
- 当前进度:走马观花的看完了,还是挺有用的
- 《Linux-UNIX系统编程手册》
- 推荐:❤️❤️❤️❤️💚
- 评价:孤篇横绝,竟为大家
- 当前进度看到第58章暂停
- 《TCP-IP高效编程改善网络程序的44个技巧》
- 推荐:💚💚💚💚
- 评价谁翻译的译者语文不好吗还不如机器翻译呢内容ok翻译烂
- 当前进度:正在看
- 《TCP/IP详解卷二》
- 4.4BSD-Lite源码的下载地址 `http://ftp.icm.edu.pl/packages/4.4BSD-Lite/ https://pub.allbsd.org/bsd-sources/`
- 《用TCP_IP进行网际互联设计、实现与内核 (卷2)》
- 推荐:
- 评价:
- 信息密度很高,读来有种原来如此的感觉,将买书收藏,常看常新
- 被安利了操作系统课程以及对Xinu的源码感兴趣了
- 感觉网友说的“比TCP/IP详解”更好是有道理的
- 这书的源码网上没有找到。
- 当前进度:正在看
- 《用TCP_IP进行网际互联客户-服务器编程与应用Linux版 (卷3)》
- 推荐:❤️❤️❤️💚💚
- 评价:
- 这书我想买下来收藏,适合有一定基础的人看
- 第1到17章质量很高后面的就比较拉胯了
- 当前进度看到第26章暂停
- 《TCP/IP详解卷1协议》
- 推荐:
- 评价:
- 当前进度:
- 正在看(2021/06/07)
- 暂停,因为我觉得它不说人话(2021/06/08)
- 《TCP/IP网络编程》
- 推荐:
- 评价:
- 《Unix/Linux编程实践教程》
- 推荐:
- 评价:
- 当前进度:
- 《一本书读懂TCP_IP》
- 推荐:🌒
- 评价: 不推荐,为什么这样的书也能出版
- 当前进度: 已看完
------
- Linux高性能服务器编程
- Linux多线程服务器端编程选看
- UNIX 环境高级编程
- UNIX网络编程卷1必看五星推荐
零.手册类:
- 《C++程序设计语言(The C++ Programming Language)》
- 《C++标准程序库(C++ Standard Library Tutorial and Reference) 》
- 《The C++ IO Streams and Locales》
- 《The C++ Standard (INCITS/ISO/IEC 14882-2011)》
- 《Overview of the New C++ (C++11/14) 》
- 《The Standard C Library》
一.初级入门系列:
- 《C++ Primer》
- 《Accelerated C++》
- 《C++编程思想Thinking in C++) 》
- 《C++程序设计原理与实践Programming: Principles and Practice Using C++ )》
- 《C++初学者指南》
- 《Visual.C++.2008入门经典》
- 《面向对象程序设计—C++语言描述》
- 《数据结构(C++语言版)第三版_邓俊辉》
二.实用系列:
- 《深入浅出设计模式》
- 《设计模式:可复用面向对象软件的基础》
- 《HeadFirst设计模式》
- 《大话设计模式》
三.中级进阶系列:
- 《C++ templates》
- 《More Exceptional C++》
- 《Exceptional C++ Style》
- 《C++编程规范(C++ Coding Standards) 》
- 《C++ 模板完全指南(C++ Templates: The Complete Guide)》
- 《Beyond the C++ Standard Library(Boost)》
- 《C和C++安全编码》
四.高级成神系列:
- 《C++设计新思维-泛型编程与设计模式之应用(Modern C++ Design ) 》
- 《C++模板元编程(C++ Template Metaprogramming)》
- 《C++ Concurrency In Action》
- 《Advanced c++ Programming Styles and Idioms 》
- 《Real-Time C++ Efficient Object-Oriented and Template Microcontroller Programming》
- 《Advanced_Metaprogramming_in_Classic_C 》

View File

@ -1,6 +1,6 @@
---
title: 第一次使用hexo
date: 2021-08-06
abbrlink: helloword
abbrlink: helloword/1
---
# 第一次使用仅为测试
# 第一次使用仅为测试

View File

@ -0,0 +1,329 @@
---
title: BIO,NIO,AIO 总结
date: 2021-08-13
tag: [net,java]
categories: [net,java]
abbrlink: java/base/net/1
---
# BIO,NIO,AIO 总结
Java 中的 BIO、NIO和 AIO 理解为是 Java 语言对操作系统的各种 IO 模型的封装。程序员在使用这些 API 的时候不需要关心操作系统层面的知识也不需要根据不同操作系统编写不同的代码。只需要使用Java的API就可以了。
在讲 BIO,NIO,AIO 之前先来回顾一下这样几个概念:同步与异步,阻塞与非阻塞。
关于同步和异步的概念解读困扰着很多程序员,大部分的解读都会带有自己的一点偏见。参考了 [Stackoverflow](https://stackoverflow.com/questions/748175/asynchronous-vs-synchronous-execution-what-does-it-really-mean)相关问题后对原有答案进行了进一步完善:
> When you execute something synchronously, you wait for it to finish before moving on to another task. When you execute something asynchronously, you can move on to another task before it finishes.
>
> 当你同步执行某项任务时,你需要等待其完成才能继续执行其他任务。当你异步执行某些操作时,你可以在完成另一个任务之前继续进行。
- **同步** :两个同步任务相互依赖,并且一个任务必须以依赖于另一任务的某种方式执行。 比如在`A->B`事件模型中,你需要先完成 A 才能执行B。 再换句话说,同步调用中被调用者未处理完请求之前,调用不返回,调用者会一直等待结果的返回。
- **异步** 两个异步的任务完全独立的,一方的执行不需要等待另外一方的执行。再换句话说,异步调用种一调用就返回结果不需要等待结果返回,当结果返回的时候通过回调函数或者其他方式拿着结果再做相关事情,
**阻塞和非阻塞**
- **阻塞:** 阻塞就是发起一个请求,调用者一直等待请求结果返回,也就是当前线程会被挂起,无法从事其他任务,只有当条件就绪才能继续。
- **非阻塞:** 非阻塞就是发起一个请求,调用者不用一直等着结果返回,可以先去干其他事情。
**如何区分 “同步/异步 ”和 “阻塞/非阻塞” 呢?**
同步/异步是从行为角度描述事物的,而阻塞和非阻塞描述的当前事物的状态(等待调用结果时的状态)。
## 1. BIO (Blocking I/O)
同步阻塞I/O模式数据的读取写入必须阻塞在一个线程内等待其完成。
### 1.1 传统 BIO
BIO通信一请求一应答模型图如下(图源网络,原出处不明)
![传统BIO通信模型图](./img/2.png)
采用 **BIO 通信模型** 的服务端,通常由一个独立的 Acceptor 线程负责监听客户端的连接。我们一般通过在`while(true)` 循环中服务端会调用 `accept()` 方法等待接收客户端的连接的方式监听请求,请求一旦接收到一个连接请求,就可以建立通信套接字在这个通信套接字上进行读写操作,此时不能再接收其他客户端连接请求,只能等待同当前连接的客户端的操作执行完成, 不过可以通过多线程来支持多个客户端的连接,如上图所示。
如果要让 **BIO 通信模型** 能够同时处理多个客户端请求,就必须使用多线程(主要原因是`socket.accept()`、`socket.read()`、`socket.write()` 涉及的三个主要函数都是同步阻塞的),也就是说它在接收到客户端连接请求之后为每个客户端创建一个新的线程进行链路处理,处理完成之后,通过输出流返回应答给客户端,线程销毁。这就是典型的 **一请求一应答通信模型** 。我们可以设想一下如果这个连接不做任何事情的话就会造成不必要的线程开销,不过可以通过 **线程池机制** 改善,线程池还可以让线程的创建和回收成本相对较低。使用`FixedThreadPool` 可以有效的控制了线程的最大数量保证了系统有限的资源的控制实现了N(客户端请求数量):M(处理客户端请求的线程数量)的伪异步I/O模型N 可以远远大于 M下面一节"伪异步 BIO"中会详细介绍到。
**我们再设想一下当客户端并发访问量增加后这种模型会出现什么问题?**
在 Java 虚拟机中,线程是宝贵的资源,线程的创建和销毁成本很高,除此之外,线程的切换成本也是很高的。尤其在 Linux 这样的操作系统中,线程本质上就是一个进程,创建和销毁线程都是重量级的系统函数。如果并发访问量增加会导致线程数急剧膨胀可能会导致线程堆栈溢出、创建新线程失败等问题,最终导致进程宕机或者僵死,不能对外提供服务。
### 1.2 伪异步 IO
为了解决同步阻塞I/O面临的一个链路需要一个线程处理的问题后来有人对它的线程模型进行了优化一一一后端通过一个线程池来处理多个客户端的请求接入形成客户端个数M线程池最大线程数N的比例关系其中M可以远远大于N.通过线程池可以灵活地调配线程资源,设置线程的最大值,防止由于海量并发接入导致线程耗尽。
伪异步IO模型图(图源网络,原出处不明)
![伪异步IO模型图](http://study.zyjblogs.cn/3.png)
采用线程池和任务队列可以实现一种叫做伪异步的 I/O 通信框架,它的模型图如上图所示。当有新的客户端接入时,将客户端的 Socket 封装成一个Task该任务实现java.lang.Runnable接口投递到后端的线程池中进行处理JDK 的线程池维护一个消息队列和 N 个活跃线程,对消息队列中的任务进行处理。由于线程池可以设置消息队列的大小和最大线程数,因此,它的资源占用是可控的,无论多少个客户端并发访问,都不会导致资源的耗尽和宕机。
伪异步I/O通信框架采用了线程池实现因此避免了为每个请求都创建一个独立线程造成的线程资源耗尽问题。不过因为它的底层仍然是同步阻塞的BIO模型因此无法从根本上解决问题。
### 1.3 代码示例
下面代码中演示了BIO通信一请求一应答模型。我们会在客户端创建多个线程依次连接服务端并向其发送"当前时间+:hello world",服务端会为每个客户端线程创建一个线程来处理。代码示例出自闪电侠的博客,原地址如下:
[https://www.jianshu.com/p/a4e03835921a](https://www.jianshu.com/p/a4e03835921a)
**客户端**
```java
/**
*
* @author 闪电侠
* @date 2018年10月14日
* @Description:客户端
*/
public class IOClient {
public static void main(String[] args) {
// TODO 创建多个线程,模拟多个客户端连接服务端
new Thread(() -> {
try {
Socket socket = new Socket("127.0.0.1", 3333);
while (true) {
try {
socket.getOutputStream().write((new Date() + ": hello world").getBytes());
Thread.sleep(2000);
} catch (Exception e) {
}
}
} catch (IOException e) {
}
}).start();
}
}
```
**服务端**
```java
/**
* @author 闪电侠
* @date 2018年10月14日
* @Description: 服务端
*/
public class IOServer {
public static void main(String[] args) throws IOException {
// TODO 服务端处理客户端连接请求
ServerSocket serverSocket = new ServerSocket(3333);
// 接收到客户端连接请求之后为每个客户端创建一个新的线程进行链路处理
new Thread(() -> {
while (true) {
try {
// 阻塞方法获取新的连接
Socket socket = serverSocket.accept();
// 每一个新的连接都创建一个线程,负责读取数据
new Thread(() -> {
try {
int len;
byte[] data = new byte[1024];
InputStream inputStream = socket.getInputStream();
// 按字节流方式读取数据
while ((len = inputStream.read(data)) != -1) {
System.out.println(new String(data, 0, len));
}
} catch (IOException e) {
}
}).start();
} catch (IOException e) {
}
}
}).start();
}
}
```
### 1.4 总结
在活动连接数不是特别高小于单机1000的情况下这种模型是比较不错的可以让每一个连接专注于自己的 I/O 并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的 I/O 处理模型来应对更高的并发量。
## 2. NIO (New I/O)
### 2.1 NIO 简介
NIO是一种同步非阻塞的I/O模型在Java 1.4 中引入了 NIO 框架,对应 java.nio 包,提供了 Channel , SelectorBuffer等抽象。
NIO中的N可以理解为Non-blocking不单纯是New。它支持面向缓冲的基于通道的I/O操作方法。 NIO提供了与传统BIO模型中的 `Socket``ServerSocket` 相对应的 `SocketChannel``ServerSocketChannel` 两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样比较简单但是性能和可靠性都不好非阻塞模式正好与之相反。对于低负载、低并发的应用程序可以使用同步阻塞I/O来提升开发速率和更好的维护性对于高负载、高并发的网络应用应使用 NIO 的非阻塞模式来开发。
### 2.2 NIO的特性/NIO与IO区别
如果是在面试中回答这个问题,我觉得首先肯定要从 NIO 流是非阻塞 IO 而 IO 流是阻塞 IO 说起。然后,可以从 NIO 的3个核心组件/特性为 NIO 带来的一些改进来分析。如果,你把这些都回答上了我觉得你对于 NIO 就有了更为深入一点的认识,面试官问到你这个问题,你也能很轻松的回答上来了。
#### 1)Non-blocking IO非阻塞IO
**IO流是阻塞的NIO流是不阻塞的。**
Java NIO使我们可以进行非阻塞IO操作。比如说单线程中从通道读取数据到buffer同时可以继续做别的事情当数据读取到buffer中后线程再继续处理数据。写数据也是一样的。另外非阻塞写也是如此。一个线程请求写入一些数据到某通道但不需要等待它完全写入这个线程同时可以去做别的事情。
Java IO的各种流是阻塞的。这意味着当一个线程调用 `read()``write()` 时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了
#### 2)Buffer(缓冲区)
**IO 面向流(Stream oriented),而 NIO 面向缓冲区(Buffer oriented)。**
Buffer是一个对象它包含一些要写入或者要读出的数据。在NIO类库中加入Buffer对象体现了新库与原I/O的一个重要区别。在面向流的I/O中·可以将数据直接写入或者将数据直接读到 Stream 对象中。虽然 Stream 中也有 Buffer 开头的扩展类,但只是流的包装类,还是从流读到缓冲区,而 NIO 却是直接读到 Buffer 中进行操作。
在NIO厍中所有数据都是用缓冲区处理的。在读取数据时它是直接读到缓冲区中的; 在写入数据时写入到缓冲区中。任何时候访问NIO中的数据都是通过缓冲区进行操作。
最常用的缓冲区是 ByteBuffer,一个 ByteBuffer 提供了一组功能用于操作 byte 数组。除了ByteBuffer,还有其他的一些缓冲区事实上每一种Java基本类型除了Boolean类型都对应有一种缓冲区。
#### 3)Channel (通道)
NIO 通过Channel通道 进行读写。
通道是双向的可读也可写而流的读写是单向的。无论读写通道只能和Buffer交互。因为 Buffer通道可以异步地读写。
#### 4)Selector (选择器)
NIO有选择器而IO没有。
选择器用于使用单个线程处理多个通道。因此,它需要较少的线程来处理这些通道。线程之间的切换对于操作系统来说是昂贵的。 因此,为了提高系统效率选择器是有用的。
![一个单线程中Selector维护3个Channel的示意图](./img/Slector.png)
### 2.3 NIO 读数据和写数据方式
通常来说NIO中的所有IO都是从 Channel通道 开始的。
- 从通道进行数据读取 :创建一个缓冲区,然后请求通道读取数据。
- 从通道进行数据写入 :创建一个缓冲区,填充数据,并要求通道写入数据。
数据读取和写入操作图示:
![NIO读写数据的方式](./img/NIO读写数据的方式.png)
### 2.4 NIO核心组件简单介绍
NIO 包含下面几个核心的组件:
- Channel(通道)
- Buffer(缓冲区)
- Selector(选择器)
整个NIO体系包含的类远远不止这三个只能说这三个是NIO体系的“核心API”。我们上面已经对这三个概念进行了基本的阐述这里就不多做解释了。
### 2.5 代码示例
代码示例出自闪电侠的博客,原地址如下:
[https://www.jianshu.com/p/a4e03835921a](https://www.jianshu.com/p/a4e03835921a)
客户端 IOClient.java 的代码不变,我们对服务端使用 NIO 进行改造。以下代码较多而且逻辑比较复杂,大家看看就好。
```java
/**
*
* @author 闪电侠
* @date 2019年2月21日
* @Description: NIO 改造后的服务端
*/
public class NIOServer {
public static void main(String[] args) throws IOException {
// 1. serverSelector负责轮询是否有新的连接服务端监测到新的连接之后不再创建一个新的线程
// 而是直接将新连接绑定到clientSelector上这样就不用 IO 模型中 1w 个 while 循环在死等
Selector serverSelector = Selector.open();
// 2. clientSelector负责轮询连接是否有数据可读
Selector clientSelector = Selector.open();
new Thread(() -> {
try {
// 对应IO编程中服务端启动
ServerSocketChannel listenerChannel = ServerSocketChannel.open();
listenerChannel.socket().bind(new InetSocketAddress(3333));
listenerChannel.configureBlocking(false);
listenerChannel.register(serverSelector, SelectionKey.OP_ACCEPT);
while (true) {
// 监测是否有新的连接这里的1指的是阻塞的时间为 1ms
if (serverSelector.select(1) > 0) {
Set<SelectionKey> set = serverSelector.selectedKeys();
Iterator<SelectionKey> keyIterator = set.iterator();
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
if (key.isAcceptable()) {
try {
// (1) 每来一个新连接不需要创建一个线程而是直接注册到clientSelector
SocketChannel clientChannel = ((ServerSocketChannel) key.channel()).accept();
clientChannel.configureBlocking(false);
clientChannel.register(clientSelector, SelectionKey.OP_READ);
} finally {
keyIterator.remove();
}
}
}
}
}
} catch (IOException ignored) {
}
}).start();
new Thread(() -> {
try {
while (true) {
// (2) 批量轮询是否有哪些连接有数据可读这里的1指的是阻塞的时间为 1ms
if (clientSelector.select(1) > 0) {
Set<SelectionKey> set = clientSelector.selectedKeys();
Iterator<SelectionKey> keyIterator = set.iterator();
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
if (key.isReadable()) {
try {
SocketChannel clientChannel = (SocketChannel) key.channel();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
// (3) 面向 Buffer
clientChannel.read(byteBuffer);
byteBuffer.flip();
System.out.println(
Charset.defaultCharset().newDecoder().decode(byteBuffer).toString());
} finally {
keyIterator.remove();
key.interestOps(SelectionKey.OP_READ);
}
}
}
}
}
} catch (IOException ignored) {
}
}).start();
}
}
```
为什么大家都不愿意用 JDK 原生 NIO 进行开发呢?从上面的代码中大家都可以看出来,是真的难用!除了编程复杂、编程模型难之外,它还有以下让人诟病的问题:
- JDK 的 NIO 底层由 epoll 实现,该实现饱受诟病的空轮询 bug 会导致 cpu 飙升 100%
- 项目庞大之后,自行实现的 NIO 很容易出现各类 bug维护成本较高上面这一坨代码我都不能保证没有 bug
Netty 的出现很大程度上改善了 JDK 原生 NIO 所存在的一些让人难以忍受的问题。
### 3. AIO (Asynchronous I/O)
AIO 也就是 NIO 2。在 Java 7 中引入了 NIO 的改进版 NIO 2,它是异步非阻塞的IO模型。异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。
AIO 是异步IO的缩写虽然 NIO 在网络操作中,提供了非阻塞的方法,但是 NIO 的 IO 行为还是同步的。对于 NIO 来说,我们的业务线程是在 IO 操作准备好时,得到通知,接着就由这个线程自行进行 IO 操作IO操作本身是同步的。除了 AIO 其他的 IO 类型都是同步的这一点可以从底层IO线程模型解释推荐一篇文章[《漫话如何给女朋友解释什么是Linux的五种IO模型》](https://mp.weixin.qq.com/s?__biz=Mzg3MjA4MTExMw==&mid=2247484746&amp;idx=1&amp;sn=c0a7f9129d780786cabfcac0a8aa6bb7&source=41#wechat_redirect)
查阅网上相关资料,我发现就目前来说 AIO 的应用还不是很广泛Netty 之前也尝试使用过 AIO不过又放弃了。
## 参考
- 《Netty 权威指南》第二版
- <https://zhuanlan.zhihu.com/p/23488863> (美团技术团队)

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

View File

@ -1,8 +1,9 @@
---
title: 微服务框架
date: 2021-08-07
tag: springcloud
abbrlink: springcloud
tag: [springcloud,java]
categories: java
abbrlink: java/springcloud/1
---
# 微服务框架
@ -13,7 +14,7 @@ abbrlink: springcloud
### 1.1 微服务架构
> https://martinfowler.com/articles/microservices.html
> <https://martinfowler.com/articles/microservices.html>
>
> 微服务架构提出者:马丁福勒
@ -25,9 +26,9 @@ abbrlink: springcloud
>
> SpringCloud中的大多数技术都是基于Netflix公司的技术进行第二次开发。
>
> 1、SpringCloud的中文社区网站http://springcloud.cn/
> 1、SpringCloud的中文社区网站<http://springcloud.cn/>
>
> 2、SpringCloud的中文网 http://springcloud.cc/
> 2、SpringCloud的中文网 <http://springcloud.cc/>
>
> 八个技术点:
>
@ -127,8 +128,6 @@ eureka:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
```
#### 2.2.2 创建EurekaClient
> 1、创建Maven工程修改为SpringBoot
@ -332,17 +331,17 @@ eureka:
```yml
eureka:
client:
#每隔多久去更新一下本地的注册表缓存信息
#每隔多久去更新一下本地的注册表缓存信息
registry-fetch-interval-seconds: 30
```
> 5、Eureka的自我保护机制统计15分钟内如果一个服务的心跳发送比例低于85%EurekaServer就会开启自我保护机制
>
> 1、不会从EurekaServer中去移除长时间没有收到心跳的服务
> 1、不会从EurekaServer中去移除长时间没有收到心跳的服务
>
> 2、EurekaServer还是可以正常提供服务的
> 2、EurekaServer还是可以正常提供服务的
>
> 3、网络稳定时EurekaServer才会开始将自己的信息被其他节点同步过去
> 3、网络稳定时EurekaServer才会开始将自己的信息被其他节点同步过去
![image-20201111132523595](images/image-20201111132523595.png)
@ -350,8 +349,8 @@ eureka:
eureka:
# Eureka保护机制配置
server:
#true 开启 false关闭
enable-self-preservation: true
#true 开启 false关闭
enable-self-preservation: true
```
> 6、CAP定理C-一致性 A-可用性 P-分区容错性这三个特新在分布是环境下只能满足2个而且分区容错性在分布式环境下时必须要满足的。只能在AC之间进行权衡。
@ -414,10 +413,10 @@ public String customer() {
> 1、负载均衡策略
>
> 1. RandomRule随机策略
> 2. RoundRobbinRule轮询策略
> 3. WeightedResponseTimeRule默认会采用轮询的策略后续会根据服务的响应时间自动给你分配权重
> 4. BestAvailableRule根据被调用方并发数最小的去分配
> 1. RandomRule随机策略
> 2. RoundRobbinRule轮询策略
> 3. WeightedResponseTimeRule默认会采用轮询的策略后续会根据服务的响应时间自动给你分配权重
> 4. BestAvailableRule根据被调用方并发数最小的去分配
> 2、采用注解的形式
@ -487,7 +486,7 @@ public interface SearchClient {
private SearchClient searchClient;
@GetMapping("/customer")
public String customer() {
public String customer() {
String result = searchClient.search();
return result;
}
@ -497,10 +496,10 @@ public String customer() {
> 1、注意事项
>
> 1. 如果你传递的参数比较复杂时默认会采用POST的请求方式。
> 2. 传递单个参数时,推荐使用@PathVariable如果传递的单个参数比较多这里也可以采用@RequestParam不要省略value属性
> 3. 传递对象信息时统一采用json的方式添加@RequestBody
> 4. Client接口必须采用@RequestMapping
> 1. 如果你传递的参数比较复杂时默认会采用POST的请求方式。
> 2. 传递单个参数时,推荐使用@PathVariable如果传递的单个参数比较多这里也可以采用@RequestParam不要省略value属性
> 3. 传递对象信息时统一采用json的方式添加@RequestBody
> 4. Client接口必须采用@RequestMapping
> 2、在Search模块下准备三个接口
@ -515,7 +514,7 @@ public Customer getcustomer(@RequestParam Integer id, @RequestParam String name)
return new Customer(id, name, 23);
}
@PostMapping("save")
@PostMapping("save")
public Customer save(@RequestBody Customer customer) {
return customer;
}
@ -697,15 +696,15 @@ public Customer findByIdFallBack(Integer id) {
> 1、Hystrix的线程池的配置(具体的配置属性需要去查看HystrixCommandProperties类) [wiki](https://github.com/Netflix/Hystrix/wiki/Configuration)
>
> 1. 线程隔离策略name = `hystrix.command.default.execution.isolation.strategy`,value=`THREAD`,`SEMAPHORE `
> 2. 指定超时时间针对线程池name= `hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds` ,value =`1000`
> 3. 是否开启超时时间配置name=`hystrix.command.default.execution.timeout.enabled`,value=`true`
> 4. 超时之后是否中断线程name=`hystrix.command.default.execution.isolation.thread.interruptOnTimeout`,value=`true`
> 5. 取消任务之后是否中断线程name=`hystrix.command.default.execution.isolation.thread.interruptOnCancel`,value=false
> 1. 线程隔离策略name = `hystrix.command.default.execution.isolation.strategy`,value=`THREAD`,`SEMAPHORE`
> 2. 指定超时时间针对线程池name= `hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds` ,value =`1000`
> 3. 是否开启超时时间配置name=`hystrix.command.default.execution.timeout.enabled`,value=`true`
> 4. 超时之后是否中断线程name=`hystrix.command.default.execution.isolation.thread.interruptOnTimeout`,value=`true`
> 5. 取消任务之后是否中断线程name=`hystrix.command.default.execution.isolation.thread.interruptOnCancel`,value=false
> 2、信号量配置信息
>
> 1. 线程隔离策略name = `hystrix.command.default.execution.isolation.strategy`,value=`THREAD`,`SEMAPHORE `
> 1. 线程隔离策略name = `hystrix.command.default.execution.isolation.strategy`,value=`THREAD`,`SEMAPHORE`
> 2. 指定信号量的最大并发请求数name=`hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests`,value=`10`
### 5.4 断路器
@ -763,7 +762,7 @@ hystrix:
> 6、测试
直接访问: http://host:port/hystrix.stream
直接访问: <http://host:port/hystrix.stream>
![1605103421256](images/1605103421256.png)
@ -775,12 +774,12 @@ hystrix:
> 断路器的属性(10秒之内)
>
> 1. 断路器的开关name=` hystrix.command.default.circuitBreaker.enabled `,value=`true`
> 2. 失败阈值的总请求数name=` hystrix.command.default.circuitBreaker.requestVolumeThreshold `,value=`20`
> 3. 请求总数失败率达到%多少时打开断路器name=` hystrix.command.default.circuitBreaker.errorThresholdPercentage `,value=`50`
> 4. 断路器open状态后多少秒是拒绝请求的name=` hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds `value=`5000`
> 5. 强制让服务拒绝请求name=` hystrix.command.default.circuitBreaker.forceOpen `,value=`false`
> 6. 强制让服务接收请求name=` hystrix.command.default.circuitBreaker.forceClosed `,value=`false`
> 1. 断路器的开关name=` hystrix.command.default.circuitBreaker.enabled `,value=`true`
> 2. 失败阈值的总请求数name=` hystrix.command.default.circuitBreaker.requestVolumeThreshold `,value=`20`
> 3. 请求总数失败率达到%多少时打开断路器name=` hystrix.command.default.circuitBreaker.errorThresholdPercentage `,value=`50`
> 4. 断路器open状态后多少秒是拒绝请求的name=` hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds `value=`5000`
> 5. 强制让服务拒绝请求name=` hystrix.command.default.circuitBreaker.forceOpen `,value=`false`
> 6. 强制让服务接收请求name=` hystrix.command.default.circuitBreaker.forceClosed `,value=`false`
> 具体配置方式
@ -834,9 +833,9 @@ public class CustomerService {
> 2、使用请求缓存的注解`@CacheResult` `CacheRemove`
>
> 1. @CacheResult:帮助我们缓存当前方法的返回结果(必须配合@HystrixCommand使用
> 2. @CacheRemove帮助我们清除某一个缓存信息基于commandKey
> 3. @CacheKey:指定那个方法参数作为缓存标识
> 1. @CacheResult:帮助我们缓存当前方法的返回结果(必须配合@HystrixCommand使用
> 2. @CacheRemove帮助我们清除某一个缓存信息基于commandKey
> 3. @CacheKey:指定那个方法参数作为缓存标识
> 3、修改Search模块的结果返回值
@ -860,7 +859,7 @@ public class HystrixRequestContextFilter implements Filter {
> 5、修改Controller
```java
@Autowired
@Autowired
private CustomerService customerService;
@GetMapping("/customer/{id}")
@ -884,7 +883,7 @@ private CustomerService customerService;
System.out.println(customerService.findById(id));
System.out.println(customerService.findById(id));
customerService.clearFindById(id);
return searchClient.findById(id);
}
```
@ -962,8 +961,6 @@ spring:
![image-20201112113609523](images/image-20201112113609523.png)
### 6.3 Zuul常用配置信息
#### 6.3.1 Zuul的监控界面
@ -1052,8 +1049,6 @@ spring:
name: CUSTOMER-${version}
```
> 3、修改Zuul的配置
```yml
@ -1074,8 +1069,6 @@ zuul:
}
```
> 5、测试
![image-20201112135410803](images/image-20201112135410803.png)
@ -1095,7 +1088,7 @@ zuul:
```java
@Component
public class ZuulFilterTest extends ZuulFilter {
}
```
@ -1106,7 +1099,7 @@ public class ZuulFilterTest extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
}
```
> 3、指定过滤器的执行顺序
@ -1209,7 +1202,7 @@ public class AuthenticationFilter extends ZuulFilter{
```java
@Component
public class ZuulFallBack implements FallbackProvider {
}
```
@ -1280,7 +1273,7 @@ public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
```java
@Component
public class DynamicRoutingFilter extends ZuulFilter{
}
```
@ -1603,13 +1596,13 @@ spring:
uri: https://gitee.com/zyjblog/config-resp.git
```
> 5、测试(例子:`http://localhost:82/master/customer-xxx.yml ` (master可以省略)
> 5、测试(例子:`http://localhost:82/master/customer-xxx.yml` (master可以省略)
>
> 访问方式如下:
>
> `/{application}/{profile}[/{label}]`
> `/{application}-{profile}.yml`
> `/{label}/{application}-{profile}.yml`
> `/{label}/{application}-{profile}.yml`
>
> `/{application}-{profile}.properties`
> `/{label}/{application}-{profile}.properties`
@ -1729,11 +1722,11 @@ public class CustomerController {
> 4、测试
>
> 1. CONFIG在gitee修改之后自动拉取最新的配置信息。
> 2. 其他模块需要更新的话手动发送一个POST请求http://localhost:10000/actuator/bus-refresh ,不重启项目,即可获取最新的配置信息
> 2. 其他模块需要更新的话手动发送一个POST请求<http://localhost:10000/actuator/bus-refresh> ,不重启项目,即可获取最新的配置信息
#### 9.4.4 内网穿透
> 1、内网穿透官网http://www.ngrok.cc/
> 1、内网穿透官网<http://www.ngrok.cc/>
> 2、注册登录
@ -1879,7 +1872,7 @@ logging:
### 10.3 Zipkin的使用
> 1、搭建Zipkin的web工程 https://zipkin.io/pages/quickstart
> 1、搭建Zipkin的web工程 <https://zipkin.io/pages/quickstart>
>
> 1. docker安装Zipkin
@ -1944,8 +1937,6 @@ spring:
type: rabbit
```
> 3、修改Zipkin信息
```yml
@ -2003,9 +1994,9 @@ services:
docker run --name es1_6.6.0 \
-p 9200:9200 \
-p 9300:9300 \
-e ES_JAVA_OPTS="-Xms256m -Xmx256m" \
-v /d/elasticsearch/config/es1.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /d/elasticsearch/data/es1:/usr/share/elasticsearch/data \
-e ES_JAVA_OPTS="-Xms256m -Xmx256m" \
-v /d/elasticsearch/config/es1.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /d/elasticsearch/data/es1:/usr/share/elasticsearch/data \
-v /d/elasticsearch/logs/es1:/usr/share/elasticsearch/logs \
-d 13aa43015aa1
```
@ -2035,4 +2026,4 @@ docker-compose restart
## 十一、完整SpringCloud架构图
![image-20201113165759501](images/image-20201113165759501.png)
![image-20201113165759501](images/image-20201113165759501.png)

View File

Before

Width:  |  Height:  |  Size: 256 KiB

After

Width:  |  Height:  |  Size: 256 KiB

View File

Before

Width:  |  Height:  |  Size: 111 KiB

After

Width:  |  Height:  |  Size: 111 KiB

View File

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 112 KiB

View File

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 104 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

5
source/about/index.md Normal file
View File

@ -0,0 +1,5 @@
---
title: about
date: 2021-08-10 23:06:26
type: "about"
---

View File

@ -0,0 +1,5 @@
---
title: 分类
date: 2021-08-10 22:56:18
type: "categories"
---

5
source/link/index.md Normal file
View File

@ -0,0 +1,5 @@
---
title: 友链
date: 2021-08-10 22:56:56
type: "link"
---

5
source/tags/index.md Normal file
View File

@ -0,0 +1,5 @@
---
title: tags
date: 2021-08-10 23:07:08
type: "tags"
---