Springboot整合Zookeeper分布式组件实例
一、Zookeeper概述
1.1 Zookeeper的定义
Zookeeper是一个开源的分布式协调服务,主要用于分布式应用程序中的协调管理。它由Apache软件基金会维护,是Hadoop生态系统中的重要成员。Zookeeper提供了一个高效且可靠的分布式锁服务,以及群集管理功能,在分布式系统中起到了“守护神”的作用。
1.2 Zookeeper的核心理念
Zookeeper基于以下关键概念构建:
-
数据模型:Zookeeper的数据模型是一个层次结构,这个层次类似于一个文件系统,与liunx的文件系统类似,整体可以看作为一棵树。它由节点组成,节点也成为ZNode,每个节点可以有子节点。节点可以存储数据,但数据尺寸有限默认存储为1MB的数据。
-
节点(ZNode):Zookeeper中的每个数据单元称为ZNode。ZNode有两种类型:持久(Persistent)和临时(Ephemeral)。持久节点在客户端断开连接后仍存在,而临时节点在客户端断开连接后会被自动删除。
-
观察者(Watcher):客户端可以在ZNode上设置观察者,当ZNode的数据或子节点发生变化时,Watcher会通知对应的客户端。
-
有序性(Orderliness):Zookeeper通过全局顺序来确保所有操作的顺序一致。
-
数据一致性 :每个server保存一份相同的数据拷贝,客户端无论请求到被集群中哪个server处理,得到的数据都是一致的。
-
集群服务:在Zookeeper集群服务由一个领导者(leader),多个跟随者(follower)组成的集群。领导者(leader)负责进行投票的发起和决议,更新集群服务状态。跟随者用于接收客户请求并向客户端返回结果,在选举Leader过程中参与投票。集群中只要有半数以上节点存活,Zookeeper集群就能正常服务。
二、Zookeeper的应用场景
2.1 分布式锁服务
Zookeeper能够非常有效地实现分布式锁。这在需要同步或并发控制的分布式系统中尤为重要。通过利用Zookeeper的临时ZNode特性,可以实现锁的自动释放,防止死锁。
2.2 统一配置管理
在分布式系统中,应用程序的配置管理成为一个复杂的问题。Zookeeper提供了一种集中式管理配置的方式,所有的配置文件可以存储在Zookeeper中,并且可以动态更新。当配置变化时,Zookeeper可以通知到所有客户端,从而使应用程序能够立即响应变化。
2.3 命名服务
Zookeeper可以作为分布式系统的命名服务,通过维护名称和元数据的映射关系,提供高效的名称解析能力。
2.4 集群管理
Zookeeper能够监控集群中各个节点的状态,决定节点是否健康,而节点的加入和离开能够动态调整。
三、Zookeeper的安全管理操作方法
3.1 基本安全措施
-
验证(Authentication):Zookeeper支持基于客户端和服务器之间的认证机制。通过设置用户和密码,可以限制对ZNode的访问。
3.1.1认证方式
- world:默认方式,开放的权限,意解为全世界都能随意访问。
- auth:已经授权且认证通过的用户才可以访问。
- digest:用户名:密码方式认证,实际业务开发中最常用的方式。
- IP白名单:授权指定的Ip地址,和指定的权限点,控制访问。
-
ACL(Access Control Lists):通过设定ACL,能够控制ZNode的读写权限。ACL规则可以根据不同的需求设定,如只读、完全控制等。
3.1.2 ACL授权流程
- 添加认证用户
addauth digest 用户名:密码
- 设置权限
setAcl /path auth:用户名:密码:权限
- 查看Acl设置
getAcl /path
完整的操作如下代码
-- 添加授权用户
[zk: localhost:2181] addauth digest user1:123456
-- 创建节点
[zk: localhost:2181] create /testNode testNode
-- 节点授权
[zk: localhost:2181] setAcl /testNode auth:user1:123456:cdrwa
-- 查看授权
[zk: localhost:2181] getAcl /testNode
3.2 数据加密
在Zookeeper的配置文件中,可以启用数据传输加密(例如SSL/TLS)来保证数据在网络传输中的安全性。
3.3 安全配置示例
# zookeeper configuration
authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
requireClientAuthScheme=sasl
digest.authenticationHandler.sasl.clientAllowedProtocols=GSSAPI:CRAM-MD5
四、Zookeeper与Spring Boot 2的整合
4.1 引入依赖
在Spring Boot 2项目中,首先需要引入Curator依赖,这是用于简化Zookeeper操作的一个高层次API。Curator框架在Zookeeper原生API接口上进行二次包装。提供ZooKeeper各种应用场景:比如:分布式锁服务、集群领导选举、共享计数器、缓存机制、分布式队列等API封装。
<dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>2.12.0</version>
</dependency>
<dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>2.12.0</version>
</dependency>
<dependency><groupId>org.apache.curator</groupId><artifactId>curator-client</artifactId><version>2.12.0</version>
</dependency>
4.2 Springboot项目yml配置
在application.properties
中,配置Zookeeper的连接信息:
zoo:keeper:#开启标志enabled: true#服务器地址server: 127.0.0.1:2181#命名空间,被称为ZNodenamespace: testNode#权限控制,加密digest: user1:123456#会话超时时间sessionTimeoutMs: 3000#连接超时时间connectionTimeoutMs: 60000#最大重试次数maxRetries: 2#初始休眠时间baseSleepTimeMs: 1000
4.3 编写配置类
编写Zookeeper配置类,用于初始化Zookeeper客户端:
@Configuration
public class ZookeeperConfig {private static final Logger LOGGER = LoggerFactory.getLogger(ZookeeperConfig.class) ;//注入Zookeeper配置文件类,用于获取yml的配置项值@Autowiredprivate ZookeeperParam zookeeperParam ;private static CuratorFramework client = null ;/*** 初始化*/@PostConstructpublic void init (){//重试策略,初试时间1秒,重试10次RetryPolicy policy = new ExponentialBackoffRetry(zookeeperParam.getBaseSleepTimeMs(),zookeeperParam.getMaxRetries());//通过工厂创建Curatorclient = CuratorFrameworkFactory.builder().connectString(zookeeperParam.getServer()) //链接的服务的地址.authorization("digest",zookeeperParam.getDigest().getBytes()) //认证方式.connectionTimeoutMs(zookeeperParam.getConnectionTimeoutMs()).sessionTimeoutMs(zookeeperParam.getSessionTimeoutMs()).retryPolicy(policy).build();//开启连接client.start();LOGGER.info("zookeeper 初始化完成...");}public static CuratorFramework getClient (){return client ;}public static void closeClient (){if (client != null){client.close();}}
}
4.4 示例代码
示例代码展示如何在Spring Boot 2项目中使用Zookeeper:
Zookeeper接口类
public interface ZookeeperService {/*** 判断节点是否存在*/boolean isExistNode (final String path) ;/*** 创建节点*/void createNode (CreateMode mode,String path ) ;/*** 设置节点数据*/void setNodeData (String path, String nodeData) ;/*** 创建节点*/void createNodeAndData (CreateMode mode, String path , String nodeData) ;/*** 获取节点数据*/String getNodeData (String path) ;/*** 获取节点下数据*/List<String> getNodeChild (String path) ;/*** 是否递归删除节点*/void deleteNode (String path,Boolean recursive) ;/*** 获取读写锁*/InterProcessReadWriteLock getReadWriteLock (String path) ;
}
Zookeeper接口实现类IMPL
@Service
public class ZookeeperServiceImpl implements ZookeeperService {private static final Logger LOGGER = LoggerFactory.getLogger(ZookeeperServiceImpl.class);@Overridepublic boolean isExistNode(String path) {CuratorFramework client = ZookeeperConfig.getClient();client.sync() ;try {Stat stat = client.checkExists().forPath(path);return client.checkExists().forPath(path) != null;} catch (Exception e) {LOGGER.error("isExistNode error...", e);e.printStackTrace();}return false;}@Overridepublic void createNode(CreateMode mode, String path) {CuratorFramework client = ZookeeperConfig.getClient() ;try {// 递归创建所需父节点client.create().creatingParentsIfNeeded().withMode(mode).forPath(path);} catch (Exception e) {LOGGER.error("createNode error...", e);e.printStackTrace();}}@Overridepublic void setNodeData(String path, String nodeData) {CuratorFramework client = ZookeeperConfig.getClient() ;try {// 设置节点数据client.setData().forPath(path, nodeData.getBytes("UTF-8"));} catch (Exception e) {LOGGER.error("setNodeData error...", e);e.printStackTrace();}}@Overridepublic void createNodeAndData(CreateMode mode, String path, String nodeData) {CuratorFramework client = ZookeeperConfig.getClient() ;try {// 创建节点,关联数据client.create().creatingParentsIfNeeded().withMode(mode).forPath(path,nodeData.getBytes("UTF-8"));} catch (Exception e) {LOGGER.error("createNode error...", e);e.printStackTrace();}}@Overridepublic String getNodeData(String path) {CuratorFramework client = ZookeeperConfig.getClient() ;try {// 数据读取和转换byte[] dataByte = client.getData().forPath(path) ;String data = new String(dataByte,"UTF-8") ;if (StringUtils.isNotEmpty(data)){return data ;}}catch (Exception e) {LOGGER.error("getNodeData error...", e);e.printStackTrace();}return null;}@Overridepublic List<String> getNodeChild(String path) {CuratorFramework client = ZookeeperConfig.getClient() ;List<String> nodeChildDataList = new ArrayList<>();try {// 节点下数据集nodeChildDataList = client.getChildren().forPath(path);} catch (Exception e) {LOGGER.error("getNodeChild error...", e);e.printStackTrace();}return nodeChildDataList;}@Overridepublic void deleteNode(String path, Boolean recursive) {CuratorFramework client = ZookeeperConfig.getClient() ;try {if(recursive) {// 递归删除节点client.delete().guaranteed().deletingChildrenIfNeeded().forPath(path);} else {// 删除单个节点client.delete().guaranteed().forPath(path);}} catch (Exception e) {LOGGER.error("deleteNode error...", e);e.printStackTrace();}}@Overridepublic InterProcessReadWriteLock getReadWriteLock(String path) {CuratorFramework client = ZookeeperConfig.getClient() ;// 写锁互斥、读写互斥InterProcessReadWriteLock readWriteLock = new InterProcessReadWriteLock(client, path);return readWriteLock ;}
}
Zookeeper业务API场景使用
@Api("Zookeeper接口使用实例")
@RestController
public class ZookeeperController {@Autowiredprivate ZookeeperService zookeeperService ;@ApiOperation(value="查询节点数据")@GetMapping("/getNodeData")public HttpResult getNodeData (String path) {return HttpResult.create(HttpStatus.SUCCESS,zookeeperService.getNodeData(path));}@ApiOperation(value="判断节点是否存在")@GetMapping("/isExistNode")public HttpResult isExistNode (final String path){return HttpResult.create(HttpStatus.SUCCESS,zookeeperService.isExistNode(path));}@ApiOperation(value="创建节点")@GetMapping("/createNode")public HttpResult createNode (CreateMode mode, String path ){zookeeperService.createNode(mode,path) ;return HttpResult.create(HttpStatus.SUCCESS);}@ApiOperation(value="设置节点数据")@GetMapping("/setNodeData")public HttpResult setNodeData (String path, String nodeData) {zookeeperService.setNodeData(path,nodeData) ;return HttpResult.create(HttpStatus.SUCCESS);}@ApiOperation(value="创建并设置节点数据")@GetMapping("/createNodeAndData")public HttpResult createNodeAndData (CreateMode mode, String path , String nodeData){zookeeperService.createNodeAndData(mode,path,nodeData) ;return HttpResult.create(HttpStatus.SUCCESS);}@ApiOperation(value="递归获取节点数据")@GetMapping("/getNodeChild")public HttpResult getNodeChild (String path) {return HttpResult.create(HttpStatus.SUCCESS,zookeeperService.getNodeChild(path));}@ApiOperation(value="是否递归删除节点")@GetMapping("/deleteNode")public HttpResult deleteNode (String path,Boolean recursive) {zookeeperService.deleteNode(path,recursive) ;return HttpResult.create(HttpStatus.SUCCESS);}
}
接口返回HttpResult统一类
import com.fasterxml.jackson.annotation.JsonInclude;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;/*** @author Lqzhang* @date 2020/5/19*/
@Data
@ApiModel(value = "HttpResult", description = "统一返回数据结构")
public class HttpResult<T> {@ApiModelProperty(value = "返回状态码")private Integer code;@ApiModelProperty(value = "返回信息")private String msg;@ApiModelProperty(value = "返回数据")@JsonInclude(value = JsonInclude.Include.NON_NULL)private T data;public static <E> HttpResult<E> create(HttpStatus httpStatus) {HttpResult<E> httpResult = new HttpResult<>();httpResult.setCode(httpStatus.getCode());httpResult.setMsg(httpStatus.getMessage());return httpResult;}public static <E> HttpResult<E> create(HttpStatus httpStatus, String msg) {HttpResult<E> httpResult = new HttpResult<>();httpResult.setCode(httpStatus.getCode());httpResult.setMsg(msg);return httpResult;}public static <E> HttpResult<E> create(HttpStatus httpStatus, E data) {HttpResult<E> httpResult = new HttpResult<>();httpResult.setCode(httpStatus.getCode());httpResult.setMsg(httpStatus.getMessage());httpResult.setData(data);return httpResult;}public static <E> HttpResult<E> create(HttpStatus httpStatus, String msg, E data) {HttpResult<E> httpResult = new HttpResult<>();httpResult.setCode(httpStatus.getCode());httpResult.setMsg(msg);httpResult.setData(data);return httpResult;}public static <E> HttpResult<E> create(Integer code, String msg, E data) {HttpResult<E> httpResult = new HttpResult<>();httpResult.setCode(code);httpResult.setMsg(msg);httpResult.setData(data);return httpResult;}public static <E> HttpResult<E> success() {return success(null);}public static <E> HttpResult<E> success(E data) {HttpResult<E> httpResult = new HttpResult<>();httpResult.setCode(200);httpResult.setMsg("操作成功");httpResult.setData(data);return httpResult;}public static <E> HttpResult<E> fail() {return fail(HttpStatus.FAIL.getMessage());}public static <E> HttpResult<E> fail(String message) {HttpResult<E> httpResult = new HttpResult<>();httpResult.setCode(HttpStatus.FAIL.getCode());httpResult.setMsg(message);return httpResult;}
}
/*** 请求结果状态枚举常量类** @author Lqzhang*/
public enum HttpStatus {SUCCESS(200, "请求成功"),NO_DATA(201, "没有查询到对应的数据"),FAIL(203, "请求异常"),PARAM_ERROR(204, "参数名错误或参数为空,请检查"),NO_LOGIN(205, "没有授权"),SAVE_ERROR(206, "操作失败"),NO_DATA_IN_AUTH(207, "权限范围内没有查询到数据"),ARREARS(208, "账户可用余额已不足,请充值"),UNBOUND_PHONE(210, "用户账户未绑定微信手机"),USER_NOT_EXITS(211, "用户不存在"),PASSWORD_ERROR(212, "密码错误"),TOKEN_EXPIRED(403, "当前登录凭证已失效,请重新登录"),SERVICE_NOT_OPENED(215, "该功能未开通,联系管理员开通使用"),;/*** 状态码*/private int code;/*** 状态信息*/private String message;HttpStatus(int code, String message) {this.code = code;this.message = message;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public int getStatusTypeCode(HttpStatus httpStatus) {return httpStatus.getCode();}public String getStatusTypeMessage(HttpStatus httpStatus) {return httpStatus.getMessage();}public static HttpStatus getStatusTypeByCode(int code) {HttpStatus httpStatus = null;for (HttpStatus status : values()) {if (status.getCode() == code) {httpStatus = status;break;}}return httpStatus;}public static HttpStatus getStatusTypeByMessage(String message) {HttpStatus httpStatus = null;for (HttpStatus status : values()) {if (status.getMessage().equals(message)) {httpStatus = status;break;}}return httpStatus;}}
结论
Zookeeper作为分布式系统中的重要组件,提供了多种功能和强大的协调能力。在实际应用中,可以利用Zookeeper实现分布式锁、统一配置管理、命名服务及集群管理等功能。通过与Spring Boot 2的整合,能更好地在应用中利用Zookeeper这些功能,以提升系统的可用性和可靠性。希望通过本文的介绍,您对Zookeeper有更加深入的了解,并能够在实际项目中加以应用。
相关文章:
![](https://img-blog.csdnimg.cn/direct/71bef768befd4757bf4dbfdc61e8af0d.png)
Springboot整合Zookeeper分布式组件实例
一、Zookeeper概述 1.1 Zookeeper的定义 Zookeeper是一个开源的分布式协调服务,主要用于分布式应用程序中的协调管理。它由Apache软件基金会维护,是Hadoop生态系统中的重要成员。Zookeeper提供了一个高效且可靠的分布式锁服务,以及群集管理…...
![](https://img-blog.csdnimg.cn/direct/2150649fdcee4ac8ab0f2d632c8054f3.png)
Python | 使用Matplotlib生成子图的示例
数据可视化在分析和解释数据的过程中起着举足轻重的作用。Python中的Matplotlib库提供了一个强大的工具包,用于制作各种图表和图表。一个突出的功能是它能够在单个图中生成子图,为以组织良好和结构化的方式呈现数据提供了有价值的工具。使用子图可以同时…...
![](https://www.ngui.cc/images/no-images.jpg)
云原生巡检监控报告
一、巡检概述 本次云原生巡检工作主要围绕云原生平台的稳定性、安全性以及性能进行,通过对平台资源的监控、日志分析以及安全扫描,发现了一些潜在的问题和隐患。巡检工作采用了自动化工具和人工分析相结合的方式,确保了巡检结果的准确性和全…...
![](https://www.ngui.cc/images/no-images.jpg)
Linux系统编程——部分内容补充
回顾 进程 内核相关数据结构 代码和数据,一个可执行程序加载到内存变成进程,不仅仅是把代码和数据加载进去就完事了,得“先描述,再组织”,每个进程都有内核数据结构,地址空间,进程相关页表&a…...
![](https://img-blog.csdnimg.cn/direct/4b6f38de50454b96bd84e219aadc8038.png)
数学建模基础:非线性模型
目录 前言 一、非线性方程组 二、非线性规划 三、微分方程模型 四、非线性模型的应用 五、实例示范:传染病传播模型 实例总结 五、总结 前言 非线性模型用于描述变量之间的非线性关系,相比线性模型,其数学形式更为复杂,但…...
![](https://img-blog.csdnimg.cn/direct/5605bcf5b94047f3bca5c02338f2eb62.png)
Kotlin 语言基础学习
什么是Kotlin ? Kotiln翻译为中文是:靠他灵。它是由JetBrains 这家公司开发的,JetBrains 是一家编译器软件起家的,例如常用的WebStorm、IntelliJ IDEA等软件。 Kotlin官网 JetBrains 官网 Kotlin 语言目前的现状: 目前Android 已将Kotlin 作为官方开发语言。 Spring 框…...
![](https://www.ngui.cc/images/no-images.jpg)
Kafka 之 KRaft —— 配置、存储工具、部署注意事项、缺失的特性
目录 一. 前言 二. 配置(Configuration) 2.1. 处理者角色(Process Roles) 2.2. 控制器(controller) 2.3. 存储工具(Storage Tool) 2.4. 调试(Debugging)…...
![](https://img-blog.csdnimg.cn/direct/21b400ff81334deeb8988215c48117ef.png)
专业和学校到底怎么选,兴趣和知名度到底哪个重要?
前言 2024高考已经落下帷幕,再过不久就到了激动人心的查分和填报志愿的时刻,在那天到来,小伙伴们就要根据自己的分数选取院校和专业,接下来我就以参加22年(破防年)河南高考的大二生来讲述一下我自己对于如何选取院校和专业的看法以…...
![](https://www.ngui.cc/images/no-images.jpg)
【MySQL】数据库
数据库概述 【MySQL】数据库概述-CSDN博客 数据库基本操作 【MySQL】数据库基本操作-CSDN博客 数据表基本操作 【MySQL】数据表基本操作-CSDN博客 约束 【MySQL】约束-CSDN博客 基本增删改查 【MySQL】基本增删改查-CSDN博客 多表操作 【MySQL】多表操作-CSDN博客 视图 …...
![](https://img-blog.csdnimg.cn/direct/3d5647332ae342d5a4cfcb83aa651e7e.jpeg)
D111FCE01LC2NB70带流量调节派克比例阀
D111FCE01LC2NB70带流量调节派克比例阀 派克比例阀:由于采用(秉圣135陈工6653询3053)电液混合控制技术,响应速度更快、精度更高、控制更平稳。同时,由于采用高质量的材料制造,具有较高的承压能力和抗磨损性…...
![](https://img-blog.csdnimg.cn/direct/5ce266e43c2349e2aa0f4565926d6310.png)
buuctf-findKey
exe文件 运行发现这个窗口,没有任何消息 32位 进入字符串就发现了flag{ 左边红色代表没有F5成功 我们再编译一下(选中红色的全部按p) LRESULT __stdcall sub_401640(HWND hWndParent, UINT Msg, WPARAM wParam, LPARAM lParam) {int v5; // eaxsize_t v6; // eaxDWORD v7; /…...
![](https://www.ngui.cc/images/no-images.jpg)
针对oracle系列数据库慢数据量大的问题
-- 确保索引存在 create index idx_risk_assessment_hazard on risk_assessment_hazard(data_time, perception_id); create index idx_risk_dispose_base_info on risk_dispose_base_info(perception_id); -- 使用并行查询和with子句进行优化 explain plan for with t2 as (se…...
![](https://img-blog.csdnimg.cn/direct/ca1ef6c1500e402db8c79961d316839a.png)
Nginx-Rewrite
1、Rewrite的定义 rewrite功能就是使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现url重写以及重定向。rewrite只能放在 server { }, location { }, if { }中,并且只能对域名后边的除去传递的参数外的字符串起作用。 例如location…...
![](https://img-blog.csdnimg.cn/direct/ed3c754282384a789faa7d7b4b894b7f.png)
2024 年 Python 基于 Kimi 智能助手 Moonshot Ai 模型搭建微信机器人(更新中)
注册 Kimi 开放平台 Kimi:https://www.moonshot.cn/ Kimi智能助手是北京月之暗面科技有限公司(Moonshot AI)于2023年10月9日推出的一款人工智能助手,主要为用户提供高效、便捷的信息服务。它具备多项强大功能,包括多…...
![](https://img-blog.csdnimg.cn/direct/270256cc2a6648f2906f4e919b5e11aa.png)
关于接口多态,何时使用接口名创建对象?何时使用子类创建对象?
接口创建对象只能创建他的实现类,所以会出现两种创建方式: 1、接口 对象名 new 类名 2、子类对象 对象名 new 类名 举个例子,swimming是一个接口,flog是他的一个实现类,重写了swimming的eat()方法 子类对象 对象名…...
![](https://img-blog.csdnimg.cn/img_convert/eb23e3fbbd7e7751e216e02267efbc54.jpeg)
短视频热恋进行时:成都柏煜文化传媒有限公司
短视频热恋进行时:情感与创意的碰撞与融合 在数字时代的浪潮中,短视频以其独特的魅力,成为了当代人表达情感、分享生活的新宠。它如同一个浓缩的时空胶囊,将那些瞬间的美好、感人的故事、创意的火花,封装在短短几十秒…...
![](https://img-blog.csdnimg.cn/direct/50e1917d0afd4966bac95ee0288c6e2e.png)
springBoot多数据源使用、配置
又参加了一个新的项目,虽然是去年做的项目,拿来复用改造,但是也学到了很多。这个项目会用到其他项目的数据,如果调用他们的接口取数据,我还是觉得太麻烦了。打算直接配置多数据源。 然后去另一个数据库系统中取出数据…...
![](https://img-blog.csdnimg.cn/img_convert/400981c590bd0740ab37179c5b5f74be.png)
打破安全设备孤岛,多源威胁检测与响应(XDR)如何构建一体化安全防线
在数字化和信息化迅猛发展的当下,安全设备孤岛现象成为网络安全治理中的一大挑战。在多元化的市场环境中,不同厂商的安全设备因数据格式与系统兼容性的差异,导致信息流通受阻、共享困难,形成孤立的安全防线。 安全设备孤岛现象不仅…...
![](https://img-blog.csdnimg.cn/direct/c8e374ee7945461caac7ff0751bdd38c.png)
Android SurfaceFlinger——概述(一)
一、基础介绍 SurfaceFlinger 是 Android 系统中的一个关键组件,负责管理屏幕显示的合成和渲染。 服务角色:SurfaceFlinger 作为一个系统服务独立运行,它不依赖于任何应用程序进程,而是由系统启动并持续运行。窗口管理:…...
![](https://img-blog.csdnimg.cn/direct/88925f8383e342ac966aa34dd4610671.jpeg)
工业 web4.0,UI 风格令人赞叹
工业 web4.0,UI 风格令人赞叹...
![](https://img-blog.csdnimg.cn/direct/8939d548a4e14cf79861d11af83ee11b.png)
HarmonyOS 角落里的知识 —— 状态管理
一、前言 在探索 HarmonyOS 的过程中,我们发现了许多有趣且实用的功能和特性。有些总是在不经意间或者触类旁通的找到。或者是某些开发痛点。其中,状态管理是ArkUI开发非常核心的一个东西,我们进行了大量的使用和测试遇到了许多奇奇怪怪的问…...
![](https://www.ngui.cc/images/no-images.jpg)
TDengine数据迁移
前言 taosdump 是一个支持从运行中的 TDengine 集群备份数据并将备份的数据恢复到相同或另一个运行中的 TDengine 集群中的工具应用程序。 taosdump 可以用数据库、超级表或普通表作为逻辑数据单元进行备份,也可以对数据库、超级 表和普通表中指定时间段内的数据记录…...
![](https://img-blog.csdnimg.cn/direct/2f46e040403c495b884a26d3069f5db6.png)
使用ZIP包安装MySQL及配置教程
在本教程中,我们将指导您完成使用ZIP包安装MySQL的过程,并对配置文件进行必要的修改,以及解决可能遇到的问题。本示例以MySQL 5.7.44为例,但步骤同样适用于其他版本如MySQL 8.3.0等。请根据实际需要选择适合的版本下载:…...
![](https://www.ngui.cc/images/no-images.jpg)
Java基础入门day64
day64 web项目 数据库设计 在小米商城主页,主要的内容是多种商品类型的展示,分别有手机,智能穿戴,笔记本平板,家电,生活电器,厨房电器,智能家具等大的七个分类,根据这个…...
![](https://img-blog.csdnimg.cn/direct/e54ccb5d3e5747a59db0f699863077e8.jpeg)
高德地图轨迹回放/轨迹播放
前言 本篇文章主要介绍高德地图的轨迹回放或播放的实现过程,是基于vue2实现的功能,同时做一些改动也是能够适配vue3的。其中播放条是用的是element UI中的el-slider组件,包括使用到的图标也是element UI自带的。可以实现轨迹的播放、暂停、停…...
![](https://img-blog.csdnimg.cn/direct/853474a62f4347a68dc53fe3c8067724.jpeg#pic_center)
像素、像素密度、位图和矢量图
像素、像素密度、位图和矢量图 像素 -- 图像元素pt分辨率ppidpi 点阵图 - bitmap常见的类型 矢量图点阵图 vs 矢量图参考小结 像素、矢量图等概念在前端开发中经常遇到,这里做一个简单的梳理。 像素 – 图像元素 做前端开发的经常遇到它。像素是图像的最小单位&am…...
![](https://img-blog.csdnimg.cn/direct/e7b3f326e07641f598110addf152a7ab.png)
第二证券股市资讯:昨夜!全球新“股王”诞生
昨晚,英伟达成全球市值榜首公司。 当地时间6月18日,美股三大指数小幅收高,标普500指数与纳指再创前史新高。标普500指数涨0.25%,道指涨0.15%,纳指涨0.03%。 AI热潮推动英伟达大涨,市值逾越微软、苹果&…...
![](https://img-blog.csdnimg.cn/direct/ceb0e268eefa4acea70860f6802f826e.jpeg)
自动水位雨量站:用于水库防汛预警
TH-SW2自动水位雨量站是一种现代化的监测设备,主要用于水库等水域的防汛预警系统。它通过集成水位和雨量监测功能,为水库的管理和调度提供实时、准确的数据支持。 工作原理: 自动水位雨量站通过内置的水位计和雨量计实时监测水库的水位变化和…...
![](https://img-blog.csdnimg.cn/direct/e2007ed77c374b21bcd08f3af4cc6d98.png)
苍穹外卖---新增员工(P16-P20)
一、需求分析和设计 (1)产品原型 一般在做需求分析时,往往都是对照着产品原型进行分析,因为产品原型比较直观,便于我们理解业务。后台系统中可以管理员工信息,通过新增员工来添加后台系统用户。 新增员工…...
![](https://img-blog.csdnimg.cn/direct/c5c96fe5ad93462d9398410bdab19520.png#pic_center)
Windows10 利用QT搭建SOEM开发环境
文章目录 一. SOEM库简介二. 安装WinPcap三. SOEM(1.4)库安装(1) 编译32位库(2) 编译64位库 四. 运行SOEM示例代码五. WIN10下利用QT构建SOEM开发环境 一. SOEM库简介 SOEM(Scalable Open EtherCAT Master 或 Simple Open EtherCAT Master)是一个开源的…...
![](/images/no-images.jpg)
网站建设实训日记/北京全网营销推广公司
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼sqlplus 运行脚本prvtlmpg.plb 报错,请问各位大神有什么解决方法SQL> prvtlmpg.plbOracle GoldenGate Workaround prvtlmpgThis script provides a temporary workaround for bug 17030189.It is strongly recommend…...
![](/images/no-images.jpg)
网站制作网页版/百度排名优化软件
一、Java语言特点Java是一种简单、面向对象、分布式、易读、鲁棒、安全、结构明晰、可移植、高性能、多线程、动态的语言。面向对象(继承、封装、多态)一次编译,到处运行(JVM实现跨平台运行)可靠性安全性支持多线程(对比C没有内置多线程机制)etc...二、Java为什么不…...
![](/images/no-images.jpg)
amazon wordpress/沈阳专业网站seo推广
当两个人的感情破裂之后,可能会走向离婚的地步,这时是需要处理财产问题的,比如说房产怎么分配,谁获得产权,如何补偿对方等等,那么民法典离婚怎么判决无产权证房产呢?小编已经整理了如下的内容供大家做法律…...
![](/images/no-images.jpg)
邢台做网站多少钱/seo站长
PHP语言基础》》》了解PHP的标记分隔》》》了解PHP的注释种类》》》了解PHP的数据类型》》》了解PHP的常量变量》》》了解PHP运算符》》》了解PHP表达式》》》了解PHP函数》》》了解PHP的编码规范1、PHP标记风格XML风格<?phpecho "这是XML风格的标记";…...
大学生做网站兼职/免费seo快速排名工具
一、问题: cmd输入javac显示不是内部或外部文件,如下图 二、解决方法: 我搜了网上的方法,重启cmd,并无卵用。 然后有说环境变量里系统变量的JAVA_HOME,CLASSPATH设置错误的。我检查了一遍也没有问题。 还有说什…...
![](https://img-blog.csdnimg.cn/20190808114948809.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQyMzYzMDkw,size_16,color_FFFFFF,t_70)
重庆自助建站系统哪家好/搜索百度
1 container 顾名思义container是栅格系统最外层的class,直接被container包裹的只能是row这个class。需要注意的是container自带左右各15px padding值,这样container与浏览器窗口之间就存在一定距离。 2 row row指container的一行,每行理想…...