libp2p 快速开始

news2024/11/21 15:30:36

文章目录

  • 第一部分:libp2p 快速入门
    • 一、什么是libp2p
      • libp2p 发展历程
      • libp2p的特性
      • p2p 网络和我们熟悉的 client/server 网络的区别:
    • 二、Libp2p的实现目标
    • 三、Libp2p的用途
    • 四、运行 Libp2p 协议流程
      • libp2p 分为三层
      • libp2p 还有一个局域网节点发现协议 mDNS
  • 第二部分:使用实战
    • 一、基本接口
      • multiaddr
      • Host
      • protocol.ID
      • 如何封装 libp2p?
    • 二、基本使用
    • 参考

第一部分:libp2p 快速入门

一、什么是libp2p

libp2p 官网:非常重要,会解释非常多的新概念,是学习 libp2p 的第一课。
libp2p spec:这个是比官网更详细的开发指导手册,所有语言的实现都基于这个 specs。
rust-libp2p: libp2p 的 Rust 实现。

Libp2p是一个模块化的网络栈,通过将各种传输和P2P协议结合在一起,使得开发人员很容易构建大型、健壮的P2P网络。

libp2p 的产生是一个漫长的过程。 它是对网络协议栈的深层次的挖掘, 丰富了过去点对点的协议。在过去的15年里面, 构建大规模的点对点分布式应用及其复杂, libp2p的目标就是希望让事情变得简单。 Libp2p 设计的初衷就是为了支持未来的去中心化网络协议,它的宗旨是让开发者进行应用程序开发时,能确保他们的服务是可达且可用的。

如果说TCP/IP协议是互联网时代网络层的标准,那么libp2p的愿景是希望成为区块链时代,网络层的标准。 虽然离这个目标还想去甚远, 但随着ipv4地址的耗尽,以及区块链浪潮的到来,这苗星星之火仿佛已经燃起。

bp2p 包含一系列协议的实现,这些协议共同作用,完成了:

p2p 网络的传输层(下图绿色):支持几乎所有的主流传输协议,甚至允许不同节点间使用不同的传输层,比如 native 节点间优先使用 QUIC,而 native 和 web 节点间使用 websocket。
节点发现(黄色,注意这里 PKI 是指基于 PKI 的节点身份):一般本地网络可以使用 mDNS,大规模 p2p 网络一般使用 bootstrap 来连接初始节点,然后通过 gossip 获取更多节点信息,并通过 Kad DHT 来查找节点。
节点路由(蓝色):主要使用 Kad DHT 通过多跳来路由到网络中任意一个节点
内容路由(紫色):如果点对点发送消息,可以通过 Kad DHT,如果在网络中 flood,可以通过 floodsub 和 gossipsub 来对某个 topic 的内容进行广播。
NAT traversal(红色):包括主流的 hole punching 解决方案

在这里插入图片描述(图片来源:A network framework for decentralized P2P application development [2])

libp2p 发展历程

libp2p孵化于ipfs项目, 最初libp2p是ipfs的网络层实现。 在过去的数十年间, 构建分布式p2p项目,一直是困扰大家的难题。 为简化这种操作,libp2p项目应运而生,libp2p是一组网络协议套件,任何人,任何应用都可以使用libp2p进行构建分布式应用。可以说libp2p项目极大简化了底层技术的开发难度,我们可以基于libp2p构建自己的分布式系统。

libp2p is used by IPFS as its networking library.
libp2p被用作IPFS的网络层。

libp2p 处于ipfs项目的最底层。最开始,libp2p是在ipfs项目里面的,只是ipfs项目中的一个网络层模块,大概在2017年左右, protocol lab对整个产品序列与技术栈进行了重新规划,ipfs项目被拆分成了很多个子项目,而这每一个子项目相互独立,又各有关联。 在整个项目发展过程中,尤其是在18年,整个项目模块化重构,被拆的很细。而以大的产品类别进行划分,可以划分为以下产品栈:

  • ipfs
  • libp2p
  • filecoin
  • ipld

ibp2p 模块在 IPFS 中主要负责数据的传递功能,即路由、网络、交换等。
libp2p是一套点对点的协议来发现节点,并连接他们,发现内容,并转移它们。

libp2p的主要功能是:

  • 发现节点
  • 连接节点
  • 发现数据
  • 传输数据

libp2p的特性

  1. Transport传输:

传输层是libp2p的基础,它负责数据从一个节点到另一个节点的可靠发送和接收。libp2p提供了一个可用于适配支持现有或未来传输协议的简单的接口,从而允许libp2p应用可以运行在不同的运行时和网络环境中。最新版本的go-libp2p已支持TCP/TLS、WebSocket、QUIC传输层实现。

  1. Identity身份验证:

libp2p使用公钥作为节点身份的基础,这么做有两个互补的用途,一是根据公钥可以为节点提供一个全局唯一的身份ID(PeerId),二是所有节点可以用PeerId恢复出被认证过的节点的公钥,用于它们之间建立安全通讯

  1. Security安全性:

libp2p支持将传输层提供的一个连接“upgrading”到一个安全加密通道中。这种方式很灵活,可以支持多种通讯加密方式。当前libp2p支持TLS1.3和Noise两种(老版本支持已弃用的Secio)。

  1. PeerRouting节点路由:

当你想要向另一个节点发送一个消息时,你需要知道两个信息:它的PeerId和它的网络地址。在很多情况下我们只有对方的PeerId,我们需要一种可以找到它们的网络地址的方法。节点路由是通过利用其他节点的信息发现目标节点的网络地址的过程。

在一个节点路由系统中,若我们想知道节点A的信息,我们可以向节点B请求查询,如果节点B有节点A的信息,则我们可以获得节点A的信息;如果节点B没有节点A的信息,则节点B会返回给我们一个它认为可能知道节点A的信息的节点C的信息,我们可以再向节点C请求查询。随着我们查询越来越多的节点,我们不仅增加了找到节点A信息的概率,同时我们还在自己的路由表中建立了一个更完整的网络视图,这样我们也可以为别的节点提供路由查询服务。

当前,libp2p的节点路由的稳定实现是使用分布式哈希表(distributed hash table)基于Kademlia路由算法迭代查询实现的。

  1. Content Discovery 内容发现服务:

在一些系统中,我们更关心的是它能为我们提供什么,而不是我们在和谁通讯。比如,我们想要一个文件,我们可以验证这个文件的完整性,所以我们不关心从谁那拿到这个文件。

libp2p为这个场景提供了一个内容路由接口(content routing interface),它的稳定实现也是基于与节点路由中相同的KadDHT实现的。

  1. Messaging / PubSub 消息传输及发布订阅:

向其他节点发送消息是大多数P2P系统的核心功能,而PubSub是一种非常有用的模式用于给一组订阅者发送消息。

libp2p定义了一个可以向已订阅指定Topic的所有节点发送消息的PubSub接口,该接口有两种实现:floodsub和gossipsub。默认使用gossipsub。

p2p 网络和我们熟悉的 client/server 网络的区别:

p2p 网络的每一个节点既是客户端,又是服务器
p2p 网络的每个节点,都(潜在)是数据的发起者和存储者(对比:c/s 网络中,server 拥有数据)
p2p 网络很不稳定,节点可能进进出出(对比:c/s 网络,服务器非常稳定,一般 SLA 都有几个9)
p2p 网络需要某种机制来实现节点的发现和查找(对比:c/s 网络,客户端知道服务器在哪,如何访问)
p2p 网络(往往)需要 NAT traversal / Hole punching 等技术来允许两个节点之间通讯。这是因为很多节点(比如说家庭网络)往往藏在运营商的 NAT 服务器之后。

二、Libp2p的实现目标

  • 支持各种各样的传输方式:
    • 传输:TCP,UDP,SCTP,UDP,uTP,QUIC,SSH,etc.
    • 安全传输:TLS,DTLS,CurveCP,SSH
  • 有效使用sockets(连接重用)
  • 允许端点之间的交流可以在一个socket上复用(避免过多的握手)
  • 允许端点之间通过一个协商过程使用多协议以及各自的版本
  • 向后兼容
  • 在现在的系统中可以运行
  • 充分使用当前网络技术的能力
  • 实现NAT转换
  • 实现连接中继
  • 实现加密通道
  • 充分使用基础传输(例如原生的流复用等)

三、Libp2p的用途

认识Libp2p的用途
参考URL: https://baijiahao.baidu.com/s?id=1654695941739663075&wfr=spider&for=pc

  • 物联网
    对于物联网场景来说,P2P连接是很重要的一环。比如,在安防场景,安防摄像头与手机之间最好建立直连连接。如此可以大幅度减轻中央服务器的带宽压力。libp2p可以帮助其完成链路上的连接工作,同时可以完成诸如NAT打洞(目前尚未实现,但正在完善中)、流量及RTT统计、长链接、流式加密传输、服务端主动和终端通信等工作。此外,libp2p在车联网领域也有适合的应用场景。由于该场景中终端设备会不断在各种网络之间进行切换,导致其IP地址信息不断发生变化。

    **libp2p基于节点ID的链接方式及DHT路由发现机制,可以解除底层物理链接与上层逻辑的耦合。随着互联网的发展,应用规模越来越大,如何有效且快速地分发信息,同时降低中心化服务器的压力,是未来网络技术发展的一个重要方向。

  • 区块链
    在区块链领域里面已经有项目利用libp2p作为自己的底层服务,比如之前多次提到的 Filecoin。在“区块数据同步”“文件传输”节点查找”等核心环节都使用了libp2p。还有 Polkadot(波卡链)项目,作为可能成为区块链3.0的开辟者,为了兼容现有的诸如以太坊等主链而采用异构多链架构,更要考虑终端设备的复杂场景,因此选择使用libp2p作为其底层传输层,利用libp2p在各个模块中的高度抽象带来的灵活性及可扩展性,来避免因区块链技术发展而导致的不兼容问题。

  • 分布式消息
    分布式消息系统,可以不通过中心服务器的中转功能,直接在节点之间建立连接,用于消息的发送和接收。去除了中心化服务器,可以有效防止单点失效、网络攻击。

  • 传输文件
    Filecoin和IPFS是基于libp2p来进行数据传输的。对于点对点文件传输,libp2p将有非常广泛的应用场景。

四、运行 Libp2p 协议流程

  1. 运行 Libp2p 协议的节点在初始化之后需要通过各种方式发现更多的节点,比如 Bootstrap list、mDNS、DHT 等,这主要由发现模块负责与实现。

  2. 当发现更多接点后,Libp2p 会把这些获取到的节点信息存储在分布式记录存储模块中,供以后方便使用。

  3. 当上层应用需要连接某个节点时,节点路由模块会找到多条不同的路径,连接管理模块会对这些路径进行尝试连接。

  4. 连接成功之后,上层应用将通过内容路由模块与连接节点进行内容交互,在底层通过传输模块互相传递数据。

下面我们具体分析一下连接的建立过程,主要包括3个步骤,包括地址解析、传输协议适配、双方协商。

  1. 地址解析
  2. 传输协议适配
  3. 双方协商

连接建立之后,libp2p 会首先进行双方协商,确定对方支持哪些功能。负责协商功能的是 identify 协议,它是内置在 libp2p 的基础协议,能够交换节点的公钥、本地监听地址等。

协商完成后,连接两端的节点会找到共同支持的协议,并且初始化它们。初始化时会注册每种协议的 handler(回调函数),当有协议数据到达时,相应的 handler 就会被调用。 由于多种传输协议会复用同一个底层连接,所以连接会被拆分成多个“流(Stream)”。

libp2p 分为三层

  • Transport 传输层:负责数据的传输。
    底层网络协议:支持 TCP / UDP / QUIC 等;
    安全协议:支持 TLS 1.3 / Noise;
    多路复用(Stream Multiplexing):支持 Yamux,mplex 从 libp2p-0.52.0 开始不再支持。

  • Protocols 协议层:负责数据的处理。
    一个 P2P 节点要使用很多 Protocols,包括节点发现(Kademlia、Identify、Ping)、内容发现(Gossipsub)、和请求响应(Request-Response)
    libp2p 定义了很多官方协议 spec,我们也可以实现自己的协议,这是封装 libp2p 的方式之一。
    一个 Protocol 包含两个核心部分:Behaviour 和 BehaviourEvent。在构造 Swarm 时需要 Behaviour;在处理 SwarmEvent 时需要处理 BehaviourEvent。

  • Swarm 控制层:负责将 Transport 和 Protocols 结合起来,相当于 HTTP Server 中的 Controller。

libp2p 还有一个局域网节点发现协议 mDNS

第二部分:使用实战

官方demo程序:https://github.com/libp2p/go-libp2p/tree/master/examples

libp2p 分为三层:transport, swarm, protocol
运行一个 P2P 节点的步骤:构造 transport -> 构造 protocol -> 构造 swarm -> 运行 swarm -> 处理 swarm events

  • Transport 传输层:负责数据的传输。// 相当于 tinychain 的网络层
  • Protocols 协议层:负责数据的处理。// 相当于 tinychain 的业务层,libp2p 没有状态,所以不需要数据层
  • Swarm 控制层:负责将 Transport 和 Protocols 结合起来,相当于 HTTP Server 中的 Controller。 /

一、基本接口

multiaddr

libp2p使用了multiaddr,一个自描述的地址形式,可以理解为不同协议不同地址类型的一个封装。这使得libp2p可以不透明的处理系统中的所有地址,支持网络层中的各种传输协议。

Host

// Host is an object participating in a p2p network, which
// implements protocols or provides services. It handles
// requests like a Server, and issues requests like a Client.
// It is called Host because it is both Server and Client (and Peer
// may be confusing).
type Host interface {
	// ID returns the (local) peer.ID associated with this Host
	ID() peer.ID

	// Peerstore returns the Host's repository of Peer Addresses and Keys.
	Peerstore() peerstore.Peerstore

	// Returns the listen addresses of the Host
	Addrs() []ma.Multiaddr

	// Networks returns the Network interface of the Host
	Network() network.Network

	// Mux returns the Mux multiplexing incoming streams to protocol handlers
	Mux() protocol.Switch

	// Connect ensures there is a connection between this host and the peer with
	// given peer.ID. Connect will absorb the addresses in pi into its internal
	// peerstore. If there is not an active connection, Connect will issue a
	// h.Network.Dial, and block until a connection is open, or an error is
	// returned. // TODO: Relay + NAT.
	Connect(ctx context.Context, pi peer.AddrInfo) error

	// SetStreamHandler sets the protocol handler on the Host's Mux.
	// This is equivalent to:
	//   host.Mux().SetHandler(proto, handler)
	// (Threadsafe)
	SetStreamHandler(pid protocol.ID, handler network.StreamHandler)

	// SetStreamHandlerMatch sets the protocol handler on the Host's Mux
	// using a matching function for protocol selection.
	SetStreamHandlerMatch(protocol.ID, func(string) bool, network.StreamHandler)

	// RemoveStreamHandler removes a handler on the mux that was set by
	// SetStreamHandler
	RemoveStreamHandler(pid protocol.ID)

	// NewStream opens a new stream to given peer p, and writes a p2p/protocol
	// header with given ProtocolID. If there is no connection to p, attempts
	// to create one. If ProtocolID is "", writes no header.
	// (Threadsafe)
	NewStream(ctx context.Context, p peer.ID, pids ...protocol.ID) (network.Stream, error)

	// Close shuts down the host, its Network, and services.
	Close() error

	// ConnManager returns this hosts connection manager
	ConnManager() connmgr.ConnManager

	// EventBus returns the hosts eventbus
	EventBus() event.Bus
}

protocol.ID

func DhtProtocolName(netName dtypes.NetworkName) protocol.ID {
	return protocol.ID("/fil/kad/" + string(netName))
}
...

dht.ProtocolPrefix(build.DhtProtocolName(nn)),

//ProtocolPrefix设置附加到所有DHT协议的特定于应用程序的前缀。例如,
///myapp/kad/1.0.0而不是/ipfs/kad/1.0.0。前缀的格式应为/myapp。
//
//默认为默认dht.DefaultPrefix (dht包下 const DefaultPrefix protocol.ID = “/ipfs”)

如何封装 libp2p?

自定义 protocol:工作量很大,可能要重新实现官方已提供的 protocols
自定义 swarm event handlers:较简单,找到要处理哪些 evnets,问题就解决了一半

二、基本使用

官方demo:https://github.com/libp2p/go-libp2p/tree/master/examples/libp2p-host

创建 libp2p 主机

// To construct a simple host with all the default settings, just use `New`
h, err := libp2p.New()
if err != nil {
	panic(err)
}
defer h.Close()

fmt.Printf("Hello World, my p2p hosts ID is %s\n", h.ID())

如果您想对配置进行更多控制,则可以为构造函数指定一些选项。有关构造函数支持的所有配置的完整列表,请参阅文档中的不同选项 。

在此片段中,我们设置了许多有用的选项,例如自定义ID并启用路由。这将提高同伴在NAT’ED环境上的可发现性和可达到性:

// Set your own keypair
priv, _, err := crypto.GenerateKeyPair(
	crypto.Ed25519, // Select your key type. Ed25519 are nice short
	-1,             // Select key length when possible (i.e. RSA).
)
if err != nil {
	panic(err)
}

var idht *dht.IpfsDHT

h2, err := libp2p.New(
	// Use the keypair we generated
	libp2p.Identity(priv),
	// Multiple listen addresses
	libp2p.ListenAddrStrings(
		"/ip4/0.0.0.0/tcp/9000",      // regular tcp connections
		"/ip4/0.0.0.0/udp/9000/quic", // a UDP endpoint for the QUIC transport
	),
	// support TLS connections
	libp2p.Security(libp2ptls.ID, libp2ptls.New),
	// support Noise connections
	libp2p.Security(noise.ID, noise.New),
	// support QUIC
	libp2p.Transport(libp2pquic.NewTransport),
	// support any other default transports (TCP)
	libp2p.DefaultTransports,
	// Let's prevent our peer from having too many
	// connections by attaching a connection manager.
	libp2p.ConnectionManager(connmgr.NewConnManager(
		100,         // Lowwater
		400,         // HighWater,
		time.Minute, // GracePeriod
	)),
	// Attempt to open ports using uPNP for NATed hosts.
	libp2p.NATPortMap(),
	// Let this host use the DHT to find other hosts
	libp2p.Routing(func(h host.Host) (routing.PeerRouting, error) {
		idht, err = dht.New(ctx, h)
		return idht, err
	}),
	// Let this host use relays and advertise itself on relays if
	// it finds it is behind NAT. Use libp2p.Relay(options...) to
	// enable active relays and more.
	libp2p.EnableAutoRelay(),
)
if err != nil {
	panic(err)
}
defer h2.Close()

fmt.Printf("Hello World, my second hosts ID is %s\n", h2.ID())

参考

参考资料:libp2p-specifications : https://github.com/libp2p/specs
为什么 ETH2.0 要选择 libp2p ?
参考URL: https://blog.csdn.net/shangsongwww/article/details/89428696
libp2p 替代方案调研
参考URL: https://www.jianshu.com/p/214ec5f54bbd
参考资料:libp2p-specifications : https://github.com/libp2p/specs
Libp2p学习(一)
参考URL: https://www.cnblogs.com/YuzhouQiang/p/10593160.html
IPFS世界的物流系统:libp2p
参考URL: https://blog.csdn.net/IPFS_Newb/article/details/83186581
长安链P2P网络技术介绍(2):初识LibP2P
参考URL: https://cloud.tencent.com/developer/article/1988253
网络协议十二之P2P协议
参考URL: https://www.cnblogs.com/SuoLiweng/articles/16574502.html
[推荐]06 | libp2p: 需求分析与封装思路
参考URL: https://zhuanlan.zhihu.com/p/643357754
【go-libp2p学习笔记】使用go-libp2p搭建中转服务器(circuit relay server)
参考URL: https://blog.csdn.net/Cake_C/article/details/127630718
[推荐]探索 libp2p:基本知识
参考URL: https://cloud.tencent.com/developer/article/1836307

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

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

相关文章

27系列DGUS智能屏发布:可实时播放高清模拟信号摄像头视频

针对高清晰度的模拟信号摄像头视频画面的显示需求,迪文特推出27系列DGUS智能屏。该系列智能屏可适配常见的AHD摄像头、CVBS摄像头,支持单路1080P高清显示、两路720P同屏显示(同一类型摄像头)。用户通过DGUS简单开发即可实现摄像头…

netty-daxin-3(rpc远程调用)

文章目录 nettyRpcObjectEncoder 与 ObjectDecoderjdk动态代理回顾Rpc调用过程简析服务端客户端 nettyRpc ObjectEncoder 与 ObjectDecoder ObjectEncoder继承自MessageToByteEncoder<Serializable>&#xff0c;它内部使用ByteBufOutputStream包装ByteBuf对象&#xff…

SpringBoot 自动装配原理---源码详解

目录 SpringBoot 自动装配原理源码流程详解&#xff1a;流程总结&#xff1a;条件匹配解释&#xff1a;其他解释&#xff1a; SpringBoot 自动装配原理 源码流程详解&#xff1a; 1、先看启动类&#xff0c;启动这个main方法&#xff0c;然后调用这个run方法。 2、把 启动类作…

一文了解Tomcat

文章目录 1、Tomcat介绍2、Tomcat使用配置2.1、Tomcat下载启动2.2、Tomcat启动乱码2.3、Tomcat端口号修改 3、Tomcat项目部署4、IDEA中使用Tomcat方式 1、Tomcat介绍 什么是Tomcat ​ Tomcat是Apache软件基金会一个核心项目&#xff0c;是一个开源免费的轻量级web服务器&#x…

Networkx实现小世界网络的分析

Networkx实现小世界网络的分析 小世界网络 小世界现象&#xff0c;也被称为六度分离原则&#xff0c;即如果你在地球上的任何地方随便选择任何两个人&#xff0c;你会发现一条至多由他们之间的6个熟人形成的路径。在网络科学语言中&#xff0c;六度也被称为小世界性质&#x…

C++相关闲碎记录(16)

1、正则表达式 &#xff08;1&#xff09;regex的匹配和查找接口 #include <regex> #include <iostream> using namespace std;void out (bool b) {cout << ( b ? "found" : "not found") << endl; }int main() {// find XML/H…

【C++干货铺】继承后的多态 | 抽象类

个人主页点击直达&#xff1a;小白不是程序媛 C系列专栏&#xff1a;C干货铺 代码仓库&#xff1a;Gitee 目录 多态的概念 多态的定义和实现 多态的定义条件 虚函数 虚函数的重写 特殊情况 协变&#xff08;基类和派生类的虚函数返回值不同&#xff09; 析构函数的重…

如果你找不到东西,请先确保你在正确的地方寻找

之前我们在几篇文章中描述了如何进行”思想”调试&#xff0c;今天的文章我将不会这样做。 因为下面的编程错误大部分人都会遇到&#xff0c;如果你看一眼下面的代码&#xff0c;你不会发现有什么问题&#xff0c;这仅仅是因为你的的大脑只给你希望看到的&#xff0c;而不是那…

分数约分-第11届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第20讲。 分数约分&#xf…

算法模板之单链表图文讲解

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;算法模板、数据结构 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. ⛳️使用数组模拟单链表讲解1.1 &#x1f514;为什么我们要使用数组去模拟单链表…

appium2.0.1安装完整教程+uiautomator2安装教程

第一步&#xff1a;根据官网命令安装appium&#xff08;Install Appium - Appium Documentation&#xff09; 注意npm前提是设置淘宝镜像&#xff1a; npm config set registry https://registry.npmmirror.com/ 会魔法的除外。。。 npm i --locationglobal appium或者 npm…

多线程 (上) - 学习笔记

前置知识 什么是线程和进程? 进程: 是程序的一次执行,一个在内存中运行的应用程序。每个进程都有自己独立的一块内存空间&#xff0c;一个进程可以有多个线程&#xff0c;比如在Windows系统中&#xff0c;一个运行的xx.exe就是一个进程。 线程: 进程中的一个执行流&#xff0…

Element-Ui定制Dropdown组件

1.效果 说明&#xff1a;移入后新增图标&#xff0c;然后移入后图标变色。当然大家可以想到用mouseover移入事件来实现移入颜色的变化&#xff0c;但是在使用Dropdown组件的时候&#xff0c;不支持这种写法。因此采用了原生的遍历对象的形式&#xff0c;为每一个item对象绑定鼠…

通过WinCC基本功能实现批次查询及批次报表

谈到WinCC中的批次数据处理和批次报表&#xff0c;也许有人会想到PM-Quality这款专业的批次报表软件。但如果你的银子有限&#xff0c;批次报表要求又比较简单&#xff0c;不妨看看此文。 —《通过 WinCC 基本功能实现批次数据过滤查询以及打印批次数据报表》 实现的功能描述 …

一维数组的定义

什么是数组&#xff1f; &#xff08;1&#xff09;数组是具有一定顺序关系的若干变量的集合&#xff0c;组成数组的各个变量统称为数组的元素 &#xff08;2&#xff09;数组中的各元素的数据类型要求相同&#xff0c;用数组名和下标确定&#xff0c;数组可以是一维的&#…

无经验小白开发一个 JavaWeb项目,需要注意哪些要点?

大家好我是咕噜铁蛋 &#xff0c;我收集了许多来自互联网的宝贵资源&#xff0c;这些资源帮助我学习和理解如何从零开始开发JavaWeb项目。今天&#xff0c;我将与大家分享一些关键的要点&#xff0c;包括项目规划、技术选型、数据库设计、代码编写和测试部署等。如果你有任何问…

大数据存储技术(3)—— HBase分布式数据库

目录 一、HBase简介 &#xff08;一&#xff09;概念 &#xff08;二&#xff09;特点 &#xff08;三&#xff09;HBase架构 二、HBase原理 &#xff08;一&#xff09;读流程 &#xff08;二&#xff09;写流程 &#xff08;三&#xff09;数据 flush 过程 &#xf…

Mysql数据库 19.Mysql 锁

MySQL锁 锁&#xff1a;锁是计算机用以协调多个进程间并发访问同一共享资源的一种机制&#xff0c;在数据库中&#xff0c;除传统的计算资源&#xff08;CPU、RAM、I/O&#xff09;的争用以外&#xff0c;数据也是一种供许多用户共享的资源&#xff0c;如何保证数据并发访问的一…

【MySQL备份】MySQL备份工具-MyDumper

目录 什么是MyDumper MyDumper优势有哪些 如何安装MyDumper 参数解释 1 mydumper参数解释 备份流程 一致性快照如何工作&#xff1f; 如何排除&#xff08;或包含&#xff09;数据库&#xff1f; 输出文件 Metadata文件 ​编辑 表数据 文件 表结构 文件 建库文件…

关于uview-ui的u-tabs标签滑块不居中的问题

在uniapp中&#xff0c;打开文件 uni_modules/uview-ui/components/u-tabs/u-tabs.vue 然后在style中添加以下代码即可 /deep/ .u-tabs__wrapper__nav__line {left: 18rpx; } 之前效果图&#xff1a; 之后效果图&#xff1a; 注意&#xff0c;代码中的18rpx需要自行调整