@

目录

StringBoot整合ELK实现日志收集和搜索自动补全功能(详细图文教程)

最近在给小组搭建ELK环境,并集成到项目中使用,这里记录下(jdk等基础环境配置请自行百度)


一、下载ELK的安装包上传并解压

我这边用到的版本是7.6.1版本,ELK最好版本统一,避免版本兼容导致失败,可以在官网下载,下载可能会慢,我这里下载好了,可以直接用

1.Elasticsearch下载

elasticsearch-7.6.1-linux-x86_64.tar.gz

链接:https://pan.baidu.com/s/1cAswtaYx8_2Q56XPZN_ZJA

提取码:idn3

2.Logstash下载

logstash-7.6.1.tar.gz

链接:https://pan.baidu.com/s/1bXAMXSVEe1zpOx3xIbF8LA

提取码:475x

3.Kibana下载

kibana-7.6.1-linux-x86_64.tar.gz

链接:https://pan.baidu.com/s/1xTxTLEooqCHypMIFB_tPng

提取码:w6ob

上传到自定义目录:

/usr/local/src/software

4.上传并解压

接下来使用 XShell 工具连接到服务器或者虚拟机(我使用的是阿里云服务器)

ES压缩包解压:进入 /usr/local/src/software 目录

elasticsearch解压命令:tar -zxvf elasticsearch-7.6.1-linux-x86_64.tar.gz

logstash解压命令:tar -zxvf logstash-7.6.1.tar.gz

kibana解压命令:tar -zxvf kibana-7.6.1-linux-x86_64.tar.gz

解压后的文件夹修改下名字,方便输入:mv elasticsearch-7.6.1 elasticsearch7

解压后的文件夹修改下名字,方便输入:mv kibana-7.6.1 kibana7

ES目录介绍

bin:下面存放着Es启动文件         elasticsearch.bat/elasticsearch
config:配置目录
data:数据目录
jdk、lib:Java运行环境以及依赖包
logs:日志目录
modules、plugins:模块及插件目录,head插件可以存放在plugins目录下

二、Elasticsearch配置

1.修改配置文件elasticsearch.yml

基础配置

ES 本身其实也相当于是一个数据库,为此,我们在 elasticsearch7 文件夹下自己建一个 data 文件夹,用于存放数据:

mdkir data

进入 data 文件夹下,执行 pwd 命令拷贝下该文件夹的路径,下面配置要用到!

我的 data 路径:

/usr/local/src/software/elasticsearch7/data

修改配置文件elasticsearch.yml,我们进入elasticsearch7 这个文件夹下的config 文件夹,编辑 elasticsearch.yml 文件:

vim elasticsearch.yml



跨域问题

http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-headers: Authorization,X-Requested-With,Content-Length,Content-Type

保存退出esc+(:wq!)

2.新建es用户

因为Elasticsearch为了安全起见,不支持root用户直接启动

新建一个用户elasticsearch,命令:

adduser es
//添加一个名为tommy的用户
#passwd tommy //修改密码
Changing password for user tommy.
New UNIX password: //在这里输入新密码
Retype new UNIX password: //再次输入新密码
passwd: all authentication tokens updated successfully.

在software 目录下 赋予 elasticsearch7 这个文件夹的权限给 es用户,命令:

chown -R es:es /usr/local/src/software/elasticsearch7

命令,切换到 es 用户,并重新到 bin 目录下执行 ES服务

su es

3.启动Elasticsearch

在es安装目录bin下执行

./elasticsearch  -d

浏览器访问:http://服务器ip:9200/

显示如下内容表示成功

4.启动问题:

由于某种原因可能导致启动失败,我这边也遇到过一些情况,可以参考解决方案:

4.1:JDK版本问题:

future versions of Elasticsearch will require Java 11; your Java version from [/usr/local/jdk8/jdk1.8.0_291/jre] does not meet this requirement

原因:说明这个版本对应的jdk应该是java11。我们环境中的jdk是java8。其实新版的es是自带了jdk的。但是和我们环境变量的冲突了。

解决方案:修改启动文件,添加如下修改

wget https://download.java.net/java/GA/jdk11/13/GPL/openjdk-11.0.1_linux-x64_bin.tar.gz
tar -xzvf openjdk-11.0.1_linux-x64_bin.tar.gz /opt/
vi bin/elasticsearch

配置自己的jdk11

export JAVA_HOME=/opt/jdk-11.0.1
export PATH=$JAVA_HOME/bin:$PATH

添加jdk判断

if [ -x "$JAVA_HOME/bin/java" ]; then
JAVA="/opt/jdk-11.0.1/bin/java"
else
JAVA=`which java`
fi

4.2:内存不足问题处理:

可以修改 config 下的 jvm.options 配置文件,将运行大小 2g 修改为 1g(还是不行的话,再小设置到256m):

三、Logstash配置

1.新建持久化目录:

mkdir -p /usr/local/src/software/logstash-7.6.1/plugin-data

2.修改配置文件logstash.yml

编辑 /config/logstash.yml 配置文件

node.name: cpy04.dev.xjh.com    #设置节点名称,一般写主机名
path.data: /usr/local/src/software/logstash-7.6.1/plugin-data #上一步创建logstash 和插件使用的持久化目录
config.reload.automatic: true #开启配置文件自动加载
config.reload.interval: 10 #定义配置文件重载时间周期
http.host: "172.18.10.172" #(阿里云服务器私网IP)定义访问主机名,一般为域名或IP

3.安装logstash所需插件

从Filebeat 输入、过滤、输出至elasticsearch(logstash 有非常多插件,详见官网,此处不列举)

安装logstash-input-jdbc 和logstash-input-beats-master 插件

如果你的Logstash没有安装logstash-codec-json_lines插件,通过以下命令安装

/usr/local/src/software/logstash-7.6.1/bin/logstash-plugin install logstash-integration-jdbc
wget https://github.com/logstash-plugins/logstash-input-beats/archive/master.zip -O /opt/master.zip
unzip -d /usr/local/src/software/logstash-7.6.1 /opt/master.zip
root@iZwz91w9jegcgf28ttbe2yZ:/usr/local/src/software/logstash-7.6.1/bin# ./logstash-plugin install logstash-codec-json_lines
Validating logstash-codec-json_lines
Installing logstash-codec-json_lines
Installation successful

4.新建配置文件 logstash.conf(/bin目录下)

vim logstash.conf

配置文档内容

input {
tcp {
#模式选择为server
mode => "server"
#阿里云服务器私网ip和端口根据自己情况填写,端口默认4560,我这边改成4567,对应后面整合spring boot的logback.xml里appender中的destination
host => "172.18.10.172"
port => 4567
#格式json
codec => json_lines
}
}
filter {
#过滤器,根据需要填写
}
output {
elasticsearch {
action => "index"
#这里是es的地址(es服务在阿里云服务器私网ip),多个es要写成数组的形式
hosts => "172.18.10.172:9200"
#用于kibana过滤,可以填项目名称
index => "springboot-logstash-%{+YYYY.MM.dd}"
}
}

5.启动logstash

切换到/usr/local/src/software/logstash-7.6.1/bin

nohup ./logstash -f logstash.conf >/dev/null 2>&1 &

验证

访问http://服务器ip:9600/,成功的话会显示一个JSON串

6.启动问题:

由于某种原因可能导致启动失败,我这边也遇到过一些情况,可以参考解决方案:

6.1:内存问题:

:Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000c5330000

解决方案;

.修改logstash核心的执行文件 在bin目录下,有一个可执行的文件logstash,需要添加参数:(可以先

不用设置,报错的话再设置)

LS_JAVA_OPTS="-server -Xms256m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=256m"

2./usr/local/src/software/logstash-7.6.1/config修改jvm.options

-Xms256m
-Xmx256m

四、Kibana配置

1.修改配置文件kibana.yml

修改内容:

2.启动kibana

进入bin目录启动:  ./bin/kibana
或者守护进程启动: nohup ./bin/kibana &
或者 nohup ./bin/kibana >/dev/null 2>&1 & 关键在于最后的 >/dev/null 2>&1 部分,/dev/null是一个虚拟的空设备(类似物理中的黑洞),任何输出信息被重定向到该设备后,将会石沉大海
>/dev/null 表示将标准输出信息重定向到"黑洞"
2>&1 表示将标准错误重定向到标准输出(由于标准输出已经定向到“黑洞”了,即:标准输出此时也是"黑洞",再将标准错误输出定向到标准输出,相当于错误输出也被定向至“黑洞”)

进行访问本机访问 http://服务器ip:5601

五、Spring boot整合ELK实现日志采集

日志采集新增Logback直接发送日志到Logstash的形式。如果采用此方式,web服务可减少部分生成log文件配置,提高实时性和日志推送效率

1. 修改 pom.xml

logback 相关

<!-- logback -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency> <!-- logback --> <dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/net.logstash.logback/logstash-logback-encoder -->
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>5.3</version>
</dependency>

2. logback.xml

<?xml version="1.0" encoding="UTF-8"?>

<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<!--应用名称-->
<property name="APP_NAME" value="VBlog"/>
<!--日志文件保存路径-->
<property name="LOG_FILE_PATH" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/logs}"/>
<contextName>${APP_NAME}</contextName>
<!--每天记录日志到文件appender-->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE_PATH}/${APP_NAME}-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!--输出到logstash的appender-->
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<!--可以访问的logstash日志收集端口-->
<destination>172.18.10.172:4567</destination>
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder"/>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="LOGSTASH"/>
</root> </configuration>

3. Test.java

在接口中使用log进行日志生成,启动项目

4. 进入kibana -> 管理 -> 索引模式 -> 创建索引模式,输入 * ,下一步创建

5. 调用接口触发日志记录,打开Kibana-->Discover菜单-->筛选" * ",显示请求日志

六、使用logstash-input-jdbc进行Mysql与ES数据同步

1,下载 mysql-connector-java-8.0.20.jar 包放到安装目录,复制绝对路径下面会用到

2,新建配置jdbc.conf和jdbc.sql文件

在bin目录下创建,

jdbc.sql文件

select
*
from user

jdbc.conf 配置文件内容如下

input {
stdin {
}
jdbc {
# mysql相关jdbc配置
jdbc_connection_string => "jdbc:mysql://mysqlip:3306/vueblog2"
jdbc_user => "root"
jdbc_password => "*****" # jdbc连接mysql驱动的文件目录,可去官网下载:https:#dev.mysql.com/downloads/connector/j/
jdbc_driver_library => "/usr/local/src/software/logstash-7.6.1/mysql-connector-java-8.0.20.jar"
# the name of the driver class for mysql
jdbc_driver_class => "com.mysql.jdbc.Driver"
jdbc_paging_enabled => "true"
jdbc_page_size => "50000" # mysql文件, 也可以直接写SQL语句在此处,如下:
# statement => "SELECT * from user;"
statement_filepath => "/usr/local/src/software/logstash-7.6.1/bin/jdbc.sql" # 这里类似crontab,定时字段 各字段含义(由左至右)分、时、天、月、年,全部为*默认含义为每分钟都更新,比如每10分钟("*/10 * * * *")执行一次同步
schedule => "* * * * *"
#设定ES索引类型
type => "jdbc" # 是否记录上次执行结果, 如果为真,将会把上次执行到的 tracking_column 字段的值记录下来,保存到 last_run_metadata_path 指定的文件中
#record_last_run => "true" # 是否需要记录某个column 的值,如果record_last_run为真,可以自定义我们需要 track 的 column 名称,此时该参数就要为 true. 否则默认 track 的是 timestamp 的值.
#use_column_value => "true" # 如果 use_column_value 为真,需配置此参数. track 的数据库 column 名,该 column 必须是递增的. 一般是mysql主键
#tracking_column => "id" #last_run_metadata_path => "/opt/logstash/conf/last_id" # 是否清除 last_run_metadata_path 的记录,如果为真那么每次都相当于从头开始查询所有的数据库记录
#clean_run => "false" #是否将 字段(column) 名称转小写
#lowercase_column_names => "false"
}
}

过滤处理,如果需要,也可参考elk安装那篇

filter {

  json {
source => "message"
remove_field => ["message"]
} } output {
# 输出到elasticsearch的配置
elasticsearch {
hosts => ["http://ESIP:9200/"]
index => "jdbc"
document_type => "user"
#自增ID编号
document_id => "%{id}"
template_overwrite => true
} # 这里输出调试,正式运行时可以注释掉
stdout {
codec => json_lines
}
}

在logstash安装目录bin下面创建文件夹 logstash_jdbc,将之前的 logstash.conf和刚才创建的jdbc.conf 移动到 logstash_jdbc文件夹下。后面启动logstash会用到

3,然后到bin目录下启动 Logstash

nohup ./logstash -f logstash_jdbc/ >/dev/null 2>&1 &

七、使用ES实现简单的搜索自动补全功能

1,安装es客户端pom.xml依赖包

<!--es客户端-->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.6.1</version>
<exclusions>
<exclusion>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
</exclusion>
<exclusion>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.6.1</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.6.1</version>
</dependency>

2,编写ES-Java客户端调用代码

/**
* Created by fansongsong
*/
@Component
@Service
public class Util { public static User getCurrentUser() {
User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return user;
} private static RestHighLevelClient client;
public Util() {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("ESIP", 9200, "http")));
this.client = client;
}
public void shutdown(){
if(client!=null){
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} /**
* 根据指定的内容,查询所有Doc。
* @return
*/
public static List<Map<String,Object>> searchArticle(String index,String key, String value){
SearchHits searchHits = search(index,key,value);
List<Map<String,Object>> list = new ArrayList<>();
for(SearchHit hit:searchHits.getHits()){
System.out.println( hit.getSourceAsString());
Map<String,Object> stringObjectMap = hit.getSourceAsMap();
stringObjectMap.put("name", stringObjectMap.get("nickname"));
list.add(stringObjectMap);
}
return list;
} public static SearchHits search(String index, String key, String value){
QueryBuilder matchQueryBuilder = QueryBuilders.matchPhraseQuery(key, value);
// matchQueryBuilder.
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// sourceBuilder.query(QueryBuilders.termQuery("content", content));
sourceBuilder.query(matchQueryBuilder);
sourceBuilder.from(0);
sourceBuilder.size(100);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(index);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse;
List<Map<String,Object>> list = new ArrayList<>();
SearchHits searchHits = null;
try {
searchResponse = client.search(searchRequest,RequestOptions.DEFAULT);
searchHits = searchResponse.getHits();
for(SearchHit hit:searchHits.getHits()){
System.out.println( hit.getSourceAsString());
list.add(hit.getSourceAsMap());
}
} catch (IOException e) {
e.printStackTrace();
}
return searchHits;
} }

3,Service

public List<String> getUserByNicknameKeyword(String nickname) {
List<Map<String, Object>> mapList = Util.searchArticle("jdbc", "nickname", nickname);
List<String> goodsNameList = mapList.stream().map(m->m.get("nickname").toString()).collect(Collectors.toList());
log.info(nickname+"==>搜索自动补全:"+JSONArray.toJSONString(mapList));
return goodsNameList;
}

4,Controller

@RestController
@RequestMapping("/admin")
public class UserManaController {
@Autowired
UserService userService; @RequestMapping(value = "/user/keyword", method = RequestMethod.GET)
@ResponseBody
public List<?> getUserByNicknameKeyword(String nickname) {
return userService.getUserByNicknameKeyword(nickname);
}
}

前端代码vue

<div style="margin-top: 10px;display: flex;justify-content: center">
<input
placeholder="默认展示部分用户,可以通过用户名搜索用户..."
prefix-icon="el-icon-search"
v-model="keywords" style="width: 400px" size="small"
@keyup="get($event)" @keydown.down.prevent="selectDown"
@keydown.up.prevent="selectUp"
> <el-button type="primary" icon="el-icon-search" size="small" style="margin-left: 3px" @click="searchClick">搜索
</el-button>
</div>
<div style="margin-top: 10px;display: flex;justify-content: center">
<ul>
<li class="text-center" v-for="(value,index) in myData"><span class="text-success textprimary" :class="{gray:index==now}">{{value}}</span></li>
</ul>
</div>
methods: {
get:function (event) {
if(event.keyCode==38||event.keyCode==40)return;
var _this = this;
getRequest("/admin/user/keyword?nickname="+this.keywords).then(resp=> {
_this.loading = false;
if (resp.status == 200) {
_this.myData = resp.data;
} else {
_this.$message({type: 'error', message: '数据加载失败!'});
}
}, resp=> {
_this.loading = false;
if (resp.response.status == 403) {
var data = resp.response.data;
_this.$message({type: 'error', message: data});
}
});
},
selectDown:function () {
this.now++;
if(this.now==this.myData.length)this.now=-1;
this.keywords=this.myData[this.now];
},
selectUp:function () {
this.now--;
if(this.now==-2)this.now=this.myData.length-1;
this.keywords=this.myData[this.now];
}
},
data(){
return {
loading: false,
keywords: '',
myData:[],
now:-1
}
}

显示效果

StringBoot整合ELK实现日志收集和搜索自动补全功能(详细图文教程)的更多相关文章

  1. C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志

    C#实现多级子目录Zip压缩解压实例 参考 https://blog.csdn.net/lki_suidongdong/article/details/20942977 重点: 实现多级子目录的压缩, ...

  2. asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程

    最近在学习张善友老师的NanoFabric 框架的时了解到Exceptionless : https://exceptionless.com/ !因此学习了一下这个开源框架!下面对Exceptionl ...

  3. 【转】asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程

    最近在学习张善友老师的NanoFabric 框架的时了解到Exceptionless : https://exceptionless.com/ !因此学习了一下这个开源框架!下面对Exceptionl ...

  4. java整合Elasticsearch,实现crud以及高级查询的分页,范围,排序功能,泰文分词器的使用,分组,最大,最小,平均值,以及自动补全功能

    //为index创建mapping,index相当于mysql的数据库,数据库里的表也要给各个字段创建类型,所以index也要给字段事先设置好类型: 使用postMan或者其他工具创建:(此处我使用p ...

  5. [LeetCode] Design Search Autocomplete System 设计搜索自动补全系统

    Design a search autocomplete system for a search engine. Users may input a sentence (at least one wo ...

  6. 第三百六十八节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)用Django实现搜索的自动补全功能

    第三百六十八节,Python分布式爬虫打造搜索引擎Scrapy精讲—用Django实现搜索的自动补全功能 elasticsearch(搜索引擎)提供了自动补全接口 官方说明:https://www.e ...

  7. 四十七 Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)用Django实现搜索的自动补全功能

    elasticsearch(搜索引擎)提供了自动补全接口 官方说明:https://www.elastic.co/guide/en/elasticsearch/reference/current/se ...

  8. [LeetCode] 642. Design Search Autocomplete System 设计搜索自动补全系统

    Design a search autocomplete system for a search engine. Users may input a sentence (at least one wo ...

  9. 仿Google首页搜索自动补全

    仿Google自动补全,实现细节: 后台是简单的servlet(其实就是负责后台处理数据交互的,没必要非跌用个struts...什么的) 传输介质:xml 使用jQuery js框架 功能实现: 如果 ...

随机推荐

  1. JSP和Servlet有哪些相同点和不同点?

    JSP是Servlet技术的扩展,本质上是Servlet的简易方式,更强调应用的外表表达.JSP编译后是"类servlet". Servlet和JSP最主要的不同点在于,Servl ...

  2. 为什么Java中不支持多重继承?

    我发现这个 Java 核心问题很难回答,因为你的答案可能不会让面试官满意,在大多数情况下,面试官正在寻找答案中的关键点,如果你提到这些关键点,面试官会很高兴.在 Java 中回答这种棘手问题的关键是准 ...

  3. springcloud如何实现服务的注册?

    1.服务发布时,指定对应的服务名,将服务注册到 注册中心(eureka zookeeper)2.注册中心加@EnableEurekaServer,服务用@EnableDiscoveryClient,然 ...

  4. spring源码-ioc容器周期

    Spring容器的refresh 创建刷新:   1-prepareRefresh刷新前的预处理: initPropertySources 初始化一些属性配置,原来是空的,子类自定义的属性设置方法 g ...

  5. nginx简介&nginx基本配置和优化

    一.nginx简介 1.nginx的发展 Nginx是俄罗斯人编写的一款高性能HTTP和反向代理服务器.Nginx能够选择高效的epoll(Linux2.6内核).kqueue(FreeBSD).ev ...

  6. 四、Springboot+jpa+mycat应用

    一.后台配置文件 # 连接地址 url: jdbc:mysql://127.0.0.1:8066/CHUNK?useUnicode=true&characterEncoding=utf-8&a ...

  7. 学习saltstack (七)

    一.SaltStack概述 Salt,,一种全新的基础设施管理方式,部署轻松,在几分钟内可运行起来,扩展性好,很容易管理上万台服务器,速度够快,服务器之间秒级通讯. salt底层采用动态的连接总线, ...

  8. 学习GlusterFS(六)

    一.GlusterFS概述 分布式文件系统由来 在介绍之前我们先来看下文件系统及典型的NFS文件系统. 计算机通过文件系统管理,存储数据的.而现在数据信息时代中人们可获取数据成指数倍的增长,单纯通过增 ...

  9. springboot 指定启动环境

    java -jar dbmaster.jar --spring.profiles.active=test

  10. FPGA入门到精通系列1:数字电路基础知识

      本文主要介绍数字电路基础知识,用最简洁的内容介绍最核心的知识. 1.数字电路是什么? 数字电路是利用电源电压的高电平和低电平分别表示1和0,进而实现信息的表达.模拟信号:随时间连续变化的信号.处理 ...