服务发现组件:Consul简易攻略

news2024/11/22 16:45:58

简介

  Consul是一种分布式、高可用性、支持多数据中心的解决方案,可动态、分布式基础架构连接和配置的应用程序。

特性

  • 『多数据中心』

    Consul是为支持数据中心而构建的,可以支持任意数量的区域,而无需复杂的配置。
  • 『服务网格』

    Consul服务网格通过自动TLS加密和基于身份的授权实现安全的服务到服务通信。应用程序可以在服务网格配置中使用sidecar代理,通过透明代理为入站和出站连接建立TLS连接。
  • 『服务发现』

    Consul使服务注册自己和通过DNSHTTP接口发现其他服务变得简单。SaaS提供商等外部服务也可以注册。
  • 『健康检查』

     健康检查使Consul能够快速提醒和反馈集群中的任何问题,与服务发现的集成可防止将流量路由到不健康的主机,并启用服务级别断路器。
  • 『键值对存储』

     灵活的键值对存储器支持存储动态配置、功能标记、协调、Leader选举等。简单的HTTP API使其易于在任何地方使用。

  Consul支持在Linux、macOS、FreeBSD、Solaris、Windows系统上运行,提供了交互友好的Web UI管理,也提供了Consul Enterprise的商业版本。

环境安装

MacOS系统,依赖xcode版本,不符合的可以升级下版本

brew tap hashicorp/tap
brew install hashicorp/tap/consul

Consul使用

  关于Consul的使用主要可以通过两种途径完成,一种通过原生支持的WebUI进行可视化管理,另一种是通过API、Command(Cli)能力实现交互。

途径备注
WebUIConsul服务启动后访问 http://{ip}:8500/ui
API、Command(Cli)Consul Command(Cli)
API

Command(Cli)

  如下是Consul支持的命令清单,关于命令集操作大部分都是开源版本支持的,部分是需要商业版才可以支持,这里只关注开源版常用命令。

命令说明
acl访问控制交互
agent运行Consul的代理
catalog目录交互
connectConsul连接相关
debug支持debug模式调试
event启动一个新事件
exec在Consul节点上执行命令
force-leave强制集群成员进入“left”状态
info提供调试信息
intention交互连接服务意向
join通知Consul代理加入集群
keygen生成新的加密密钥
keyring管理gossip层的加密密钥
kv交互KV存储
leave优雅地离开Consul集群并关闭
lock执行持有锁的命令
login使用身份验证方法登录Consul
logout销毁使用登录创建的Consul令牌
maint控制节点或服务维护模式
members输出Consul集群中的节点信息
monitor从Consul代理流式传输日志
operator提供操作集群的工具
peering创建、管理Consul集群之间的对等连接
reload触发代理重新加载配置文件
rtt评估节点之间的网络往返时间
services和服务进行交互
snapshot保存、恢复和检查Consul服务器状态的快照
tls用于创建CA和证书的内置帮助程序
validate验证配置文件/目录
version输出Consul版本
watch监听Consul变化

  下面我们通过串联实际案例体验下核心的Command(Cli)API来操作交互,如下:

查看版本

  当安装完成后,可以执行如下查看当前Consul版本号,这里我们使用的当前最新的v1.14.2版本。

[parallels@localhost bin]$ ./consul --version

Consul v1.14.2
Revision 0ba7a401
Build Date 2022-11-30T19:54:31Z
Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)

服务启动

  服务启动可以通过debug、server模式来进行。

  debug模式下,可以支持单节点启动,适合本地测试,不需要多服务器节点来搭建集群。

# -server 以服务模式启动
# -bind 绑定服务IP
# -client 允许所有IP访问
# -ui 打开可视化页面
# -data-dir 数据存储路径
# -node 节点名称
[parallels@localhost bin]$ ./consul agent -dev -bind=192.168.0.101 -client=0.0.0.0 -ui -data-dir=/usr/local/consul/data/ -node=server-01

  server模式下,需要最少3个节点共同支持方可完成启动。

  为了避免网络通信产生问题,可先关闭服务器防火墙设置,如下:

systemctl stop firewalld
systemctl disable firewalld

  这里准备了三台服务器10.211.55.3110.211.55.3210.211.55.33,分别以Server模式启动,如下:

# -server 以服务模式启动
# -bind 绑定服务IP
# -client 允许所有IP访问
# -ui 打开可视化页面
# -bootstrap-expect 集群节点数量,最少3个,最多建议5个 
# -data-dir 数据存储路径
# -node 节点名称
[parallels@localhost bin]$ ./consul agent -server -bind=10.211.55.31 -client=0.0.0.0 -ui -bootstrap-expect=3 -data-dir=/usr/local/consul/data/ -node=server-01
[parallels@localhost bin]$ ./consul agent -server -bind=10.211.55.32 -client=0.0.0.0 -ui -bootstrap-expect=3 -data-dir=/usr/local/consul/data/ -node=server-02
[parallels@localhost bin]$ ./consul agent -server -bind=10.211.55.33 -client=0.0.0.0 -ui -bootstrap-expect=3 -data-dir=/usr/local/consul/data/ -node=server-03

  启动后的Server节点并不会自动完成Leader选举,需要完成join命令操作完成加入操作,这里让10.211.55.31成为Leader,需要在10.211.55.3210.211.55.33机器上执行如下命令进行加入,如下:

[parallels@localhost bin]$ ./consul join 10.211.55.31

查看集群成员信息

  当加入完节点后,我们再来查看下当前集群的成员信息,可以看到节点名称、地址端口、节点状态、节点类型、机房等信息。

[parallels@localhost bin]$ ./consul members

Node       Address            Status  Type    Build   Protocol  DC   Partition  Segment
server-01  10.211.55.31:8301  alive   server  1.14.2  2         dc1  default    <all>
server-02  10.211.55.32:8301  alive   server  1.14.2  2         dc1  default    <all>
server-03  10.211.55.33:8301  alive   server  1.14.2  2         dc1  default    <all>

Raft视角相关操作

  由于Consul集群是基于Raft协议来构建的,Cli操作也提供了Raft视角的一些查看、处理操作。

### 可以看到10.211.55.31当前是leader节点,其余两个是follower节点

[parallels@localhost bin]$ ./consul operator raft list-peers

Node       ID                                    Address            State     Voter  RaftProtocol
server-03  996beb1a-ffa3-a621-d384-e355a1edeb37  10.211.55.33:8300  leader    true   3
server-01  0c117b67-d283-6b5d-98bd-217d829cda9e  10.211.55.31:8300  follower  true   3
server-02  0fb2224a-0ad4-7053-1bea-0c89a408d569  10.211.55.32:8300  follower  true   3

### 指定IP+PORT踢出节点不再参与Raft协议过程,适合处理节点异常的情况
consul operator raft remove-peer -address=10.211.55.33:8300

Removed peer with address "10.211.55.33:8300"

查看目录信息

### 节点信息
[parallels@localhost bin]$ ./consul catalog nodes
Node       ID        Address       DC
server-01  0c117b67  10.211.55.31  dc1
server-02  0fb2224a  10.211.55.32  dc1
server-03  996beb1a  10.211.55.33  dc1

### 服务信息
[parallels@localhost bin]$ ./consul catalog services
consul

### 数据中心、机房信息
[parallels@localhost bin]$ ./consul catalog datacenters
dc1

查看Consul元数据

  提供了Consul运维管理层面的元数据查看能力

### - agent: 提供agent相关信息
### - consul: 提供当前节点的Consul信息
### - raft: 提供Raft一致性协议信息 (https://developer.hashicorp.com/consul/docs/architecture/consensus)
### - serf_lan:提供本地局域网Gossip协议信息 (https://developer.hashicorp.com/consul/docs/architecture/gossip)
### - serf_wan:提供广域网Gossip协议信息(https://developer.hashicorp.com/consul/docs/architecture/gossip)

[parallels@localhost bin]$ ./consul info

agent:
	check_monitors = 0
	check_ttls = 0
	checks = 0
	services = 0
build:
	prerelease = 
	revision = 0ba7a401
	version = 1.14.2
	version_metadata = 
consul:
	acl = disabled
	bootstrap = false
	known_datacenters = 1
	leader = false
	leader_addr = 10.211.55.31:8300
	server = true
raft:
	applied_index = 47
	commit_index = 47
	fsm_pending = 0
	last_contact = 78.947472ms
	last_log_index = 47
	last_log_term = 2
	last_snapshot_index = 0
	last_snapshot_term = 0
	latest_configuration = [{Suffrage:Voter ID:0c117b67-d283-6b5d-98bd-217d829cda9e Address:10.211.55.31:8300} {Suffrage:Voter ID:0fb2224a-0ad4-7053-1bea-0c89a408d569 Address:10.211.55.32:8300} {Suffrage:Voter ID:996beb1a-ffa3-a621-d384-e355a1edeb37 Address:10.211.55.33:8300}]
	latest_configuration_index = 0
	num_peers = 2
	protocol_version = 3
	protocol_version_max = 3
	protocol_version_min = 0
	snapshot_version_max = 1
	snapshot_version_min = 0
	state = Follower
	term = 2
runtime:
	arch = amd64
	cpu_count = 2
	goroutines = 126
	max_procs = 2
	os = linux
	version = go1.19.2
serf_lan:
	coordinate_resets = 0
	encrypted = false
	event_queue = 0
	event_time = 2
	failed = 0
	health_score = 0
	intent_queue = 0
	left = 0
	member_time = 3
	members = 3
	query_queue = 0
	query_time = 1
serf_wan:
	coordinate_resets = 0
	encrypted = false
	event_queue = 0
	event_time = 1
	failed = 0
	health_score = 0
	intent_queue = 0
	left = 0
	member_time = 3
	members = 3
	query_queue = 0
	query_time = 1

操作KV存储

  构建完集群后我们来向Consul中做KV数据操作,如下:

### 存储key为user,value为zhangsan的数据
[parallels@localhost bin]$ ./consul kv put user zhangsan
Success! Data written to: user

### 查看当前KV数据,value存储格式是base64
[parallels@localhost bin]$ ./consul kv export
[
	{
		"key": "user",
		"flags": 0,
		"value": "emhhbmdzYW4="
	}
]

### 指定key查看数据
[parallels@localhost bin]$ ./consul kv get user
zhangsan

### 指定key删除数据
[parallels@localhost bin]$ ./consul kv delete user
Success! Deleted key: user

查看节点间延迟

  可以检查节点之间的网络延迟情况。

### 查看server-01 server-02之间
[parallels@localhost bin]$ ./consul rtt server-01 server-02
Estimated server-01 <-> server-02 rtt: 1.235 ms (using LAN coordinates)
### 查看server-01 server-03之间
[parallels@localhost bin]$ ./consul rtt server-01 server-03
Estimated server-01 <-> server-03 rtt: 1.261 ms (using LAN coordinates)
### 查看server-02 server-03之间
[parallels@localhost bin]$ ./consul rtt server-02 server-03
Estimated server-02 <-> server-03 rtt: 1.157 ms (using LAN coordinates)

注册注销服务

### 注册client-01服务
[parallels@localhost bin]$ ./consul services register -name=client-01
Registered service: client-01
### 查看服务列表
[parallels@localhost bin]$ ./consul catalog services
client-01
consul
### 注销client-01服务
[parallels@localhost bin]$ ./consul services deregister -id=client-01
Deregistered service: client-01
### 查看服务列表
[parallels@localhost bin]$ ./consul catalog services
consul

监听器使用

  监听器支持如下形式监听:

  • key - 监听指定键值对
  • keyprefix - 监控指定键前缀
  • services - 监听service服务列表
  • nodes - 监听nodes节点列表
  • service- 监听service实例
  • checks - 监听健康检查
  • event - 监听用户事件

  下面演示监听指定key变化:

### 先创建一个sh脚本,内容为 echo 'key is changed'
[root@localhost bin]# touch shell.sh

### 配置监听key为user的命令,该key变化后会执行shell.sh脚本,此时会挂起
[root@localhost bin]# ./consul watch -type=key -key=user /usr/local/bin/shell.sh

### 修改key为user的值
[parallels@localhost bin]$ ./consul kv put user lisi
Success! Data written to: user

### 监听到key的变化调用shell.sh
[root@localhost bin]# ./consul watch -type=key -key=user /usr/local/bin/shell.sh
key is changed

API

  API的交互调试,推荐使用PostmanHttp工具,API的功能和Command(Cli)提供的能力相仿,可参考文档自行测试。Consul API。

源码解读

架构概览

image.png

  上图是Consul官方提供的架构示意图,解读如下:

  • 支持多机房部署,跨机房通过局域网Gossip协议进行通信
  • 每个机房有多个Client、Server模块构成,职责如下
    • Client: 客户端,无状态,将Http/DNS接口请求转发给局域网内的服务端集群,主要作用是做服务代理进行请求转发,和具体服务进行交互,在大规模集群下很快就会膨胀到成千上万个。
    • Server: 服务端,保持配置信息,高可用集群,每个数据中心的server数量推荐为3个或者5个,通过Raft协议进行通信,是CP的实现,极端情况下保证数据一致性牺牲可用性。

源码结构

如果觉得每个模块的源码太多,梳理不清楚逻辑关系,可参考Goland中使用GoPlantUml生成ER关系图 进行ER图拆解。

  首先,将1.4.2版本代码结构整理成了思维导图,绿色背景模块是个人认为较为重要的目录,学习时可以重点关注。

Consul源码 (2).png

功能特性

  工程目录中contributing、docs两个目录文档内容是非常好的Consul源码学习材料,它能有效地引导我们快速认识Consul

  • contributing是概括性内容,便于了解全貌。
  • docs是每个模块详细介绍,便于了解细节。

  下面我们借助两个目录文档内容来剖析下Consul的核心功能模块,如下:

image.png

模块介绍
Command-Line Interface (CLI)- 基于https://github.com/mitchellh/cli 实现的命令行交互工具,这部分的核心代码在目录command中,可以在main.go查看Cli的启动进行溯源跟踪。
HTTP API- 这部分的核心代码在目录api中,使用了Go官方的API库,ConsulCLI命令也使用该客户端与本地Consul代理进行通信。
Agent Configuration- 代理配置是配置Consul的主要机制。代理配置还允许指定代理启动时将加载的配置条目、服务和检查。
- 大多数配置来自hcljson文件,但也可以使用命令行标志指定某些配置,也可以使用Auto Config加载某些配置。
- 这部分核心代码在目录agent/config
RPC-Consul使用两个RPC系统在集群内的组件之间以及其他客户端之间进行通信,gRPCGonet/RPC包。
- 客户端代理和服务器之间的通信混合使用gRPCnet/rpc。一般来说,gRPC是首选的,因为它支持诸如上下文、截止日期、取消、流和中间件等功能,但Consul已经存在了一段时间,因此大多数RPC端点仍然使用net/RPC。大多数集群内通信都是通过多路复用的“服务器”TCP端口进行的(默认值:8300)。Consul服务器实现了一个自定义协议,用于在同一端口上服务不同类型的流量,其中发送的第一个字节表示协议(例如gRPCnet/rpcRaft)。在单个服务器端口上复用多个协议有助于减少网络需求,但也让使用grpcurl等本地开发工具与Consul进行交互变得困难。
- 这部分的核心代码在目录agent/consul/rpc.go
Cluster Persistence- 集群持久化子系统完全在服务器代理中运行。它处理来自RPC子系统的读和写请求。
- 有关Consul部署体系结构和集群持久化子系统使用的共识协议的介绍,可以参阅Consul体系结构指南。
- 这部分主要是基于Raft共识协议实现
Client Agent客户端代理核心代码主要有以下部分:
- agent/cache
- agent/local
- agent/ae
客户端节点上的应用程序在客户端模式下使用其本地代理来注册服务,并发现其他服务或与密钥/值存储交互
Service Discovery服务发现包含如下部分:
- Catalog,是服务发现和服务网格的核心。它接受服务、节点和检查的注册和注销。
- DNS Interface,DNS接口允许用户使用DNS查询查找服务的IP地址和端口,DNS接口在许多方面类似于HTTP API,主要区别在于DNS协议的不同。
- Health Checks
Service Mesh (Connect)服务网格
Cluster Membership集群成员关系包含如下:
- hashicorp/serf
- hashicorp/memberlist
- network coordinates
- consul events
- consul exec
客户机和服务器模式代理都参与Gossip协议,该协议提供了两种重要机制。
- 首先,它允许代理了解集群中的所有其他代理,只需最初加入集群的单个现有成员即可。这允许客户端发现新的Consul服务器。
- 其次,Gossip协议提供了一个分布式故障检测器,集群中的代理以规则的间隔随机探测彼此。由于有了这个故障检测器,Consul可以在每个代理上本地运行运行状况检查,并在运行状况检查的状态发生变化时发送边缘触发的更新,确信如果代理完全死亡,那么集群将检测到这一点。这使得Consul的健康检查设计与具有中央轮询类型设计的集中式系统相比非常可扩展。
Key/Value StoreKV存储相关
ACLACL子系统负责验证和授权对Consul操作HTTP-APIRPC的访问。
Multi-Cluster Federation这部分主要是企业版功能

协议

  在Consul中,数据一致性使用到Raft协议完成,节点通信使用到Gossip协议完成。可以说一致性协议、通信协议两大协议簇撑起了分布式服务及其组件的理论基础和技术底盘,类似的还有Redis、Kafka、RocketMQ等。

协议实现作用
Raft基于HashiCorp自己的https://github.com/hashicorp/raft数据一致性管理,协商、投票、Leader选举等
Gossip基于HashiCorp自己的 https://www.serf.io/ 实现集群节点通信,处理节点发现、故障检测等

  在这里真的很佩服hashicorp这家公司,大家感兴趣可以在在Github上找到该公司的开源库。

Raft协议

Consul一致性协议介绍

Raft和FSM

  hashicorp/raft是集群持久性的核心。Raft需要FSM(一种有限状态机实现)来持久化状态更改。Consul FSM作为一组命令的核心代码在目录agent/consul/fsm

  Raft还需要LogStore将日志持久化到磁盘。Consul使用hashicorp/raft-boltdb,它使用boltdb.实现LogStore。在不久的将来,推荐使用bbolt。

状态存储

  Consul使用状态存储将集群的完整状态存储在内存中。状态存储在agent/consul/state实现,并使用hashicorp/go-memdb维护存储在一组表中的数据索引,状态存储的主要入口点是NewStateStore。

表/结构/索引

  状态存储被组织为一组表,每个表都有一组索引。架构中的schema.go显示表的完整列表,每个模式函数显示索引的完整列表。

  定义表索引有两种样式。原始样式使用来自hashicorp/go-memdb(例如StringFieldIndex)的通用索引器实现。这些索引使用reflect查找索引的值。当索引值是直接从struct字段中获得的单个值,并且没有oss/enterprise差异时,这些通用索引器工作得很好。

  第二种类型的索引器是仅使用函数并基于indexer.go中定义的类型实现的自定义索引器。当索引值是从一个或多个字段派生的值时,或者当索引之间存在oss/enterprise差异时,这种类型的索引非常有效。

快照/恢复

  快照(snapshot) 是用于备份集群持久性存储的数据的主要机制。如果所有Consul服务器都出现故障,则可以使用快照将群集恢复到以前的状态。

  需要注意的是,在不同的层中存在两种不同的快照和恢复概念。首先是raftFSM接口上的SnapshotRestore方法,Consul必须实现这些方法。这些方法主要通过状态存储来实现。这些方法可以由raft内部调用,以执行日志压缩(快照)或引导新的跟随器(恢复)。Consul的快照和还原类型实现快照和还原的核心代码在agent/consul/state。

  快照和还原也作为用户可以执行的操作存在。有CLI命令、HTTP API端点和RPC端点,允许用户捕获包含状态快照的存档,并将该状态还原到正在运行的集群。consul/snapshot为用户创建和读取快照存档提供了一些逻辑。有关这些面向用户的操作的参考,请参见consul/snapshot。

  最后,还有一个快照代理(仅限企业版),它使用快照API端点定期捕获快照,并可选择将其发送到某个存储位置。

Gossip协议

Consul Gossip协议介绍

image.png

  Consul使用LAN Gossip PoolWAN Gossip Pool来执行不同的功能。这些协议池能够通过利用嵌入式Serf库来执行其功能。Consul对库进行了抽象和屏蔽,以简化用户体验和操作的复杂度。

局域网通信池(LAN Gossip Pool)

  Consul所在的每个数据中心都有一个包含数据中心所有成员(客户端和服务器)的LAN Gossip PoolLAN Gossip Pool提供的成员信息允许客户端自动发现服务器,从而减少所需的配置量。故障检测也由整个集群分布和共享,而不是集中在几个服务器上,LAN Gossip Pool可以快速可靠的进行事件广播。

广域网通信池(WAN Gossip Pool)

  WAN Gossip Pool是全球唯一的,无论数据中心如何,所有服务器都应参与WAN Gossip PoolWAN Gossip Pool提供的成员信息允许服务器执行跨数据中心请求。集成故障检测允许Consul优雅地处理连接丢失,无论是整个数据中心还是远程数据中心中的单个服务器。

参考资料

目前最新版本为1.4.2,本篇以此版本为参考。

Consul官网

Consul官方文档

Github源码地址

简易的入门视频

🏄🏄🏄 如果觉得有所收获,欢迎 『点赞』、『收藏』、『关注』 一键三连支持喔~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/144686.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ROS移动机器人——32电机驱动

驱动电机&#xff0c;我们在这里使用TB6612来驱动电机&#xff0c;同时&#xff0c;电机的内部我们有编码器进行计次 输出比较 cnt&#xff0c;就是时基单元寄存器 ccr&#xff0c;在cnt下方&#xff0c;为捕获比较寄存器&#xff0c;cc是捕获比较的意思&#xff0c;r就是寄存…

内存溢出问题排查

一、问题背景下午突发服务器CPU频繁撑爆&#xff0c;服务启动后不久就挂掉。一周前系统有一次投产&#xff0c;之后再没有更新过系统。同时在日志中看到大量的dubbo服务调用失败。二、排查问题产生原因1.查看JVM崩溃日志hs_err_pid.logJVM崩溃时会生成hs_err_pid_xxx.log日志文…

面经分享|2022年秋招斩获7个规控算法工程师offer

该面经来自深蓝学院用户投稿&#xff0c;作者为东北大学自动化专业硕士。 作者2022年秋招情况&#xff1a;投递的岗位包括决策规划&#xff0c;规划控制和控制岗位。本人累计投递70家自动驾驶公司&#xff0c;最终收获10多家公司的笔试或面试反馈。最终拿到的offer包括主机厂、…

抖音短视频运营中的六大定位法

抖音六大定位法 1年龄反转法年龄反转法的秘诀就是指&#xff0c;所设定的人物、性格与实际的年龄并不是特别符合&#xff0c;从而让用户产生比较强烈的差异感。比如之前很火的北海爷爷&#xff0c;是一位有着七十多岁高龄的先生&#xff0c;但他依然很有精神&#xff0c;举止优…

【Mybatis-plus 入门教程】

&#x1f308;博客主页&#xff1a;屠一乐的博客 &#x1f4c5; 发文时间&#xff1a;2023.1.6 &#x1f388; 一定存在只有你才能做成的事 &#x1f339; 博主水平有限&#xff0c;如有错误&#xff0c;欢迎指正 欢迎各位&#x1f44d;收藏&#x1f48e;评论✉ MyBatisPlus …

舆情监测技术手段有哪些,网络舆情监测监测技术应用到哪些方面?

随着网络舆情的快速发展&#xff0c;舆情影响到方方面面&#xff0c;大多数企业将网络舆情监测纳入其日常工作。对于舆情监测上如何做到全面监测&#xff0c;那些技术上可以实现&#xff0c;接下来TOOM舆情监测小编带您简单了解舆情监测技术手段有哪些&#xff0c;网络舆情监测…

C语言 文件处理

文件操作 为什么使用文件 什么是文件 程序文件 数据文件 文件名 文件的打开和关闭 文件指针 只要没打开一个文件就会有一个文件信息区&#xff0c;只要一更改文件信息区也会跟着更改 **FILE *fopen( const char filename, const char mode ); filename 文件名 *char mode 打…

疑难杂症之vscode--During startup program exited with code 0xc0000139.--缺失重要文件(杂记)

问题展示在vscode中&#xff0c;只要用了STL容器&#xff0c;就会出现这样的提示发现自己的 vscode 不能运行带有部分 stl 库的程序&#xff0c;编译不会报错&#xff0c;运行也不会报错但是也没有结果&#xff0c;调试的话会有下图中报错。拿一个以前的程序做测试&#xff0c;…

Java 集合系列:Vector源码深入解析

概论 学完ArrayList和LinkedList之后&#xff0c;我们接着学习Vector。学习方式还是和之前一样&#xff0c;先对Vector有个整体认识&#xff0c;然后再学习它的源码&#xff1b;最后再通过实例来学会使用它。 第1部分 Vector介绍 Vector简介 Vector 是矢量队列&#xff0c;…

java服装商城购物商场项目源码

简介 Java基于ssm开发的服装商城&#xff0c;用户可以浏览商品和特价商品&#xff0c;加入购物车&#xff0c;直接下单支付&#xff0c;在我的个人中心里可以管理自己的订单&#xff0c;收货地址&#xff0c;编辑资料等。管理员可以发布商品&#xff0c;上下架商品&#xff0c…

Neo4j详细介绍及使用教程

文章目录一、Neo4j介绍1.Neo4j简介2.图数据库简介3.Neo4j的优缺点4.Neo4j的常见应用场景二、使用教程1.下载安装2.数据插入和查询(1)基本概念(2)基本语法Ⅰ.CREATE操作——创建Ⅱ.MERGE——创建或更新Ⅲ.Match操作——查找指定的图数据Ⅳ.DELETE操作——删除节点3.JAVA实战一、…

FPGA之VGA/LCD数字时钟显示

文章目录前言一、LCD显示控制1.LCD显示一个字符2.LCD显示多个字符二、数字时钟输出1.数字时钟2.十进制数据拆分BCD码三、按键检测及LCD驱动1.按键检测2.LCD驱动四、总结前言 软件实现了在4.3寸LCD左上角显示一个数字时钟&#xff0c;效果如下图所示。本文针对VGA/LCD控制时许有…

leetcode:2103. 环和杆(python3解法)

难度&#xff1a;简单 总计有 n 个环&#xff0c;环的颜色可以是红、绿、蓝中的一种。这些环分布穿在 10 根编号为 0 到 9 的杆上。 给你一个长度为 2n 的字符串 rings &#xff0c;表示这 n 个环在杆上的分布。rings 中每两个字符形成一个 颜色位置对 &#xff0c;用于描述每个…

makefile 入门

make常用选项 # make 默认在当前目录中寻找GUNmakefile,makefile,Makefile的文件作为make的输入文件 # -f 可以指定默认的输入文件名,如: -f MyMakefile # -v 显示make版本号 # -n 只输出命令,但不执行,一般用于测试 # -s 只执行命令,但不显示具体命令,与在命令中使用作用一样…

第四十四讲:神州防火墙双机热备配置

两台防火墙硬件型号和软件版本都完全相同&#xff0c;为了避免防火墙不堪重负而宕机引起网络中断&#xff0c;可以考虑应用双机热备&#xff08;HA&#xff09;解决方案。双机热备能够把两台防火墙构成一个工作组&#xff0c;一主一备&#xff0c;保证数据通信畅通&#xff0c;…

【实际开发01】- 单元测试 ( 追求正确性 )

目录 0. 单元测试 概念 / 解析 1. 为什么要进行单元测试 1. JUnit ~ Test 2. IDEA 中使用 junit 单元测试 , 不能使用 Scanner 的解决方法 3. Junit 测试 Tutorial 1. daiding 4. Test 修饰的方法必须 public 1. validatePublicVoidNoArgMethods(Test.class, false, er…

功率二极管的损耗分析和选型原则

功率二极管的损耗分析和选型原则 tip&#xff1a;参考网上资料&#xff0c;学习为主 1.二极管的分类 2.二极管的损耗组成 3.二级管的损耗分析 4.应用实例1.Flyback电源电路二极管损耗计算 5.实例应用2.BOOST电路二极管损耗计算 6.实例应用3.大功率整流桥二极管参数计算 7.选型…

sqli-labs 5~6 多命通关攻略

sqli-labs 5~6 多命通关攻略描述判断注入类型正常输入不正常输入错误输入判断 SQL 查询结果的列数猜测 SQL 查询结果中的列数为两列猜测 SQL 查询结果中的列数为三列猜测 SQL 查询结果中的列数为四列爆破方式的可行性函数 UpdateXML()爆破&#xff08;报错注入&#xff09;爆破…

农业智能化进入“刚需时代 ” ,维视智造机器视觉实验室赋能新农科人才培养

1、传统农业数字化转型 新农科人才急需紧缺数千年来&#xff0c;农业是我国立国基础&#xff0c;农业兴衰关系到国家的命运。在大力推动乡村振兴的背景下&#xff0c;高校作为强农兴农的“国之重器”&#xff0c;在培育“农”的传人、新农科建设方面扮演着不可替代的角色。世界…

C++入门——内联函数、extern “C“

一. 内联函数 1.概念及分析 以inline修饰的函数叫做内联函数&#xff0c;编译时C编译器会在调用内联函数的地方展开&#xff0c;没有函数调 用建立栈帧的开销&#xff0c;内联函数提升程序运行的效率。 int Add(int a, int b) {int c a b;return c; }int main() {int re…