前端技术
HTML
CSS
Javascript
前端框架和UI库
VUE
ReactJS
AngularJS
JQuery
NodeJS
JSON
Element-UI
Bootstrap
Material UI
服务端和客户端
Java
Python
PHP
Golang
Scala
Kotlin
Groovy
Ruby
Lua
.net
c#
c++
后端WEB和工程框架
SpringBoot
SpringCloud
Struts2
MyBatis
Hibernate
Tornado
Beego
Go-Spring
Go Gin
Go Iris
Dubbo
HessianRPC
Maven
Gradle
数据库
MySQL
Oracle
Mongo
中间件与web容器
Redis
MemCache
Etcd
Cassandra
Kafka
RabbitMQ
RocketMQ
ActiveMQ
Nacos
Consul
Tomcat
Nginx
Netty
大数据技术
Hive
Impala
ClickHouse
DorisDB
Greenplum
PostgreSQL
HBase
Kylin
Hadoop
Apache Pig
ZooKeeper
SeaTunnel
Sqoop
Datax
Flink
Spark
Mahout
数据搜索与日志
ElasticSearch
Apache Lucene
Apache Solr
Kibana
Logstash
数据可视化与OLAP
Apache Atlas
Superset
Saiku
Tesseract
系统与容器
Linux
Shell
Docker
Kubernetes
[prize万能抽奖小工具使用指南]的搜索结果
这里是文章列表。热门标签的颜色随机变换,标签颜色没有特殊含义。
点击某个标签可搜索标签相关的文章。
点击某个标签可搜索标签相关的文章。
Hadoop
...op的开源大数据处理工具现在可火啦!不少公司都把它捧在手心里,广泛应用在自家的各种业务场景里头。这玩意儿就像个大数据处理的超级英雄,在企业界混得风生水起的!在Hadoop这个大家族里,有个不可或缺的角色名叫YARN(也就是“又一个资源协调器”这小名儿),它可是肩负重任的大管家,主要负责给各个任务分配资源、调度工作,可重要着呢!在实际工作中,我们常常会碰到一些让人挠头的小插曲,比如那个烦人的“YARN ResourceManager初始化不成功”的问题。这不,本文就要专门来和大家唠唠这个问题,掰开揉碎了详细分析,并且给出解决它的锦囊妙计。 什么是YARN? 首先,我们需要了解一下什么是YARN。简单来说呢,YARN就是个大管家,它在Hadoop2.x这个大家族里担任着资源管理和作业调度的重要角色。你可以把它想象成一个超级调度员,负责统筹协调所有资源的分配和各种任务的执行顺序,可厉害了!它就像个超级接班人,接手了Hadoop1.x那个老版本里MapReduce任务调度员的活儿,而且表现得更出色,不仅能更高效地给各种任务排兵布阵,还把任务管理这块搞得井井有条。在YARN这个大系统里,Resource Manager(RM)可是个举足轻重的角色。你就把它想象成一个超级大管家吧,它的日常工作就是紧盯着整个集群的资源状况,确保一切都在掌握之中。不仅如此,它还兼职了“调度员”的角色,各种类型的请求都会涌向它,然后由它来灵活调配、合理分配给各个部分去执行。 YARN ResourceManager初始化失败的原因 当我们运行一个Hadoop应用时,YARN ResourceManager是最先启动的服务。如果出现“YARN ResourceManager初始化失败”的错误,通常会有很多种原因导致。下面我们就来一一剖析一下。 1. 集群资源不足 当集群的物理资源不足时,例如CPU、内存等硬件资源紧张,就可能导致YARN ResourceManager无法正常初始化。此时需要考虑增加集群资源,例如增加服务器数量,升级硬件设备等。 2. YARN配置文件错误 YARN的运行依赖于一系列的配置文件,包括conf/hadoop-env.sh、core-site.xml、mapred-site.xml、yarn-site.xml等。要是这些配置文件里头有语法错误,或者设置得不太合理,就可能导致YARN ResourceManager启动时栽跟头,初始化失败。此时需要检查并修复配置文件。 3. YARN环境变量设置不当 YARN的运行还需要一些环境变量的支持,例如JAVA_HOME、HADOOP_HOME等。如果这些环境变量设置不当,也会导致YARN ResourceManager初始化失败。此时需要检查并设置正确的环境变量。 4. YARN服务未正确启动 在YARN环境中,还需要启动一些辅助服务,例如NameNode、DataNode、Zookeeper等。如果这些服务未正确启动,也会导致YARN ResourceManager初始化失败。此时需要检查并确保所有服务都已正确启动。 如何解决“YARN ResourceManager初始化失败”? 了解了问题的原因后,接下来就是如何解决问题。根据上述提到的各种可能的原因,我们可以采取以下几种方法进行尝试: 1. 增加集群资源 对于因为集群资源不足而导致的问题,最直接的解决办法就是增加集群资源。这可以通过添加新的服务器,或者升级现有的服务器硬件等方式实现。 2. 修复配置文件 对于因为配置文件错误而导致的问题,我们需要仔细检查所有的配置文件,找出错误的地方并进行修复。同时,咱也得留意一下,改动配置文件这事儿,就像动了机器的小神经,可能会带来些意想不到的“副作用”。所以呢,在动手修改前,最好先做个全面体检——也就是充分测试啦,再给原来的文件留个安全备份,这样心里才更有底嘛。 3. 设置正确的环境变量 对于因为环境变量设置不当而导致的问题,我们需要检查并设置正确的环境变量。如果你不清楚环境变量到底该怎么设置,别担心,这里有两个实用的解决办法。首先呢,你可以翻阅一下Hadoop官方网站的官方文档,那里面通常会有详尽的指导步骤;其次,你也可以尝试在互联网上搜一搜相关的教程或者攻略,网上有很多热心网友分享的经验,总有一款适合你。 4. 启动辅助服务 对于因为辅助服务未正确启动而导致的问题,我们需要检查并确保所有服务都已正确启动。要是服务启动碰到状况了,不妨翻翻相关的文档资料,或者找专业的高手来帮帮忙。 总结 总的来说,解决“YARN ResourceManager初始化失败”这个问题需要我们具备一定的专业知识和技能。但是,只要我们有足够多的耐心和敏锐的观察力,就可以按照上面提到的办法,一步一步地把各种可能性都排查个遍,最后稳稳地找到那个真正能解决问题的好法子。最后,我想说的是,虽然这是一个比较棘手的问题,但我们只要有足够的信心和毅力,就一定能迎刃而解!
2024-01-17 21:49:06
568
青山绿水-t
Beego
...的重要性不容小觑!在使用Beego框架时,我们怎么才能把数据库连接池调校到最佳状态呢?别急,本文会手把手、从零开始,一步步带你揭开这个秘密,保证让你明明白白了解个透彻。 二、为什么要使用数据库连接池? 当我们频繁地操作数据库时,每次都会创建一个新的数据库连接,这不仅会消耗大量的系统资源,而且还会增加数据库的负载。为了解决这个问题,我们可以使用数据库连接池。数据库连接池,你可以想象成一个数据库连接的“共享小仓库”。它会提前准备一些数据库连接,就像把玩具预先放进收纳箱一样,都存放在这个池子里。当你的程序需要和数据库打交道时,就从这个“池子”里取出一个连接来用,用完之后呢,也不用随手扔掉,而是放回这个池子里,这样下次再需要的时候还能接着用,既方便又高效。这样既可以减少资源的浪费,又可以提高数据库的响应速度。 三、如何在Beego框架下使用数据库连接池? 在Beego框架下,我们可以通过使用开源的database/sql包来使用数据库连接池。首先,我们需要创建一个数据库连接池: go db, err := sql.Open("mysql", "user:password@/dbname") if err != nil { panic(err.Error()) } defer db.Close() pool := &sql.DB{} pool.SetMaxOpenConns(20) pool.SetMaxIdleConns(10) 这段代码首先通过sql.Open()函数打开一个数据库连接,然后定义了一个新的变量pool,类型为sql.DB。接着,我们设置了连接池的最大开放连接数为20,最大空闲连接数为10。 四、如何优化数据库连接池的配置? 在配置数据库连接池时,我们需要注意以下几个方面: 1. 设置合适的最大开放连接数和最大空闲连接数。如果最大允许的开放连接数太多了,就好比是一个接待员同时应付太多的客人,不仅会让整个系统的资源被胡乱消耗掉,变得大手大脚;而另一方面,要是最大空闲连接数设置得不够多,那就像是在高峰期,排队等待服务的顾客太少,结果就是数据库不得不频繁地忙前忙后,响应速度自然也就慢下来了。因此,这两个参数需要根据实际的业务需求来进行调整。 2. 避免频繁地关闭数据库连接。虽然数据库连接池确实是个好东西,能帮咱们有效解决频繁创建和销毁数据库连接这个大麻烦,但你要是总把它当成回收站,频繁地把连接丢回去,那这好经也可能被念歪了,会导致数据库连接资源白白浪费掉。因此,我们应该尽可能地减少数据库连接的释放次数。 3. 定期检查数据库连接池的状态。为了确保数据库连接池运转得顺顺畅畅,我们得定期给它做个全面体检,摸摸底儿,瞅瞅像当前有多少个连接在用啊,又有多少闲着没事儿干的空闲连接等等这些关键指标。这样一来,一旦有啥小毛小病的,咱们就能立马发现并及时处理掉,保证一切正常运行。 五、总结 总的来说,在Beego框架下使用数据库连接池是一个非常有效的方法,可以帮助我们提高数据库的性能。不过呢,咱们也得不断地摸索和捣鼓,才能找到那个最适合自家数据库的连接池配置。就像是找鞋子一样,不试穿几双,怎么能知道哪一双穿起来最合脚、最舒服呢?所以,对于数据库连接池的配置,咱也得慢慢尝试、逐步调整,才能找到最佳的那个“黄金比例”。同时,我们也应该注意保持良好的编程习惯,避免产生无谓的资源浪费。希望这篇内容能实实在在帮到你,让你更溜地掌握和运用Beego框架下的数据库连接池,让数据操作变得更顺手、更高效。
2023-12-11 18:28:55
528
岁月静好-t
Kafka
...,合理规划网络拓扑,使用高速稳定的网络设备,并确保带宽充足。 4.2 调整Kafka客户端配置 根据实际业务需求,调整fetch.min.bytes和fetch.max.bytes等参数,以平衡网络利用率和消费速度。 java // 示例:调整fetch.min.bytes参数 props.put("fetch.min.bytes", "1048576"); // 设置为1MB,避免频繁的小批量请求 4.3 数据压缩与分片 对发送至Kafka的消息进行压缩处理,减少网络传输的数据量;同时考虑适当增加Topic分区数,分散网络负载。 4.4 监控与报警 建立完善的监控体系,实时关注网络延迟指标,一旦发现异常情况,立即触发报警机制,便于及时排查和解决。 5. 结语 面对Kafka服务器与外部系统间的网络延迟问题,我们需要从多个维度进行全面审视和分析,结合具体应用场景采取针对性措施。明白并能切实搞定网络延迟这个问题,那可不仅仅是对咱Kafka集群的稳定性和性能有大大的提升作用,更关键的是,它能像超级能量饮料一样,给整个数据处理流程注入活力,确保其高效顺畅地运作起来。在整个寻找答案、搞定问题的过程中,我们不停地动脑筋、动手尝试、不断改进,这正是技术进步带来的挑战与乐趣所在,让我们的每一次攻关都充满新鲜感和成就感。
2023-10-14 15:41:53
467
寂静森林
Go Iris
...作为一款高性能且易于使用的Web框架,深受开发者喜爱。然而,在与数据库交互的过程中,SQL查询错误是难以避免的问题之一。本文将围绕“Go Iris中的SQL查询错误异常”这一主题,探讨其产生的原因、影响以及如何有效地进行捕获和处理,同时辅以丰富的代码示例,力求让您对这个问题有更深入的理解。 2. SQL查询错误概述 在使用Go Iris构建应用程序并集成数据库操作时,可能会遇到诸如SQL语法错误、数据不存在或权限问题等导致的SQL查询错误。这类异常情况如果不被好好处理,那可不只是会让程序罢工那么简单,它甚至可能泄露一些核心机密,搞得用户体验大打折扣,严重点还可能会对整个系统的安全构成威胁。 3. Go Iris中处理SQL查询错误的方法 让我们通过一段实际的Go Iris代码示例来观察和理解如何优雅地处理SQL查询错误: go package main import ( "github.com/kataras/iris/v12" "github.com/go-sql-driver/mysql" "fmt" ) func main() { app := iris.New() // 假设我们已经配置好了数据库连接 db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/testdb") if err != nil { panic(err.Error()) // 此处处理数据库连接错误 } defer db.Close() // 定义一个HTTP路由处理函数,其中包含SQL查询 app.Get("/users/{id}", func(ctx iris.Context) { id := ctx.Params().Get("id") var user User err = db.QueryRow("SELECT FROM users WHERE id=?", id).Scan(&user.ID, &user.Name, &user.Email) if err != nil { if errors.Is(err, sql.ErrNoRows) { // 处理查询结果为空的情况 ctx.StatusCode(iris.StatusNotFound) ctx.WriteString("User not found.") } else if mysqlErr, ok := err.(mysql.MySQLError); ok { // 对特定的MySQL错误进行判断和处理 ctx.StatusCode(iris.StatusInternalServerError) ctx.WriteString(fmt.Sprintf("MySQL Error: %d - %s", mysqlErr.Number, mysqlErr.Message)) } else { // 其他未知错误,记录日志并返回500状态码 log.Printf("Unexpected error: %v", err) ctx.StatusCode(iris.StatusInternalServerError) ctx.WriteString("Internal Server Error.") } return } // 查询成功,继续处理业务逻辑... // ... }) app.Listen(":8080") } 4. 深入思考与讨论 面对SQL查询错误,我们应该首先确保它被正确捕获并分类处理。就像刚刚提到的例子那样,面对各种不同的错误类型,我们完全能够灵活应对。比如说,可以选择扔出合适的HTTP状态码,让用户一眼就明白是哪里出了岔子;还可以提供一些既友好又贴心的错误提示信息,让人一看就懂;甚至可以细致地记录下每一次错误的详细日志,方便咱们后续顺藤摸瓜,找出问题所在。 在实际项目中,我们不仅要关注错误的处理方式,还要注重设计良好的错误处理策略,例如使用中间件统一处理数据库操作异常,或者在ORM层封装通用的错误处理逻辑等。这些方法不仅能提升代码的可读性和维护性,还能增强系统的稳定性和健壮性。 5. 结语 总之,理解和掌握Go Iris中SQL查询错误的处理方法至关重要。只有当咱们应用程序装上一个聪明的错误处理机制,才能保证在数据库查询出岔子的时候,程序还能稳稳当当地运行。这样一来,咱就能给用户带来更稳定、更靠谱的服务体验啦!在实际编程的过程中,咱们得不断摸爬滚打,积攒经验,像升级打怪一样,一步步完善我们的错误处理招数。这可是我们每一位开发者都该瞄准的方向,努力做到的事儿啊!
2023-08-27 08:51:35
459
月下独酌
NodeJS
...4. 微服务间通信 使用gRPC或HTTP 在微服务架构下,各个服务间的通信至关重要。Node.js 支持多种通信方式,例如 gRPC 和 HTTP。以下是一个使用 HTTP 进行微服务间通信的例子: javascript // 在另一个服务中调用上述用户服务 const axios = require('axios'); app.get('/orders/:userId', async (req, res) => { try { const response = await axios.get(http://user-service:3000/users/${req.params.userId}); const user = response.data; // 假设我们从订单服务获取用户的订单信息 const orders = getOrdersFromDatabase(user.id); res.json(orders); } catch (error) { res.status(500).json({ error: 'Failed to fetch user data' }); } }); 在这个例子中,我们的“订单服务”通过HTTP客户端向“用户服务”发起请求,获取特定用户的详细信息,然后根据用户ID查询订单数据。 5. 总结与思考 利用 Node.js 构建微服务架构,我们可以享受到其带来的快速响应、高并发处理能力以及丰富的生态系统支持。不过呢,每种技术都有它最适合施展拳脚的地方和需要面对的挑战。比如说,当碰到那些特别消耗CPU的任务时,Node.js可能就不是最理想的解决方案了。所以在实际操作中,咱们得瞅准具体的业务需求和技术特性,小心翼翼地掂量一下,看怎样才能恰到好处地用 Node.js 来构建一个既结实又高效的微服务架构。就像是做菜一样,要根据食材和口味来精心调配,才能炒出一盘色香味俱全的好菜。同时,随着我们提供的服务越来越多,咱们不得不面对一些额外的挑战,比如怎么管理好这些服务、如何进行有效的监控、出错了怎么快速恢复这类问题。这些问题就像是我们搭建积木过程中的隐藏关卡,需要我们在构建和完善服务体系的过程中,不断去摸索、去改进、去优化,让整个系统更健壮、更稳定。
2023-02-11 11:17:08
128
风轻云淡
DorisDB
...sql -- 使用EXPLAIN获取查询计划 EXPLAIN SELECT FROM my_table WHERE key = 'some_value'; 通过分析这个执行计划,我们可以了解到查询涉及哪些分区、索引是否被有效利用等关键信息,从而为优化工作找准方向。 3. 优化策略一 合理设计表结构与分区策略 - 列选择性优化:由于DorisDB是列式存储,高选择性的列(即唯一或接近唯一的列)能更好地发挥其优势。例如,对于用户ID这样的列,将其设为主键或构建Bloom Filter索引,可以大幅提升查询性能。 sql -- 创建包含主键的表 CREATE TABLE my_table ( user_id INT PRIMARY KEY, ... ); - 分区设计:根据业务需求和数据分布特性,合理设计分区策略至关重要。比如,咱们可以按照时间段给数据分区,这样做的好处可多了。首先呢,能大大减少需要扫描的数据量,让查询过程不再那么费力;其次,还能巧妙地利用局部性原理,就像你找东西时先从最近的地方找起一样,这样就能显著提升查询的效率,让你的数据查找嗖嗖快! sql -- 按天分区 CREATE TABLE my_table ( ... ) PARTITION BY RANGE (dt) ( PARTITION p20220101 VALUES LESS THAN ("2022-01-02"), PARTITION p20220102 VALUES LESS THAN ("2022-01-03"), ... ); 4. 优化策略二 SQL查询优化 - 避免全表扫描:尽量在WHERE子句中指定明确的过滤条件,利用索引加速查询。例如,假设我们已经为user_id字段创建了索引,那么以下查询会更高效: sql SELECT FROM my_table WHERE user_id = 123; - 减少数据传输量:只查询需要的列,避免使用SELECT 。同时,合理运用聚合函数和分组,避免不必要的计算和排序。 sql -- 只查询特定列,避免全表扫描 SELECT user_name, email FROM my_table WHERE user_id = 123; -- 合理运用GROUP BY和聚合函数 SELECT COUNT(), category FROM my_table GROUP BY category; 5. 优化策略三 系统配置调优 DorisDB提供了丰富的系统参数供用户调整以适应不同场景下的性能需求。比方说,你可以通过调节max_scan_range_length这个参数,来决定每次查询时最多能扫描多少数据范围,就像控制扫地机器人的清扫范围那样。再者,通过巧妙调整那些和内存相关的设置,就能让服务器资源得到充分且高效的利用,就像精心安排储物空间,让每个角落都物尽其用。 6. 结语 优化DorisDB的SQL查询性能是一个综合且持续的过程,需要结合业务特点和数据特征,从表结构设计、查询语句编写到系统配置调整等多个维度着手。每个环节都需细心打磨,才能使DorisDB在大数据洪流中游刃有余,提供更为出色的服务。每一次对DorisDB的优化,都是我们携手这位好伙伴,一起摸爬滚打、不断解锁新技能、共同进步的重要印记。这样一来,咱的数据分析之路也能走得更顺溜,效率嗖嗖往上涨,就像坐上了火箭一样快呢!
2023-05-07 10:47:25
501
繁华落尽
转载文章
...pring Boot使用SpringFactoriesLoader,这个类是Spring Core中的,目的是为了获得Spring Java Configuration,这些配置给了org.springframework.boot.autoconfigure.EnableAutoConfiguration。这样之下,这些调用会收集spring.factories文件下的所有jar包或其它调用的路径和成分到应用的上下文的配置中。除此之了EnableAutoConfiguration,我们可以定义其它的关键接口使用,这些可以自动初始化在启动期间与如下的调用相似: org.springframework.context.ApplicationContextInitializer org.springframework.context.ApplicationListener org.springframework.boot.SpringApplicationRunListener org.springframework.boot.env.PropertySourceLoader org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider org.springframework.test.contex.TestExecutionListener 具有讽刺的是,Spring Boot Starter并不需要依赖Spring Boot的包,因为它编译时间上的依赖。如果我们看DbCountAutoConfiguation类,我们不会看到任何来自org.springframework.book的包。这仅仅的原因是我们的DbCountRunner实现了接口org.sprigframework.boot.CommandLineRunner. 本篇文章为转载内容。原文链接:https://blog.csdn.net/owen_william/article/details/107867328。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-02-10 20:49:04
269
转载
转载文章
...将请求放入请求工厂,使用请求唯一标识seq,用于辨识服务端返回的对应的响应结果RequestFactory.put(request.getSeq(), requestTask);channel.writeAndFlush("hello");//此步是返回response,超时即中断return requestTask.getResponse(request.getTimeOut());} } 其中Request是请求参数,里面有timeout超时时间,以及向服务端请求的参数 public class Request {private static final UUID uuid = UUID.randomUUID();private String seq = uuid.toString();private Object object;private long timeOut;public Object getObject() {return object;}public Request setObject(Object object) {this.object = object;return this;}public String getSeq() {return seq;}public long getTimeOut() {return timeOut;}public Request setTimeOut(long timeOut) {this.timeOut = timeOut;return this;} } 核心的RequestTask类,用于接受服务端的返回结果,超时中断 public class RequestTask {private boolean isDone = Boolean.FALSE;private ReentrantLock lock = new ReentrantLock();private Condition condition = lock.newCondition();Object response;//客户端请求服务端后,立即调用此方法获取返回结果,timeout为超时时间public Object getResponse(long timeOut) {if (!isDone) {try {lock.lock();//此步等待timeout时间,阻塞,时间达到后,自动执行,此步是超时中断的关键步骤if (condition.await(timeOut, TimeUnit.MILLISECONDS)) {if (!isDone) {return new TimeoutException();}return response;} } catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();} }return response;}public RequestTask setResponse(Object response) {lock.lock();try{//此步是客户端收到服务端的响应结果后,写入responsethis.response = response;//并唤起上面方法的阻塞状态,此时阻塞结束,结果正常返回condition.signal();isDone = true;}finally{lock.unlock();}return this;}public boolean isDone() {return isDone;}public RequestTask setDone(boolean done) {isDone = done;return this;} } ReceiveHandle客户端接收到服务端的响应结果处理handle public class ReceiveHandle extends SimpleChannelInboundHandler {protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {Response response = (Response) o;//通过seq从请求工厂找到请求的RequestTaskRequestTask requestTask = RequestFactory.get(response.getSeq());//将响应结果写入RequestTaskrequestTask.setResponse(response);} } RequestFactory请求工厂 public class RequestFactory {private static final Map<String, RequestTask> map = new ConcurrentHashMap<String, RequestTask>();public static void put(String uuid, RequestTask requestTask) {map.put(uuid, requestTask);}public static RequestTask get(String uuid) {return map.get(uuid);} } 注: 本人利用业余时间手写了一套轻量级的rpc框架,里面有用到 https://github.com/zhangta0/bigxiang 本篇文章为转载内容。原文链接:https://blog.csdn.net/CSDNzhangtao5/article/details/103075755。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-10-05 16:28:16
83
转载
Javascript
...实现高效、安全且易于使用的通信呢?这就是今天我们要讨论的话题——利用WebRTC技术实现点对点通信。 二、什么是WebRTC WebRTC(Web Real-Time Communication)是一种开源协议,由Google于2011年推出,旨在使网页能够进行实时音频、视频通话以及数据传输。它的特点是无需依赖任何第三方软件,只需通过浏览器就能完成通信。 三、WebRTC的工作原理 WebRTC的工作原理可以简单地概括为三个步骤: 1. 媒体流获取 浏览器会调用getUserMedia API,请求用户的摄像头和麦克风权限,获取用户的实时音频和视频流。 2. 信道建立 浏览器将媒体流封装成ICE候选信息,并发送给服务器或者其他浏览器。 3. 信令交换 通过WebSocket等网络传输机制,浏览器之间进行信令交换,协商并创建出一个可用于数据传输的安全连接。 四、如何利用WebRTC实现点对点通信 下面,我们通过一个简单的例子来说明如何利用WebRTC实现点对点通信。 首先,在HTML文件中添加以下代码: html 然后,在JavaScript文件中添加以下代码: javascript // 获取本地视频 const localStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true }); // 创建RTC对讲机 const pc = new RTCPeerConnection(); // 添加媒体流 pc.addTransceiver('audio'); pc.addTransceiver('video'); // 获取远程视频容器 const remoteVideo = document.getElementById('remoteVideo'); // 将本地视频流添加到远程视频容器 pc.getSenders().forEach((sender) => { sender.track.id = 'localVideo'; remoteVideo.srcObject = sender.track; }); // 接收媒体流 pc.ontrack = (event) => { event.streams.forEach((stream) => { stream.getTracks().forEach((track) => { track.id = 'remoteVideo'; const videoElement = document.createElement('video'); videoElement.srcObject = track; document.body.appendChild(videoElement); }); }); }; // 连接到其他客户端 function connect(otherUserURL) { // 创建新的RTCPeerConnection对象 const otherPC = new RTCPeerConnection(); // 设置回调函数,处理ICE候选信息和数据通道 otherPC.onicecandidate = (event) => { if (!event.candidate) return; pc.addIceCandidate(event.candidate); }; otherPC.ondatachannel = (event) => { event.channel.binaryType = 'arraybuffer'; channel.send('hello'); }; // 发送offer const offerOptions = { offerToReceiveAudio: true, offerToReceiveVideo: true }; pc.createOffer(offerOptions).then((offer) => { offer.sdp = SDPUtils.replaceBUNDLE_ID(offer.sdp, otherUserURL); offer.sdp = SDPUtils.replaceICE_UFRAG_AND_FINGERPRINT(offer.sdp, otherUserURL); offer.sdp = SDPUtils.replaceICEServers(offer.sdp, iceServers); return otherPC.setRemoteDescription(new RTCSessionDescription(offer)); }).then(() => { return otherPC.createAnswer(); }).then((answer) => { answer.sdp = SDPUtils.replaceBUNDLE_ID(answer.sdp, otherUserURL); answer.sdp = SDPUtils.replaceICE_UFRAG_AND_FINGERPRINT(answer.sdp, otherUserURL); answer.sdp = SDPUtils.replaceICEServers(answer.sdp, iceServers); return pc.setRemoteDescription(new RTCSessionDescription(answer)); }).catch((err) => { console.error(err.stack || err); }); } 在这个例子中,我们首先通过getUserMedia API获取用户的实时音频和视频流,然后创建一个新的RTCPeerConnection对象,并将媒体流添加到这个对象中。 接着,我们设置了回调函数,处理ICE候选信息和数据通道。当你收到ICE候选信息的时候,我们就把它塞到本地的那个RTCPeerConnection对象里头;而一旦收到数据通道的消息,我们就会把它的binaryType调成'arraybuffer'模式,然后就可以在通道里畅所欲言,发送各种消息啦。 最后,我们调用connect函数,与其他客户端建立连接。在connect函数里头,我们捣鼓出了一个崭新的RTCPeerConnection对象,就像组装一台小机器一样。然后呢,我们还给这个小家伙绑定了几个“小帮手”——回调函数,用来专门处理ICE候选信息和数据通道这些重要的任务,让它们能够实时报告状况,确保连接过程顺畅无阻。然后呢,我们给对方发个offer,就像递出一份邀请函那样。等对方接收到后,他们会回传一个answer,这就好比他们给出了接受邀请的答复。我们就把这个answer,当作是我们本地RTCPeerConnection对象的远程“地图”,这样一来,连接就算顺利完成啦! 五、结论 WebRTC技术为我们提供了一种方便、快捷、安全的点对点通信方式,大大提高了应用的交互性和实时性。当然啦,这只是个入门级的小例子,实际上的运用场景可能会复杂不少。不过别担心,只要咱们把WebRTC的核心原理和使用技巧都整明白了,就能根据自身需求灵活施展拳脚,开发出更多既有趣又有用的应用程序,保证让你玩得飞起! 未来,随着5G、物联网等技术的发展,WebRTC将会发挥更大的作用,成为更多应用场景的首选方案。让我们一起期待这个充满可能的新时代吧!
2023-12-18 14:38:05
316
昨夜星辰昨夜风_t
Dubbo
...大小、优化编码方式、使用缓存机制等方式降低网络传输的开销。 - 选择合适的网络协议:根据实际应用场景选择HTTP、TCP或其他协议,HTTP可能在某些场景下提供更好的性能和稳定性。 2. 缓存机制 - 服务缓存:利用Dubbo的本地缓存或第三方缓存如Redis,减少对远程服务的访问频率,提高响应速度。 - 结果缓存:对于经常重复计算的结果,可以考虑将其缓存起来,避免重复计算带来的性能损耗。 3. 负载均衡策略 - 动态调整:根据服务的负载情况,动态调整路由规则,优先将请求分发给负载较低的服务实例。 - 健康检查:定期检查服务实例的健康状态,剔除不可用的服务,确保请求始终被转发到健康的服务上。 4. 参数优化 - 调优配置:合理设置Dubbo的相关参数,如超时时间、重试次数、序列化方式等,以适应不同的业务需求。 - 并发控制:通过合理的线程池配置和异步调用机制,有效管理并发请求,避免资源瓶颈。 四、实战案例 案例一:服务缓存实现 java // 配置本地缓存 @Reference private MyService myService; public void doSomething() { // 获取缓存,若无则从远程调用获取并缓存 String result = cache.get("myKey", () -> myService.doSomething()); System.out.println("Cache hit/miss: " + (result != null ? "hit" : "miss")); } 案例二:动态负载均衡 java // 创建负载均衡器实例 LoadBalance loadBalance = new RoundRobinLoadBalance(); // 配置服务列表 List serviceUrls = Arrays.asList("service1://localhost:8080", "service2://localhost:8081"); // 动态选择服务实例 String targetUrl = loadBalance.choose(serviceUrls); MyService myService = new RpcReference(targetUrl); 五、总结与展望 通过上述的实践分享,我们可以看到,Dubbo的性能优化并非一蹴而就,而是需要在实际项目中不断探索和调整。哎呀,兄弟,这事儿啊,关键就是得会玩转Dubbo的各种酷炫功能,然后结合你手头的业务场景,好好打磨打磨那些参数,让它发挥出最佳状态。就像是调酒师调鸡尾酒,得看人下菜,看场景定参数,这样才能让产品既符合大众口味,又能彰显个性特色。哎呀,你猜怎么着?Dubbo这个大宝贝儿,它一直在努力学习新技能,提升自己呢!就像咱们人一样,技术更新换代快,它得跟上节奏,对吧?所以,未来的它呀,肯定能给咱们带来更多简单好用,性能超棒的功能!这不就是咱们开发小能手的梦想嘛——搭建一个既稳当又高效的分布式系统?想想都让人激动呢! 结语 在分布式系统构建的过程中,性能优化是一个持续的过程,需要开发者具备深入的理解和技术敏感度。嘿!小伙伴们,如果你是Dubbo的忠实用户或者是打算加入Dubbo大家庭的新手,这篇文章可是为你量身打造的!我们在这里分享了一些实用的技巧和深刻的理解,希望能激发你的灵感,让你在使用Dubbo的过程中更得心应手,共同创造分布式系统那片美丽的天空。快来一起探索,一起成长吧!
2024-07-25 00:34:28
411
百转千回
转载文章
...务,所有应用都能直接使用,因为 ServiceManager 对于 Client 端来说 Handle 句柄是固定的,都是 0,所以 ServiceManager 服务并不需要查询,可以直接使用 Binder 为什么会有两棵 binder_ref 红黑树? Binder_proc 中存在两棵 binder_ref 红黑树,其实两棵红黑树中的节点是复用的,只是查询方式不同,一个通过 Handle 句柄,一个通过 node 节点查找 refs_by_node 红黑树主要是为了 Binder驱动往用户空间写数据所使用的,而 refs_by_desc 是用户空间向 Binder 驱动写数据使用的,只是方向问题 比如在服务 addService 的时候,binder 驱动会在在 ServiceManager 进程的 binder_proc 中查找 binder_ref 结构体 Binder 是如何做到一次拷贝的 用户空间的虚拟内存地址是映射到物理内存中的 对虚拟内存的读写实际上是对物理内存的读写,这个过程就是内存映射 这个内存映射过程是通过系统调用 mmap() 来实现的 Binder借助了内存映射的方法,在内核空间和接收方用户空间的数据缓存区之间做了一层内存映射,就相当于直接拷贝到了接收方用户空间的数据缓存区,从而减少了一次数据拷贝 Binder机制是如何跨进程的 在内核空间创建一块接收缓存区, 实现地址映射:将内核缓存区、接收进程用户空间映射到同一接收缓存区 发送进程通过系统调用(copy_from_user)将数据发送到内核缓存区;由于内核缓存区和接收进程用户空间存在映射关系,故相当于也发送了接收进程的用户空间,实现了跨进程通信 就举例这么多了,面试题也不是几个就能全部覆盖的,毕竟面试官不是吃素的,他会换着花样问你;有想跳槽拿高薪的 Android 开发的朋友,我这里分享一份 Handler、Binder 精选面试 PDF 文档;私信发送 “面试” 直达获取;想拿高薪的人很多,就看你肯不肯努力了 面试题 PDF 文档内容展示: Handler 机制之 Thread Handler 机制之 ThreadLocal Handler 机制之 SystemClock 类 Handler 机制之 Looper 与 Handler 简介 Android 跨进程通信 IPC 之 Binder 之 Framewor k层 C++ 篇 Android 跨进程通信 IPC 之 Binder 之 Framework 层 Java 篇 Android 跨进程通信 IPC 之 Binder 的补充 Android 跨进程通信 IPC 之 Binder 总结 小伙伴们如果有需要以上这些资料:私信发送 “面试” 直达获取,承诺100%免费! 本篇文章为转载内容。原文链接:https://blog.csdn.net/m0_62167422/article/details/127129133。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-11-15 10:35:50
217
转载
转载文章
...许多观众借助思维导图工具,对诸如《海贼王》这样的长篇动漫进行分章节整理,以便更清晰地理解复杂的故事线索和人物关系网。 同时,动漫作品的跨学科应用也日益受到关注。在教育领域,有学者开始借鉴《海贼王》等热门动漫的叙事手法和价值观引导,将其融入计算机科学、考研复习等课程内容的讲解中,以提升学生的学习兴趣和知识吸收效率。例如,一些博主和教师通过制作“火影忍者”、“死神”的全集目录和精彩剧集思维导图,帮助学生梳理知识点、强化记忆,并结合实际案例进行生动教学。 总之,《海贼王》等经典动漫作品不仅为全球观众提供了丰富的娱乐体验,也在不同领域展现出其独特的价值和魅力。透过这些作品,我们不仅能领略到精彩的故事情节和视觉艺术,也能从中获得启示,将其中蕴含的团队协作、毅力坚持等精神内核应用于日常生活和专业学习之中。
2024-01-12 18:13:21
741
转载
转载文章
...另外,还可以在应用内使用声音、图片和文字等元素进行信息表达。最后当然就是社交分享功能。 打开应用,首先是类似Path或者啪啪那样一片红色的开始界面。界面中从下部飘起三个气泡,分别是人人登录、新浪微博登录以及直接进入使用。啵啵可以无需注册直接进入应用进行发布消息。 进入主界面后,主界面以时间线的形式把用户所关注的人发的声音图片信息。每条信息中,表示声音的大图标覆盖在图片显眼位置,意味着啵啵想让用户知道声音才是这个应用的主要元素,图片是作为背景图的辅助元素出现的。另外,在背景图右边有表示喜欢和评论的按钮。 主界面下方中心有十分突出显眼的声音按钮,点击后首先进入录音界面。 录音完成后,应用立刻列出表示声音滤镜的各种可爱图标。选择了某种滤镜效果后,声音生成完毕。进入发布界面,此时可以选择是否添加图片。可选择把信息分享到人人网或者新浪微博。 添加图片完成后,同时下方还可以添加文字描述,果然是声音、图片和文字三位一体全方位出击之应用。虽然这里主打声音,但声音、图片和文字分离的形式才更为符合人们对信息介质的认知习惯,小编一直认为啪啪中的所谓声音图片的概念只是一个伪概念。 对于新用户来说,可以选择添加人人网好友或者新浪微博好友,当然,应用本身会推荐优质应用建议新用户进行关注。另外,用户的关注、喜欢等信息会出现在用户的消息中心中。 这是一个同样基于信息分享的移动社交产品,其本质其实与Instagram等图片分享社区、啪啪等语音分享社区一样。啪啪本来是最先进行声音信息分享的社区,但啪啪把声音与图片混合在一起生硬造出了一个声音图片的概念,反而留下了主打声音信息分享的切入点,现在人人就抓住了这个切入点推出啵啵这个产品。 事实上,从目前已经存在啵啵社区中的用户发的消息来看,其性质与啪啪并无很大区别。啵啵主打的声音滤镜功能,有一个非常非常严重的缺陷。图片分享社区的滤镜功能对图片的改造是美化,图片滤镜可以把一张普通的图片改的看上去非常的优美和文艺,因而大大增强了用户的分享欲望,让人人都有当一回摄影师的感觉。 但声音滤镜做不到这样的效果,至少从啵啵中看来达不到美化的效果,目前从社区中声音信息可知,声音经过滤镜处理之后变得非常怪异。本身声音美的用户尤其女孩子必然受不了这样的声音变化,声音不好听的用户,经过处理后,结果是更加的不堪回首。所以,从实际情况来看,大多数人都会直接发布不加滤镜的原音。 另外,应用中有个设置奇特的地方在于,如果发布信息时只发布声音不附加图片,这条信息的背景会有一大片的空白,效果比较差。别说应用制作者,用户们都会觉得很有违和感,因而绝大多数用户都会添加图片。 这时候,啵啵变得非常类似啪啪,虽然本身,其与啪啪就相差不大。 是的,这是啪啪披着声音滤镜的外衣,事实上笔者怀疑啪啪不做声音滤镜就是有声音滤镜反而丑化声音的考虑。据了解,这是本周重组后的人人公司新的无线事业部推出的两款移动应用之一。但如果说这就是一个上市大公司在移动端发力所能做到的全部,这无疑是稍让人失望的。而且,人人网能不能不要这么马虎对待自己的产品?所谓的@啵啵官博就只在1月18日发布了一条消息,之后这个微博账号再无动静。 如果按照许朝军解释啪啪名字的来源:啪=口+拍,声音加图片。那啵啵又作何解? 好吧,其实人人网解释是这样的:“语音产品,所以取拟声名字,明确定位”。 参考:http://www.hooxiao.com/index.php?m=content&c=index&a=show&catid=19&id=14864(2013-01-21 10:04:03) 本篇文章为转载内容。原文链接:https://blog.csdn.net/prairie79/article/details/8546911。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-08-17 12:49:28
487
转载
Kafka
... 假设有一个电商网站使用Kafka来处理订单数据。要是其中一个分区的大佬挂了,系统就会自动转而听命于另一个健健康康的大佬。虽然在这个过程中可能会出现一会儿数据卡顿的情况,但总的来说,这并不会拖慢整个系统的进度。 4. 总结与展望 通过上面的讨论,我们可以看到副本同步和数据复制策略对于提高Kafka系统的稳定性和可靠性有多么重要。当然,这只是Kafka众多功能中的一个小部分,但它确实是一个非常关键的部分。以后啊,随着技术不断进步,咱们可能会见到更多新颖的数据复制方法,这样就能让Kafka跑得更快更稳了。 最后,我想说的是,学习技术就像是探险一样,充满了挑战但也同样充满乐趣。希望大家能够享受这个过程,不断探索和进步! --- 以上就是我对Kafka副本同步数据复制策略的一些理解和分享。希望对你有所帮助!如果有任何问题或想法,欢迎随时交流讨论。
2024-10-19 16:26:57
57
诗和远方
转载文章
... 提交表单一、使用普通按钮type="button"1.给按钮绑定click点击事件,绑定函数2.在函数中,进行表单校验(非空校验、 合法性校验等)3.如果校验通过,则手动提交表单表单对象.submit();二、使用提交按钮type="submit"1.给按钮绑定click点击事件,绑定函数2.函数需要有返回值,返回true或false (如果return false, 则表单不会提交:如果return true,则提交表单)onclick="return 函数名()"3.在函数中,进行表单校验(非空校验、 合法性校验等)4.如果校验通过,返回true;如果校验不通过,则返回false, 则表单不会提交:如果return true,则提交表单)三、使用提交按钮type="submit"1.给表单form元素绑定submit提交事件,绑定函数2.函数需要有返回值,返回true或false (如果return false, 则表单不会提交;如果return trueonsubmit="return函数名()" 3.在函数中,进行表单校验(非空校验、 合法性校验等)4.如果校验通过,返回true;如果校验不通过,则返回false <!--使用普逍按钮 type= "button"--><form id= 'myform' name= "myform" action="http://www.baidu.com" method="get" >姓名: <input name= "uname" id="uname"/> <span id = "msg" style="font-s1ze: 12px; color: red;"></span><br /><button type="button" onclick="submitForm1()">提交</button></form><!--使用提交按钮 type= "submit"--><form id= 'myform2' name= "myform2" action="http://www.baidu.com" method="get" >姓名: <input name= "uname2" id="uname2"/> <span id = "msg2" style="font-s1ze: 12px; color: red;"></span><br /><button type="submit" onclick="return submitForm2()">提交</button></form><!--使用提交按钮 type= "submit"--><form id= 'myform3' name= "myform3" action="http://www.baidu.com" method="get" onsubmit="return submitForm3()">姓名: <input name= "uname3" id="uname3"/> <span id = "msg3" style="font-s1ze: 12px; color: red;"></span><br /><button type="submit">提交</button></form><script type="text/javascript">// 表单校验// 提交表单function submitForm1() {//得到文本框的值var uname = document.getElementById("uname").value;//判断是否为空if (isEmpty(uname)) { //为空//设置提示信息(设置span元素的值)document.getElementById("msg").innerHTML="性名不能为空!" ;//阻止表单提交return;}//手动提交表单document.getElementById("myform").submit(); }function submitForm2() {//得到文本框的值var uname2 = document.getElementById("uname2").value;//判断是否为空if (isEmpty(uname2)) { //为空//设置提示信息(设置span元素的值)document.getElementById("msg2").innerHTML="性名不能为空!" ;//阻止表单提交return false;}return true;}function submitForm3() {//得到文本框的值var uname3 = document.getElementById("uname3").value;//判断是否为空if (isEmpty(uname3)) { //为空//设置提示信息(设置span元素的值)document.getElementById("msg3").innerHTML="性名不能为空!" ;//阻止表单提交return false;}return true;}/ 判断字符串是否为空如果为空,返回true如果非空,返回falsetrim() :字符串方法, 去除字符串前后空格@param {Object} str/function isEmpty(str) {//判断是否为空if (str == null || str.trim() == "") {return true;}return false;}</script> 运行效果截图: 四、原生Ajax实现流程 <!-- Ajax 异步无刷新技术原生Ajax的实现流程1.得到XMLHttpRequest对象var xhr = new XMLHttpRequest();2.打开请求xhr.open(method, uri, async) ;method:请求方式,通常是GEI|POSTurl:请求地址async:是否异步。如果是true表示异步,false表示同步3.发送请求xhr.send(params);params:请求时需要传递的参数如果是GET请求,设置nu11。 (GET请求的参数设置在url后面)如果是POST请求,无参数设置为null,有参数则设置参数4.接收响应xhr.status响应状态(200=响应成功, 404=资源末找到,500=服务器异常)xhr.responseText 得到响应结果 --> <script type="text/javascript">// 同步请求function text01() {// 1.得到XMLHttpRequest对象var xhr = new XMLHttpRequest();// 2.打开请求xhr.open("get", "js/date.json", false);// 3.发送请求xhr.send(null);// 4.判断响应状态if (xhr.status == 200) {console.log("响应成功");} else {console.log("状态码:" + xhr.status + ",原因:" + xhr.responseText)}console.log("同步请求...");}text01();// 异步请求function text02() {// 1.得到XMLHttpRequest对象var xhr = new XMLHttpRequest();// 2.打开请求xhr.open("get", "js/date.json", true);// 3.发送请求xhr.send(null);// 由于是异步请求,所以需要知道后台已经将请求处理完毕,才能获取响应结果// 遇过监听readyState的变化来得知后面的处理状态 4=完全处理xhr.onreadystatechange = function(){if(xhr.readyState == 4){// 4.判断响应状态if (xhr.status == 200) {// 得到响应结果 console.log(xhr.responseText);} else {console.log("状态码:" + xhr.status + ",原因:" + xhr.responseText)} }}console.log("异步请求...");}text02();</script> 运行效果截图: 本篇文章为转载内容。原文链接:https://blog.csdn.net/m0_61507413/article/details/122895643。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-10-22 17:32:41
521
转载
转载文章
...容。 支付接口介绍 使用此接口可以实现支付宝、QQ钱包、微信支付与财付通的即时到账,免签约,无需企业认证。接口API地址是:http://pay.lqan.cn/ 本文阅读对象:商户系统(在线购物平台、人工收银系统、自动化智能收银系统或其他)集成凉秋易支付涉及的技术架构师,研发工程师,测试工程师,系统运维工程师。 接口申请方式 共有两种接口模式: (一)普通支付商户 可以获得一个支付商户。请进行注册申请,申请之后会将商户ID和商户KEY给你! 协议规则 传输方式:HTTP 数据格式:JSON 签名算法:MD5 字符编码:UTF-8 [API]查询商户信息与结算规则 URL地址:http://pay.lqan.cn/api.php?act=query&pid={商户ID}&sign={签名字符串} 请求参数说明: 字段名变量名必填类型示例值描述 操作类型act是Stringquery此API固定值 商户IDpid是Int1001 签名字符串sign是String67d12af9ddbe38d9c7b0931ad102ca3c签名算法与支付宝签名算法相同 返回结果: 字段名变量名类型示例值描述 返回状态码codeInt11为成功,其它值为失败 商户IDpidInt1001所创建的商户ID 商户密钥keyString(32)89unJUB8HZ54Hj7x4nUj56HN4nUzUJ8i所创建的商户密钥 商户类型typeInt1此值暂无用 商户状态activeInt11为正常,0为封禁 商户余额moneyString0.00商户所拥有的余额 结算账号accountString1070077170@qq.com结算的支付宝账号 结算姓名usernameString张三结算的支付宝姓名 满多少自动结算settle_moneyString30此值为系统预定义 手动结算手续费settle_feeString1此值为系统预定义 每笔订单分成比例money_rateString98此值为系统预定义 [API]查询结算记录 URL地址:http://pay.lqan.cn/api.php?act=settle&pid={商户ID}&sign={签名字符串} 请求参数说明: 字段名变量名必填类型示例值描述 操作类型act是Stringsettle此API固定值 商户IDpid是Int1001 签名字符串sign是String67d12af9ddbe38d9c7b0931ad102ca3c签名算法与支付宝签名算法相同 返回结果: 字段名变量名类型示例值描述 返回状态码codeInt11为成功,其它值为失败 返回信息msgString查询结算记录成功! 结算记录dataArray结算记录列表 [API]查询单个订单 URL地址:http://pay.lqan.cn/api.php?act=order&pid={商户ID}&out_trade_no={商户订单号}&sign={签名字符串} 请求参数说明: 字段名变量名必填类型示例值描述 操作类型act是Stringorder此API固定值 商户IDpid是Int1001 商户订单号out_trade_no是String20160806151343349 签名字符串sign是String67d12af9ddbe38d9c7b0931ad102ca3c签名算法与支付宝签名算法相同 返回结果: 字段名变量名类型示例值描述 返回状态码codeInt11为成功,其它值为失败 返回信息msgString查询订单号成功! 易支付订单号trade_noString2016080622555342651凉秋易支付订单号 商户订单号out_trade_noString20160806151343349商户系统内部的订单号 支付方式typeStringalipayalipay:支付宝,tenpay:财付通, qqpay:QQ钱包,wxpay:微信支付 商户IDpidInt1001发起支付的商户ID 创建订单时间addtimeString2016-08-06 22:55:52 完成交易时间endtimeString2016-08-06 22:55:52 商品名称nameStringVIP会员 商品金额moneyString1.00 支付状态statusInt01为支付成功,0为未支付 [API]批量查询订单 URL地址:http://pay.lqan.cn/api.php?act=orders&pid={商户ID}&sign={签名字符串} 请求参数说明: 字段名变量名必填类型示例值描述 操作类型act是Stringorders此API固定值 商户IDpid是Int1001 查询订单数量limit否Int20返回的订单数量,最大50 签名字符串sign是String67d12af9ddbe38d9c7b0931ad102ca3c签名算法与支付宝签名算法相同 返回结果: 字段名变量名类型示例值描述 返回状态码codeInt11为成功,其它值为失败 返回信息msgString查询结算记录成功! 订单列表dataArray订单列表 [API]支付订单退款 URL地址:http://pay.lqan.cn/api.php?act=refund&pid={商户ID}&out_trade_no={商户订单号}&sign={签名字符串} 只支持微信官方、QQ钱包官方、当面付退款 请求参数说明: 字段名变量名必填类型示例值描述 操作类型act是Stringrefund此API固定值 商户IDpid是Int1001 商户订单号out_trade_no是Int1000 退款原因desc否String 退款金额money否Double20.00不填默认退全款 签名字符串sign是String67d12af9ddbe38d9c7b0931ad102ca3c签名算法与支付宝签名算法相同 返回结果: 字段名变量名类型示例值描述 返回状态码codeInt11为成功,其它值为失败 返回信息msgString退款成功! 发起支付请求 URL地址:http://pay.lqan.cn/submit.php?pid={商户ID}&type={支付方式}&out_trade_no={商户订单号}¬ify_url={服务器异步通知地址}&return_url={页面跳转通知地址}&name={商品名称}&money={金额}&sitename={网站名称}&sign={签名字符串}&sign_type=MD5 请求参数说明: 字段名变量名必填类型示例值描述 商户IDpid是Int1001 支付方式type是Stringalipayalipay:支付宝,tenpay:财付通, qqpay:QQ钱包,wxpay:微信支付 商户订单号out_trade_no是String20160806151343349 异步通知地址notify_url是Stringhttp://域名/notify_url.php服务器异步通知地址 跳转通知地址return_url是Stringhttp://域名/return_url.php页面跳转通知地址 商品名称name是StringVIP会员 商品金额money是String1.00 网站名称sitename否String某某某平台 签名字符串sign是String202cb962ac59075b964b07152d234b70签名算法与支付宝签名算法相同 签名类型sign_type是StringMD5默认为MD5 支付结果通知 通知类型:服务器异步通知(notify_url)、页面跳转通知(return_url) 请求方式:GET 特别说明:回调成功之后请输出 SUCCESS字符串,如果没有收到商户响应的SUCCESS字符串,系统将通过策略重新通知5次,通知频率为15s/60s/3m/30m/1h 请求参数说明: 字段名变量名必填类型示例值描述 商户IDpid是Int1001 易支付订单号trade_no是String20160806151343349021凉秋易支付订单号 商户订单号out_trade_no是String20160806151343349商户系统内部的订单号 支付方式type是Stringalipayalipay:支付宝,tenpay:财付通, qqpay:QQ钱包,wxpay:微信支付 商品名称name是StringVIP会员 商品金额money是String1.00 支付状态trade_status是StringTRADE_SUCCESS 签名字符串sign是String202cb962ac59075b964b07152d234b70签名算法与支付宝签名算法相同 签名类型sign_type是StringMD5默认为MD5 签名算法 请对参数按照键名进行降序排序(a-z)sign sign_type 和空值不进行签名!。 排序后请操作参数生成或拼接一个url请求字符串 例如 a=b&c=d&e=f (Url值不能携带参数!不要进行urlencode) 再将拼接好的请求字符串与平台生成的Key进行MD5加密得出sign签名参数 MD5 ( a=b&c=d&e=f + KEY ) (注意:+ 为各语言的拼接符!不是字符!) 本篇文章为转载内容。原文链接:https://blog.csdn.net/weixin_39620334/article/details/115933932。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-12-18 16:55:58
91
转载
MySQL
...、引言 二、为什么要使用无限极分类? 三、什么是递归? 四、如何使用递归来处理无限极分类? 五、不使用递归,如何处理无限极分类? 六、案例分析 七、结论 八、参考资料 一、引言 在日常工作中,我们经常需要对一些数据进行分类,例如商品分类、用户等级等。其中,无限极分类是一种非常常用的数据分类方式,它可以用来表示一种层次结构,如商品分类中的父类、子类等。然而,在处理这种数据时,我们常常会遇到一个问题:如何快速、有效地将无限极分类转换为层级结构呢? 二、为什么要使用无限极分类? 首先,我们需要了解一下什么是无限极分类。无限极分类就像一棵大树,它的构造挺有趣。在这样的树形结构中,每一个小节点都有一个自己的‘老爹’节点,而这个‘老爹’呢,它还可能是其他许多小节点的‘老爹’。这样的构造方式,其实就像家谱一样,可以展示出各种级别的层次关系。比如说在商品分类里,就有爷爷辈的大类别、爸爸辈的中类别、儿子辈的小类别,甚至还有孙子辈的更细分的类别呢! 其次,无限极分类的优点在于它可以方便地进行扩展。假如我们想要新增一个类别,就像在家族树上添个新枝丫一样简单,你只需要在它的“老爸”类别下加一个新的“小子类别”,这样一来,数据的一致性和完整性就能轻轻松松地保持住啦! 三、什么是递归? 那么,如何使用递归来处理无限极分类呢?这就需要用到递归的概念。递归啊,就是那种函数自己调用自己的神奇操作。你想象一下,这个函数有点像一个超级有耐心的小助手,一遍又一遍地做着同一件事情,但每次做的时候都比上次更进一步。通过这种自我迭代的过程,我们竟然能解开很多看起来超级复杂、让人挠头的问题呢! 在处理无限极分类时,我们可以使用递归的方式,从根节点开始,一层一层地遍历下去,直到找到所有的叶子节点。然后,我们可以根据每层的节点,构建出相应的层级结构。 四、如何使用递归来处理无限极分类? 接下来,我们来看一下如何使用递归来处理无限极分类。假设我们有一个无限极分类的数据库表,其中包含id、parent_id和name三个字段。喏,你听我说哈,id呢,就相当于每个小节点的身份证号,是独一无二的。而parent_id呢,顾名思义,就是每个小节点它爹——父节点的身份证号啦。至于name嘛,简单易懂,那就是给每个小节点起的专属昵称哈! 我们可以定义一个函数,输入参数是一个父节点的id,输出是一个层级结构的数组。具体操作如下: php function getTree($id){ $sql = "SELECT FROM node WHERE parent_id = '$id'"; $result = mysqli_query($conn, $sql); $arr = array(); while($row = mysqli_fetch_assoc($result)){ $arr[] = $row; } foreach($arr as $value){ if($value['child'] > 0){ $arr = array_merge($arr, getTree($value['id'])); } } return $arr; } 以上就是使用递归来处理无限极分类的一个简单示例。这个例子嘛,我们先从某个特定的老爸节点下手,把它的所有小崽子(子节点)都给挖出来。接着呢,对每一个小崽子,如果它们自己还有更下一代的小崽子,那我们就得像孙悟空钻进葫芦娃的肚子里那样,一层层地往里递归调用这个过程,把那些隐藏更深的孙子辈节点也给找全了。最后呢,咱们把这一大家子所有的节点都聚到一块儿,拼成一个完整的、层层分明的家族结构。 然而,递归虽然强大,但也有它的局限性。当数据量大时,递归可能会导致栈溢出,影响程序的执行效率。因此,我们需要寻找其他的解决方案。 五、不使用递归,如何处理无限极分类? 那么,如果不使用递归,我们该如何处理无限极分类呢?答案就是使用非递归的方式,也就是我们常说的迭代法。 迭代法的基本思想是从根节点开始,每次只处理一层数据,直到处理完所有的数据。这种方法压根儿不需要递归调用,所以你完全不用担心什么栈溢出的问题。而且实话跟你说,通常情况下,它的工作效率要比递归高不少! 接下来,我们来看一下如何使用迭代法处理无限极分类。假设我们已经有了一个无限极分类的数据库表,其中包含id、parent_id和name三个字段。我们可以按照以下步骤进行处理: 1. 创建一个空的层级结构数组,用于存储所有的节点; 2. 获取根节点,将其添加到层级结构数组中; 3. 遍历所有的节点,对于每一个节点,如果它还没有被处理过,则对其进行处理,将其添加到层级结构数组中,然后处理它的所有子节点。 具体的代码实现如下: php function getTree($root){ $tree = array(); $queue = array($root); while(count($queue) > 0){ $node = array_shift($queue); $tree[$node['id']] = array( 'id' => $node['id'], 'parent_id' => $node['parent_id'], 'name' => $node['name'], 'children' => array() ); if($node['child'] > 0){ $queue = array_merge($queue, getChildren($conn, $node['id'])); } } return $tree; } function getChildren($conn, $id){ $sql = "SELECT FROM node WHERE parent_id = '$id'"; $result = mysqli_query($conn, $sql); $arr = array(); while($row = mysqli_fetch_assoc($result)){ $arr[] = $row; } return $arr; } 以上就是在非递归的情况下,处理无限极分类的一个简单示例。在举这个例子的时候,我们首先动手整了个空荡荡的层级结构数组出来,接着找准了那个根节点,把它给塞进了这个层级结构数组里头。然后,我们就像在超市排队结账一样,用一个队列来装那些等待被处理的节点。每当轮到一个节点时,我们就把它从队列里拽出来,塞进层级结构数组这个大篮子里,并且仔仔细细地处理它所有的“孩子”——也就是子节点。最后一步,咱们就像玩接龙游戏一样,把已经处理过的节点从队列里拿出来,然后美滋滋地接着处理下一个排着队的节点,就这么一直玩下去,直到队列里一个节点都不剩,就表示大功告成了! 总结来说,无论是使用递归还是非递归,都可以有效地处理无限极分类。但是,不同的方法适用于不同的场景,我们需要根据实际情况选择合适的方法。
2023-08-24 16:14:06
59
星河万里_t
Golang
... 3.2 使用错误链路 在复杂的应用中,一个操作可能会触发多个后续步骤,每个步骤都可能产生新的错误。在这种情况下,错误链路(即错误传播)变得尤为重要。我们可以利用Go语言的多返回值特性来实现这一点。 go func readConfig(filePath string) (map[string]string, error) { file, err := os.Open(filePath) if err != nil { return nil, fmt.Errorf("打开配置文件失败: %w", err) } defer file.Close() var config map[string]string decoder := json.NewDecoder(file) if err := decoder.Decode(&config); err != nil { return nil, fmt.Errorf("解析配置文件失败: %w", err) } return config, nil } func main() { config, err := readConfig("config.json") if err != nil { log.Fatalf("读取配置文件失败: %v", err) } // 使用配置... } 在这个例子中,readConfig函数尝试打开并解析一个JSON格式的配置文件。如果任何一步失败,我们都会返回一个包含原始错误的错误对象。这样做不仅可以让错误信息更加完整,还便于我们在调用方进行统一处理。 3.3 自定义错误类型 虽然标准库提供的error接口已经足够强大,但在某些场景下,我们可能需要更丰富的错误信息。这时,可以定义自己的错误类型来扩展功能。 go type MyError struct { Message string Code int } func (e MyError) Error() string { return fmt.Sprintf("错误代码%d: %s", e.Code, e.Message) } func doSomething() error { return &MyError{Message: "操作失败", Code: 500} } func main() { err := doSomething() if err != nil { log.Printf("发生错误: %v", err) } } 在这个例子中,我们定义了一个自定义错误类型MyError,它包含了一个消息和一个错误码。这样做的好处是可以根据不同的错误码采取不同的处理策略。 4. 错误信息的最佳实践 最后,我想分享一些我在日常开发中积累的经验,这些经验有助于写出更好的错误信息。 - 明确且具体:错误信息应该直接指出问题所在,避免模糊不清的描述。 - 用户友好的:对于最终用户可见的错误信息,尽量使用通俗易懂的语言。 - 提供解决方案:如果可能的话,给出一些基本的解决建议。 - 避免泄露敏感信息:在生成错误信息时,注意不要暴露敏感数据,如密码或密钥。 结语 错误信息是我们与程序之间的桥梁,它能帮助我们更好地理解问题所在,并找到解决问题的方法。在Go语言里,错误处理不仅仅是个技术活儿,它还代表着一种态度——就是要做出高质量的软件的那种执着精神。希望通过这篇文章,你能在未来的项目中更加重视错误信息的处理,从而写出更加健壮和可靠的代码。 --- 以上内容结合了理论与实践,旨在让你对Go语言中的错误处理有更深的理解。记住,好的错误信息就像是一位优秀的导游,它能带你穿越迷雾,找到正确的方向。
2024-11-09 16:13:46
128
桃李春风一杯酒
ActiveMQ
...有语言版本的客户端都使用相同的协议和数据格式,如JSON或XML,以减少跨语言通信的复杂性。 2. 使用统一的API 尽管不同语言有不同的客户端库,但它们都应该遵循统一的API规范,这样可以简化开发和维护。 3. 配置共享资源 在部署时,确保所有语言环境都能访问到同一台ActiveMQ服务器,或者设置多个独立的服务器实例来满足不同语言环境的需求。 4. 性能优化 针对不同语言环境的特点进行性能调优,例如,对于并发处理需求较高的语言(如Java),可能需要更精细地调整ActiveMQ的参数。 示例代码(Python): 利用Apache Paho库来接收刚刚发送的消息: python import paho.mqtt.client as mqtt import json def on_connect(client, userdata, flags, rc): print("Connected with result code "+str(rc)) client.subscribe("myQueue") def on_message(client, userdata, msg): message = json.loads(msg.payload.decode()) print("Received message:", message) client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message client.connect("localhost", 1883, 60) client.loop_forever() 三、实践案例 多语言环境下的一体化消息系统 在一家电商公司中,我们面临了构建一个支持多语言环境的实时消息系统的需求。哎呀,这个系统啊,得有点儿本事才行!首先,它得能给咱们的商品更新发个通知,就像是快递到了,你得知道一样。还有,用户那边的活动提醒也不能少,就像朋友生日快到了,你得记得送礼物那种感觉。最后,后台的任务调度嘛,那就像是家里的电器都自动工作,你不用操心一样。这整个系统要能搞定Java、Python和Node.js这些编程语言,得是个多才多艺的家伙呢! 实现细节: - 消息格式:采用JSON格式,便于解析和处理。 - 消息队列:使用ActiveMQ作为消息中间件,确保消息的可靠传递。 - 语言间通信:通过统一的消息API接口,确保不同语言环境的客户端能够一致地发送和接收消息。 - 负载均衡:通过配置多个ActiveMQ实例,实现消息系统的高可用性和负载均衡。 四、结论与展望 ActiveMQ在多语言环境下的部署不仅提升了开发效率,也增强了系统的灵活性和可扩展性。哎呀,你知道的,编程这事儿,就像是个拼图游戏,每个程序员手里的拼图都代表一种编程语言。每种语言都有自己的长处,比如有的擅长处理并发任务,有的则在数据处理上特别牛。所以,聪明的开发者会好好规划,把最适合的拼图放在最合适的位置上。这样一来,咱们就能打造出既快又稳的分布式系统了。就像是在厨房里,有的人负责洗菜切菜,有的人专门炒菜,分工合作,效率噌噌往上涨!哎呀,你懂的,现在微服务这东西越来越火,加上云原生应用也搞得风生水起的,这不,多语言环境下的应用啊,那可真是遍地开花。你看,ActiveMQ这个家伙,它就像个大忙人似的,天天在多语言环境中跑来跑去,传递消息,可不就是缺不了它嘛!这货一出场,就给多语言环境下的消息通信添上了不少色彩,推动它往更高级的方向发展,你说它是不是有两把刷子? --- 通过上述内容的探讨,我们不仅了解了如何在多语言环境下部署和使用ActiveMQ,还看到了其实现复杂业务逻辑的强大潜力。无论是对于企业级应用还是新兴的微服务架构,ActiveMQ都是一个值得信赖的选择。哎呀,随着科技这玩意儿天天在变新,我们能期待的可是超棒的创新点子和解决办法!这些新鲜玩意儿能让我们在不同语言的世界里写程序时更爽快,系统的运行也更顺溜,就像喝了一大杯冰凉透心的柠檬水一样,那叫一个舒坦!
2024-10-09 16:20:47
66
素颜如水
转载文章
...特性进行优化, 比如使用引用计数std::shared_ptr,内存池方式等等。 1. 用户空间内存管理 目前大部分用户控件程序使用glibc提供的malloc/free系列函数,而glibc使用的ptmalloc2在性能上远远弱后于google的tcmalloc和facebook的jemalloc。 而且后两者只需要使用LD_PRELOAD环境变量启动程序即可,甚至并不需要重新编译。 1.1 ptmalloc2 malloc是一个C库中的函数,malloc向glibc请求内存空间。glibc初始分配或者通过brk和sbrk或者mmap向内核批发内存,然后“卖”给我们malloc使用。 既然brk、mmap提供了内存分配的功能,直接使用brk、mmap进行内存管理不是更简单吗,为什么需要glibc呢? 因为系统调用,导致程序从用户态陷入内核态,比较消耗资源。为了减少系统调用带来的性能损耗,glibc采用了内存池的设计,增加了一个代理层,每次内存分配,都优先从内存池中寻找,如果内存池中无法提供,再向操作系统申请。 1.2 tcmalloc tcmalloc 是google开发的内存分配算法库,用来替代传统的malloc内存分配函数,它有减少内存碎片,适用于多核,更好的并行性支持等特性。 要使用tcmalloc,只要将tcmalloc通过-ltcmalloc连接到应用程序即可。 也可以使用LD_PRELOAD在不是你自己编译的应用程序中使用:$ LD_PRELOAD="/usr/lib/libtcmalloc.so" 2. 内核空间内存管理 linux操作系统内核,将内存分为一个个页去管理。 2.1 页面管理算法–伙伴系统 在实际应用中,而频繁地申请和释放不同大小的连续页框,必然导致在已分配页框的内存块中分散了许多小块的空闲页框。这样,即使这些页框是空闲的,其他需要分配连续页框的应用也很难得到满足。 为了避免出现这种内存碎片,Linux内核中引入了伙伴系统算法(buddy system)。 2.1.1 Buddy(伙伴的定义) 满足以下三个条件的称为伙伴: 1)两个块大小相同; 2)两个块地址连续; 3)两个块必须是同一个大块中分离出来的; 2.1.2 Buddy算法的分配 假设要申请一个256个页框的块,先从256个页框的链表中查找空闲块,如果没有,就去512个页框的链表中找,找到了则将页框块分为2个256个页框的块,一个分配给应用,另外一个移到256个页框的链表中。如果512个页框的链表中仍没有空闲块,继续向1024个页框的链表查找,如果仍然没有,则返回错误。 2.1.3 Buddy算法的释放 内存的释放是分配的逆过程,也可以看作是伙伴的合并过程。页框块在释放时,会主动将两个连续的页框块合并为一个较大的页框块。 2.2 Slab机制 slab是Linux操作系统的一种内存分配机制。其工作是针对一些经常分配并释放的对象,如进程描述符等,这些对象的大小一般比较小,如果直接采用伙伴系统来进行分配和释放,不仅会造成大量的内碎片,而且处理速度也太慢。 而slab分配器是基于对象进行管理的,相同类型的对象归为一类(如进程描述符就是一类),每当要申请这样一个对象,slab分配器就从一个slab列表中分配一个这样大小的单元出去,而当要释放时,将其重新保存在该列表中,而不是直接返回给伙伴系统,从而避免这些内碎片。slab分配器并不丢弃已分配的对象,而是释放并把它们保存在内存中。当以后又要请求新的对象时,就可以从内存直接获取而不用重复初始化。 2.3 内核中申请内存的函数 2.3.1 __get_free_pages __get_free_pages函数是最原始的内存分配方式,直接从伙伴系统中获取原始页框,返回值为第一个页框的起始地址. 2.3.2 kmem_cache_alloc kmem_cache_create/ kmem_cache_alloc是基于slab分配器的一种内存分配方式,适用于反复分配释放同一大小内存块的场合。首先用kmem_cache_create创建一个高速缓存区域,然后用kmem_cache_alloc从 该高速缓存区域中获取新的内存块。 2.3.3 kmalloc kmalloc是内核中最常用的一种内存分配方式,它通过调用kmem_cache_alloc函数来实现。 kmalloc() 申请的内存位于物理内存映射区域,而且在物理上也是连续的,它们与真实的物理地址只有一个固定的偏移,因为存在较简单的转换关系,所以对申请的内存大小有限制,不能超过128KB。 较常用的flags()有: GFP_ATOMIC —— 不能睡眠; GFP_KERNEL —— 可以睡眠; GFP_DMA —— 给 DMA 控制器分配内存,需要使用该标志。 2.3.4 vmalloc vmalloc() 函数则会在虚拟内存空间给出一块连续的内存区,但这片连续的虚拟内存在物理内存中并不一定连续。由于 vmalloc() 没有保证申请到的是连续的物理内存,因此对申请的内存大小没有限制,如果需要申请较大的内存空间就需要用此函数了。 注意vmalloc和vfree时可以睡眠的,因此不能从中断上下问调用。 一般情况下,内存只有在要被 DMA 访问的时候才需要物理上连续,但为了性能上的考虑,内核中一般使用 kmalloc(),而只有在需要获得大块内存时才使用 vmalloc()。例如,当模块被动态加载到内核当中时,就把模块装载到由 vmalloc() 分配的内存上。 本篇文章为转载内容。原文链接:https://secdev.blog.csdn.net/article/details/109731954。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-02-26 20:46:17
232
转载
转载文章
..., 2]) 个人感觉使用reflect操作,而不是之间的填充0是为了在边缘去噪的时候更平滑一些。镜像填充后的图如下: 输入网络后,得到预测结果。最后进行裁剪,得到去噪后的图像。 prediction = prediction[:, :, :H, :W] 本篇文章为转载内容。原文链接:https://blog.csdn.net/qq_42948594/article/details/124712116。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-06-13 14:44:26
129
转载
Apache Solr
...olr虽然强大,但在使用过程中也会遇到各种各样的问题。了解并搞定这些常见问题后,咱们就能把Solr的潜能发挥得更淋漓尽致,这样一来,工作效率蹭蹭上涨,用户体验也噌噌提升,妥妥的双赢局面!希望本文能对你有所帮助!
2023-05-31 15:50:32
498
山涧溪流-t
站内搜索
用于搜索本网站内部文章,支持栏目切换。
知识学习
实践的时候请根据实际情况谨慎操作。
随机学习一条linux命令:
chattr +i file
- 设置文件为不可更改(防止误删或修改)。
推荐内容
推荐本栏目内的其它文章,看看还有哪些文章让你感兴趣。
2023-04-28
2023-08-09
2023-06-18
2023-04-14
2023-02-18
2023-04-17
2024-01-11
2023-10-03
2023-09-09
2023-06-13
2023-08-07
2023-03-11
历史内容
快速导航到对应月份的历史文章列表。
随便看看
拉到页底了吧,随便看看还有哪些文章你可能感兴趣。
时光飞逝
"流光容易把人抛,红了樱桃,绿了芭蕉。"