Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
zhihuaiwen committed Jan 25, 2024
1 parent 2ab4883 commit 1ff741c
Show file tree
Hide file tree
Showing 10 changed files with 635 additions and 58 deletions.
10 changes: 6 additions & 4 deletions docs/.vuepress/navbar.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
import {navbar} from "vuepress-theme-hope";
import {others} from "./sidebar/others";

export default navbar([
{text: "Java", icon: "java", link: "/index"},
{text: "数据库", icon: "database", link: "/database/"},
{text: "大数据", icon: "bigdata", link: "/bigdata/"},
{text: "Kubernetes", icon: "Kubernetes", link: "/kubernetes/"},
{text: "个人网站", icon: "personalWebsite.ts", link: "/personalWebsite/"},
{text: "其他", icon: "others", link: "/others/"},
{text: "捐赠", icon: "donate", link: "/donate/"},
{
text: "网站相关",
icon: "about",
children: [
{text: "关于作者", icon: "zuozhe", link: "/about-the-author/"},
{
text: "更新历史",
icon: "history",
link: "/timeline/",
text: "生活",
icon: "life",
link: "/life/",
},
],
},
{text: "捐赠", icon: "donate", link: "/donate/"},
]);
5 changes: 4 additions & 1 deletion docs/.vuepress/sidebar/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ export const database = arraySidebar([
prefix: "elasticsearch/",
icon: "elasticsearch",
collapsible: false,
children: ["【elasticsearch】搜索过程详解"],
children: [
"【elasticsearch】搜索过程详解",
"elasticsearch源码debug.md"
],
},
{
text: "MongoDB",
Expand Down
3 changes: 3 additions & 0 deletions docs/.vuepress/sidebar/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {donate} from "./donate.js";
import {bigdata} from "./bigdata.js";
import {personalWebsite} from "./personalWebsite.js";
import {kubernetes} from "./kubernetes.js";
import {others} from "./others";

export default sidebar({
// 应该把更精确的路径放置在前边
Expand All @@ -17,6 +18,7 @@ export default sidebar({
"/kubernetes/": kubernetes,
"/books/": books,
"/donate/": donate,
"/others/": others,
"/about-the-author/": aboutTheAuthor,
"/high-quality-technical-articles/": highQualityTechnicalArticles,
"/zhuanlan/": [
Expand All @@ -40,6 +42,7 @@ export default sidebar({
"内存屏障",
"基于kubernetes的分布式限流",
"锁",
"在 Spring 6 中使用虚拟线程.md"
],
},
],
Expand Down
14 changes: 0 additions & 14 deletions docs/.vuepress/sidebar/mysql.ts

This file was deleted.

39 changes: 0 additions & 39 deletions docs/.vuepress/sidebar/open-source-project.ts

This file was deleted.

12 changes: 12 additions & 0 deletions docs/.vuepress/sidebar/others.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {arraySidebar} from "vuepress-theme-hope";

export const others = arraySidebar([
{
text: "其他",
collapsible: false,
children: [
"tesla.md",
"chatgpt.md"
],
},
]);
32 changes: 32 additions & 0 deletions docs/database/elasticsearch/elasticsearch源码debug.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# 【elasticsearch】源码debug

# 一、下载源代码
直接用idea下载代码https://github.com/elastic/elasticsearch.git
![image](https://img2022.cnblogs.com/blog/755525/202201/755525-20220124160719006-851383635.png)



切换到特定版本的分支:比如7.17,之后idea会自己加上Run/Debug Elasitcsearch的,配置可以不用改,默认就好
![image](https://img2022.cnblogs.com/blog/755525/202201/755525-20220124160709513-361605195.png)





# 二、修改设置(可选)
为了方便, 在 gradle/run.gradle 中关闭 Auth 认证:

setting 'xpack.security.enabled', 'false'

或者使用其中的用户名密码:

user username: 'elastic-admin', password: 'elastic-password', role: 'superuser'



# 三、启动
先启动上面的 remote debug, 然后用 gradlew 启动项目:

./gradlew :run --debug-jvm
打开浏览器http://localhost:9200即可看到es相关信息了
![image](https://img2022.cnblogs.com/blog/755525/202201/755525-20220124160657219-1269826381.png)
134 changes: 134 additions & 0 deletions docs/java/在 Spring 6 中使用虚拟线程.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# 在 Spring 6 中使用虚拟线程

## 一、简介

在这个简短的教程中,我们将了解如何在 Spring Boot 应用程序中利用虚拟线程的强大功能。

虚拟线程是Java 19 的[预览功能](https://openjdk.org/jeps/425),这意味着它们将在未来 12 个月内包含在官方 JDK 版本中。[Spring 6 版本](https://spring.io/blog/2022/10/11/embracing-virtual-threads)最初由 Project Loom 引入,为开发人员提供了开始尝试这一出色功能的选项。

首先,我们将看到“平台线程”和“虚拟线程”之间的主要区别。接下来,我们将使用虚拟线程从头开始构建一个 Spring-Boot 应用程序。最后,我们将创建一个小型测试套件,以查看简单 Web 应用程序吞吐量的最终改进。

## 二、 虚拟线程与平台线程

主要区别在于[虚拟线程](https://www.baeldung.com/java-virtual-thread-vs-thread)在其操作周期中不依赖于操作系统线程:它们与硬件解耦,因此有了“虚拟”这个词。这种解耦是由 JVM 提供的抽象层实现的。

对于本教程来说,必须了解虚拟线程的运行成本远低于平台线程。它们消耗的分配内存量要少得多。这就是为什么可以创建数百万个虚拟线程而不会出现内存不足问题,而不是使用标准平台(或内核)线程创建几百个虚拟线程。

从理论上讲,这赋予了开发人员一种超能力:无需依赖异步代码即可管理高度可扩展的应用程序。

## 三、在Spring 6中使用虚拟线程

从 Spring Framework 6(和 Spring Boot 3)开始,虚拟线程功能正式公开,但虚拟线程是Java 19 的[预览功能。](https://www.baeldung.com/java-preview-features)这意味着我们需要告诉 JVM 我们要在应用程序中启用它们。由于我们使用 Maven 来构建应用程序,因此我们希望确保在 pom.xml 中包含以下*代码*

```java
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>19</source>
<target>19</target>
<compilerArgs>
--enable-preview
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
```

从 Java 的角度来看,要使用 Apache Tomcat 和虚拟线程,我们需要一个带有几个 bean 的简单配置类:

```java
@EnableAsync
@Configuration
@ConditionalOnProperty(
value = "spring.thread-executor",
havingValue = "virtual"
)
public class ThreadConfig {
@Bean
public AsyncTaskExecutor applicationTaskExecutor() {
return new TaskExecutorAdapter(Executors.newVirtualThreadPerTaskExecutor());
}

@Bean
public TomcatProtocolHandlerCustomizer<?> protocolHandlerVirtualThreadExecutorCustomizer() {
return protocolHandler -> {
protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
};
}
}
```

第一个 Spring Bean *ApplicationTaskExecutor*将取代标准的*[ApplicationTaskExecutor](https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/task/TaskExecutionAutoConfiguration.html)* ,提供为每个任务启动新虚拟线程的*Executor*。第二个 bean,名为*ProtocolHandlerVirtualThreadExecutorCustomizer,*将以相同的方式 自定义标准*[TomcatProtocolHandler 。](https://tomcat.apache.org/tomcat-8.5-doc/api/org/apache/coyote/ProtocolHandler.html)*我们还添加了注释*[@ConditionalOnProperty](https://www.baeldung.com/spring-conditionalonproperty)**以通过切换application.yaml*文件中配置属性的值来按需启用虚拟线程:

```yaml
spring:
thread-executor: virtual
//...
```

我们来测试一下Spring Boot应用程序是否使用虚拟线程来处理Web请求调用。为此,我们需要构建一个简单的控制器来返回所需的信息:

```java
@RestController
@RequestMapping("/thread")
public class ThreadController {
@GetMapping("/name")
public String getThreadName() {
return Thread.currentThread().toString();
}
}
```

*[Thread](https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/lang/Thread.html)*对象的toString *()*方法将返回我们需要的所有信息:线程 ID、线程名称、线程组和优先级。让我们通过一个[*curl*](https://www.baeldung.com/curl-rest)请求来访问这个端点:

```bash
$ curl -s http://localhost:8080/thread/name
$ VirtualThread[#171]/runnable@ForkJoinPool-1-worker-4
```
正如我们所看到的,响应明确表示我们正在使用虚拟线程来处理此 Web 请求。换句话说,*Thread.currentThread()*调用返回虚拟线程类的实例。现在让我们通过简单但有效的负载测试来看看虚拟线程的有效性。
## 四、性能比较
对于此负载测试,我们将使用[JMeter](https://www.baeldung.com/jmeter)。这不是虚拟线程和标准线程之间的完整性能比较,而是我们可以使用不同参数构建其他测试的起点。
*在这种特殊的场景中,我们将调用Rest Controller*中的一个端点,该端点将简单地让执行休眠一秒钟,模拟复杂的异步任务:
```java
@RestController
@RequestMapping("/load")
public class LoadTestController {

private static final Logger LOG = LoggerFactory.getLogger(LoadTestController.class);

@GetMapping
public void doSomething() throws InterruptedException {
LOG.info("hey, I'm doing something");
Thread.sleep(1000);
}
}
```
请记住,由于*@ConditionalOnProperty* 注释,我们只需更改 application.yaml 中变量的值即可在虚拟线程和标准线程之间*切换*
JMeter 测试将仅包含一个线程组,模拟 1000 个并发用户访问*/load* 端点 100 秒:
![image-20230827193431807](https://img2023.cnblogs.com/blog/755525/202308/755525-20230827193604936-1596575555.png)
在本例中,采用这一新功能所带来的性能提升是显而易见的。让我们比较不同实现的“响应时间图”。这是标准线程的响应图。我们可以看到,立即完成一次调用所需的时间达到 5000 毫秒:
![image-20230827193511176](https://img2023.cnblogs.com/blog/755525/202308/755525-20230827193604663-146471729.png)
发生这种情况是因为平台线程是一种有限的资源,当所有计划的和池化的线程都忙时,Spring 应用程序除了将请求搁置直到一个线程空闲之外别无选择。
让我们看看虚拟线程会发生什么:
![image-20230827193533565](https://img2023.cnblogs.com/blog/755525/202308/755525-20230827193609186-1264647264.png)
正如我们所看到的,响应稳定在 1000 毫秒。虚拟线程在请求后立即创建和使用,因为从资源的角度来看它们非常便宜。在本例中,**我们正在比较 spring 默认固定标准线程池(默认为 200)和 spring 默认无界虚拟线程池的使用情况。**
**这种性能提升之所以可能,是因为场景过于简单,并且没有考虑 Spring Boot 应用程序可以执行的全部操作。**从底层操作系统基础设施中采用这种抽象可能是有好处的,但并非在所有情况下都是如此。
Loading

0 comments on commit 1ff741c

Please sign in to comment.