当前位置: 首页 > news >正文

SpringBoot使用Hbase

SpringBoot使用Hbase

文章目录

  • SpringBoot使用Hbase
  • 一,引入依赖
  • 二,配置文件添加自己的属性
  • 三,配置类注入HBASE配置
  • 四,配置Hbase连接池
  • 五,配置操作服务类

一,引入依赖

		<dependency><groupId>org.apache.hbase</groupId><artifactId>hbase-client</artifactId><version>2.3.2</version><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId></exclusion></exclusions></dependency>

二,配置文件添加自己的属性

hbase:zookeeper:quorum: 10.xxx.xx.153,10.xxx.xx.154,10.xxx.xx.155property:clientPort: 2181master:port: 9001

三,配置类注入HBASE配置

package com.hbase.config;import org.apache.hadoop.hbase.HBaseConfiguration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @ClassName: HBaseConfig* @author: Leemon* @Description: TODO* @date: 2023/4/12 18:06* @version: 1.0*/
@Configuration
@RefreshScope
public class HBaseConfig {@Value("${hbase.zookeeper.quorum}")private String zookeeperQuorum;@Value("${hbase.zookeeper.property.clientPort}")private String clientPort;@Value("${hbase.master.port}")private String masterPort;@Beanpublic org.apache.hadoop.conf.Configuration hbaseConfiguration() {org.apache.hadoop.conf.Configuration conf = HBaseConfiguration.create();conf.set("hbase.zookeeper.quorum", zookeeperQuorum);conf.set("hbase.zookeeper.property.clientPort", clientPort);// 如果hbase是集群,这个必须加上// 这个ip和端口是在hadoop/mapred-site.xml配置文件配置的conf.set("hbase.master", zookeeperQuorum + ":" + masterPort);conf.set("hbase.client.keyvalue.maxsize", "20971520");conf = HBaseConfiguration.create(conf);return conf;}}

四,配置Hbase连接池

这里没有使用懒加载模式,减少启动后第一次访问时访问时间过长

package com.hbase.config;import lombok.extern.slf4j.Slf4j;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;/*** @ClassName: HbaseConnectionPool* @author: Leemon* @Description: TODO* @date: 2023/4/13 9:45* @version: 1.0*/
@Component
@Slf4j
public class HbaseConnectionPool {/*** 连接池最大的大小*/private int nMaxConnections = 20;/*** 连接池自动增加的大小*/private int nIncrConnectionAmount = 3;/*** 连接池的初始大小*/private int nInitConnectionAmount = 3;/*** 存放连接池中数据库连接的向量,初始时为null*/private Vector vcConnections = null;@Resourceprivate Configuration hbaseConfiguration;@PostConstructpublic void init() {try {vcConnections = new Vector();createConnections(nInitConnectionAmount);} catch (Exception e) {e.printStackTrace();}}public synchronized Connection getConnection() {// 确保连接池己被创建if (vcConnections == null) {// 连接池还没创建,则返回nullreturn null;}// 获得一个可用的数据库连接Connection conn = getFreeConnection();// 如果目前没有可以使用的连接,即所有的连接都在使用中while (conn == null) {// 等一会再试try {wait(250);} catch (InterruptedException e) {e.printStackTrace();}// 重新再试,直到获得可用的连接,如果getFreeConnection()返回的为null,则表明创建一批连接后也不可获得可用连接conn = getFreeConnection();}// 返回获得的可用的连接return conn;}/*** 本函数从连接池向量 connections 中返回一个可用的的数据库连接,如果* 当前没有可用的数据库连接,本函数则根据 incrementalConnections 设置* 的值创建几个数据库连接,并放入连接池中。* 如果创建后,所有的连接仍都在使用中,则返回 null* @return* 		返回一个可用的数据库连接*/private Connection getFreeConnection() {// 从连接池中获得一个可用的数据库连接Connection conn = findFreeConnection();if (conn == null) {// 如果目前连接池中没有可用的连接// 创建一些连接try {createConnections(nIncrConnectionAmount);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();log.error("create new connection fail.", e);}// 重新从池中查找是否有可用连接conn = findFreeConnection();if (conn == null) {// 如果创建连接后仍获得不到可用的连接,则返回 nullreturn null;}}return conn;}/*** 创建由 numConnections 指定数目的数据库连接 , 并把这些连接* 放入 connections 向量中* @param _nNumConnections 要创建的数据库连接的数目* @throws Exception*/private void createConnections(int _nNumConnections) throws Exception {// 循环创建指定数目的数据库连接for (int x = 0; x < _nNumConnections; x++) {// 是否连接池中的数据库连接的数量己经达到最大?最大值由类成员 maxConnections// 指出,如果 maxConnections 为 0 或负数,表示连接数量没有限制。// 如果连接数己经达到最大,即退出。if (this.nMaxConnections > 0  && this.vcConnections.size() >= this.nMaxConnections) {log.warn("已达到最大连接数,不能再增加连接");throw new Exception("已达到最大连接数"+ nMaxConnections+",不能再增加连接");}// 增加一个连接到连接池中(向量 connections 中)vcConnections.addElement(new ConnectionWrapper(newConnection()));log.info("HBase数据库连接己创建 ...... " + x);}}/*** 查找池中所有的連接,查找一个可用的數據庫連接,* 如果没有可用的連結,返回null* @return* 		返回一個可用的數據庫連接*/private Connection findFreeConnection() {Connection conn = null;ConnectionWrapper connWrapper = null;//獲得連接池向量中所有的對象Enumeration enumerate = vcConnections.elements();//遍歷所有的对象,看是否有可用的連接while (enumerate.hasMoreElements()) {connWrapper = (ConnectionWrapper) enumerate.nextElement();if (!connWrapper.isBusy()) {//如果此對象不忙,則獲得它的數據庫連接并把它設為忙conn = connWrapper.getConnection();connWrapper.setBusy(true);// 己经找到一个可用的連接,退出break;}}// 返回找到的可用連接return conn;}/***创建一个新的数据库连接并返回它* @return* 		返回一个新创建的数据库连接*/private Connection newConnection() {/** hbase 连接 */Connection conn = null;// 创建一个数据库连接try {conn = ConnectionFactory.createConnection(hbaseConfiguration);} catch (IOException e) {log.error("创建HBase数据库连接失败!");e.printStackTrace();}// 返回创建的新的数据库连接return conn;}public synchronized void releaseConnection(Connection conn) {if (this.vcConnections == null) {log.info("连接池不存在,无法返回此连接到连接池中!!");} else {ConnectionWrapper connWrapper = null;Enumeration enumerate = this.vcConnections.elements();while(enumerate.hasMoreElements()) {connWrapper = (ConnectionWrapper) enumerate.nextElement();if (conn == connWrapper.getConnection()) {connWrapper.setBusy(false);break;}}}}class ConnectionWrapper {/*** 数据库连接*/private Connection connection = null;/*** 此连接是否正在使用的标志,默认没有正在使用*/private boolean busy = false;/*** 构造函数,根据一个 Connection 构告一个 PooledConnection 对象*/public ConnectionWrapper(Connection connection) {this.connection = connection;}/*** 返回此对象中的连接*/public Connection getConnection() {return connection;}/*** 设置此对象的连接*/public void setConnection(Connection connection) {this.connection = connection;}/*** 获得对象连接是否忙*/public boolean isBusy() {return busy;}/*** 设置对象的连接正在忙*/public void setBusy(boolean busy) {this.busy = busy;}}}

init()方法实现在初始化连接池的时候创建默认数值的连接。

五,配置操作服务类

操作类接口 HbaseService.java

package com.hbase.service;import org.apache.hadoop.hbase.client.Scan;import java.util.Map;/*** @InterfaceName: HbaseService* @author: Leemon* @Description: TODO* @date: 2023/4/12 18:11* @version: 1.0*/
public interface HbaseService {Map<String,Map<String,String>> getResultScanner(String tableName, String startRowKey, String stopRowKey);Map<String,String> getRowData(String tableName, String rowKey);Map<String,String> getFamilyValue(String tableName, String rowKey, String familyName);String getColumnValue(String tableName, String rowKey, String familyName, String columnName);Map<String,Map<String,String>> queryData(String tableName, Scan scan);}

接口实现类 HbaseServiceImpl.java

package com.hbase.service.impl;import com.hbase.config.HbaseConnectionPool;
import com.hbase.service.HbaseService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.Filter;
import org.apache.hadoop.hbase.filter.PrefixFilter;
import org.apache.hadoop.hbase.util.Bytes;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.*;/*** @ClassName: HbaseServiceImpl* @author: Leemon* @Description: TODO* @date: 2023/4/12 18:13* @version: 1.0*/
@Slf4j
@Service
public class HbaseServiceImpl implements HbaseService {@Resourceprivate HbaseConnectionPool pool;@Overridepublic Map<String,Map<String,String>> getResultScanner(String tableName, String startRowKey, String stopRowKey){Scan scan = new Scan();if(StringUtils.isNotBlank(startRowKey) && StringUtils.isNotBlank(stopRowKey)){scan.withStartRow(Bytes.toBytes(startRowKey));scan.withStopRow(Bytes.toBytes(stopRowKey));}return this.queryData(tableName,scan);}public Map<String,Map<String,String>> getResultScannerPrefixFilter(String tableName, String prefix){Scan scan = new Scan();if(StringUtils.isNotBlank(prefix)){Filter filter = new PrefixFilter(Bytes.toBytes(prefix));scan.setFilter(filter);}return this.queryData(tableName,scan);}@Overridepublic Map<String,Map<String,String>> queryData(String tableName, Scan scan){Map<String,Map<String,String>> result = new HashMap<>();ResultScanner rs = null;// 获取表Table table= null;Connection connection = null;try {connection = pool.getConnection();table = getTable(connection, tableName);rs = table.getScanner(scan);for (Result r : rs) {//每一行数据Map<String,String> columnMap = new HashMap<>();String rowKey = null;for (Cell cell : r.listCells()) {if(rowKey == null){rowKey = Bytes.toString(cell.getRowArray(),cell.getRowOffset(),cell.getRowLength());}columnMap.put(Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength()), Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}if(rowKey != null){result.put(rowKey,columnMap);}}}catch (IOException e) {log.error(MessageFormat.format("遍历查询指定表中的所有数据失败,tableName:{0}",tableName),e);}finally {close(null, rs, table, connection);}return result;}@Overridepublic Map<String,String> getRowData(String tableName, String rowKey){//返回的键值对Map<String,String> result = new HashMap<>();Get get = new Get(Bytes.toBytes(rowKey));// 获取表Table table= null;Connection connection = null;try {connection = pool.getConnection();table = getTable(connection, tableName);Result hTableResult = table.get(get);if (hTableResult != null && !hTableResult.isEmpty()) {for (Cell cell : hTableResult.listCells()) {result.put(Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength()), Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}// 某些应用场景需要插入到数据库的时间if (hTableResult.listCells().size() > 0) {result.put("Timestamp", hTableResult.listCells().get(0).getTimestamp() + "");}}}catch (IOException e) {log.error(MessageFormat.format("查询一行的数据失败,tableName:{0},rowKey:{1}",tableName,rowKey),e);}finally {close(null,null, table, connection);}return result;}@Overridepublic Map<String,String> getFamilyValue(String tableName, String rowKey, String familyName){//返回的键值对Map<String,String> result = new HashMap<>(2);Get get = new Get(Bytes.toBytes(rowKey));get.addFamily(Bytes.toBytes(familyName));// 获取表Table table= null;Connection connection = null;try {connection = pool.getConnection();table = getTable(connection, tableName);Result getResult = table.get(get);if (getResult != null && !getResult.isEmpty()) {for (Cell cell : getResult.listCells()) {result.put(Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength()), Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));}}} catch (IOException e) {log.error(MessageFormat.format("查询指定单元格的数据失败,tableName:{0},rowKey:{1},familyName:{2}", tableName, rowKey, familyName), e);}finally {close(null,null, table, connection);}return result;}@Overridepublic String getColumnValue(String tableName, String rowKey, String familyName, String columnName){String str = null;Get get = new Get(Bytes.toBytes(rowKey));// 获取表Table table= null;Connection connection = null;try {connection = pool.getConnection();table = getTable(connection, tableName);Result result = table.get(get);if (result != null && !result.isEmpty()) {Cell cell = result.getColumnLatestCell(Bytes.toBytes(familyName), Bytes.toBytes(columnName));if(cell != null){str = Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());}}} catch (IOException e) {log.error(MessageFormat.format("查询指定单元格的数据失败,tableName:{0},rowKey:{1},familyName:{2},columnName:{3}",tableName,rowKey,familyName,columnName),e);}finally {close(null,null, table, connection);}return str;}private Table getTable(Connection connection, String tableName) throws IOException {Table table = connection.getTable(TableName.valueOf(tableName));return table;}private void close(Admin admin, ResultScanner rs, Table table, Connection connection){if(admin != null){try {admin.close();} catch (IOException e) {log.error("关闭Admin失败",e);}}if(rs != null){rs.close();}if(table != null){try {table.close();} catch (IOException e) {log.error("关闭Table失败",e);}}// 释放连接if (Objects.nonNull(connection)) {pool.releaseConnection(connection);}}}

ok,现在就可以操作使用了。

以前都是在非Spring环境下使用Hbase的,一开始会出现:当服务使用时间过久,某些会使用hbase的接口调用次数过多的时候,会报【已超过最大的连接数】,只能每一次调用接口后最后一行加上释放连接。(以前的做法每次调用都要在代码里手动获取一个连接)

这次将释放连接都集成在操作服务类的实现方法中,避免了开发接口可能遗漏的错误,可能不会再出现这个问题。

相关文章:

SpringBoot使用Hbase

SpringBoot使用Hbase 文章目录 SpringBoot使用Hbase一&#xff0c;引入依赖二&#xff0c;配置文件添加自己的属性三&#xff0c;配置类注入HBASE配置四&#xff0c;配置Hbase连接池五&#xff0c;配置操作服务类 一&#xff0c;引入依赖 <dependency><groupId>org…...

SQL优化总结

SQL优化总结 1. MySQL层优化五个原则2. SQL优化策略2.1 避免不走索引的场景 3. SELECT语句其他优化3.1 避免出现select *3.2 避免出现不确定结果的函数3.3 多表关联查询时&#xff0c;小表在前&#xff0c;大表在后。3.4 使用表的别名3.5 调整Where字句中的连接顺序 附录 1. My…...

【python学习】基础篇-字典的基本操作 获取当前日期时间

1.字典的定义与创建 定义字典时&#xff0c;每个元素都包含两个部分“键”和“值”&#xff0c;在“键”和“值”之间使用冒号(:)分隔&#xff0c;相邻两个元素使用逗号分隔&#xff0c;所有元素放在一个大括号“{}”中。语法格式如下: dictionary (‘key1’:‘value1’, &quo…...

Python FreeCAD.Vector方法代码示例

Python FreeCAD.Vector方法代码示例 本文整理汇总了Python中FreeCAD.Vector方法的典型用法代码示例。如果您正苦于以下问题&#xff1a;Python FreeCAD.Vector方法的具体用法&#xff1f;Python FreeCAD.Vector怎么用&#xff1f;Python FreeCAD.Vector使用的例子&#xff1f;那…...

HDFS 梳理

HDFS客户端 客户端作用 管理文件目录文件系统操作读写 客户端生成 配置项 配置 客户端状态 缓冲相关参数&#xff0c;读写缓冲 失败切换操作 推测执行?? NN引用 NNProxy 客户端关闭 关闭IO流 修改状态 关闭RPC连接 是否有多个RPC连接&#xff1f; HDFS读 打开文件构…...

ChatGPT团队中,3个清华学霸,1个北大学霸,共9位华人

众所周知&#xff0c;美国硅谷其实有着众多的华人&#xff0c;哪怕是芯片领域&#xff0c;华为也有着一席之地&#xff0c;比如AMD 的 CEO 苏姿丰、Nvidia 的 CEO 黄仁勋 都是华人。 还有更多的美国著名的科技企业中&#xff0c;都有着华人的身影&#xff0c;这些华人&#xff…...

通过工具生成指定 类型 大小 文件

今天给大家介绍一个神器 首先 大家在开发过程中或许经常需要涉及到文件上传类的功能 需要测试文件过大 空文件等等清空 不同大小的文件 而这种文件大小是比较不好控制的 但大家可以下载我的资源 文件生成工具(可生成指定大小 类型文件) 下载下来里面就有一个 fileGeneration…...

超外差收音机的制作-电子线路课程设计-实验课

超外差收音机的制作 一、原理部分&#xff1a; 超外差收音机&#xff1a;超外差式收音机是将接收到的不同频率的高频信号全部变成一个固定的中频信号进行放大&#xff0c;因而电路对各种电台信号的放大量基本是相同的&#xff0c;这样可以使中放电路具有优良的频率特性。 超…...

TensorFlow 深度学习实战指南:1~5 全

原文&#xff1a;Hands-on Deep Learning with TensorFlow 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 本文来自【ApacheCN 深度学习 译文集】&#xff0c;采用译后编辑&#xff08;MTPE&#xff09;流程来尽可能提升效率。 不要担心自己的形象&#xff0c;只关心如…...

【数据结构】队列的实现

白日去如箭&#xff0c;达者惜今阳。 --朱敦儒目录 &#x1f681;前言&#xff1a;​ &#x1f3dd;️一.队列的概念及结构 &#x1f33b;二.队列各种功能的实现 &#x1f34d;1.队列的初始化 &#x1f3dd;️2.队列…...

【数据库】— 无损连接、Chase算法、保持函数依赖

【数据库】— 无损连接、Chase算法 Chase算法Chase算法举例一种简便方法&#xff1a;分解为两个模式时无损连接和函数依赖的一个简单例子 Chase算法 形式化定义&#xff1a; 构造一个 k k k行 n n n列的表格&#xff0c;每行对应一个模式 R i ( 1 ≤ i ≤ k ) Ri (1≤i ≤ k)…...

用英语翻译中文-汉字英文翻译

中文转英语翻译 作为一款高效、准确的中文转英语翻译软件&#xff0c;我们的产品可以帮助全球用户更好地沟通和合作&#xff0c;实现跨文化交流。 在全球化的今天&#xff0c;中英文翻译已经成为商务、学术、娱乐等各个领域不可或缺的一部分。我们的中文转英语翻译软件是为了…...

瑞吉外卖项目——缓存优化

用户数量多&#xff0c;系统访问量大 频繁访问数据库&#xff0c;系统性能下降&#xff0c;用户体验差 环境搭建 maven坐标 在项目的pom.xml文件中导入spring data redis的maven坐标: <dependency><groupId>org.springframework.boot</groupId><arti…...

从头创建一个新的浏览器,这合理吗?

从头构建一个新浏览器&#xff1f;这如果是不是个天大的“伪需求”&#xff0c;便是一场开发者的噩梦&#xff01; 要知道&#xff0c;如果没有上百亿的资金和数百名研发工程师的投入&#xff0c;从头开始构建一个新的浏览器引擎&#xff0c;几乎是不可能的。然而SerenityOS系统…...

TypeScript泛型类型和接口

本节课我们来开始了解 TypeScript 中泛型类型的概念和接口使用。 一&#xff0e;泛型类型 1. 前面&#xff0c;我们通过泛型变量的形式来存储调用方的类型从而进行检查&#xff1b; 2. 而泛型也可以作为类型的方式存在&#xff0c;理解这一点&#xff0c;先了解下函数的…...

docker命令

1.运行 docker-compose up 2.查看命令 docker images 3.删掉docker镜像: docker rmi -f [id] docker卸载 1.杀死docker有关的容器&#xff1a; docker kill $(docker ps -a -q) 2.删除所有docker容器&#xff1a;docker rm $(docker ps -a -q) 3.删除所有docker镜像&…...

2023 年 3 月 NFT 月度报告

作者&#xff1a;Danielfootprint.network 数据来源&#xff1a;NFT Monthly Report 三月份的 NFT 市场上出现了两个有趣的趋势。一方面&#xff0c;Polygon 链尽管在二月份有所突破&#xff0c;达到了 NFT 总交易量的 4.2%&#xff0c;但于三月再次跌至 1% 以下&#xff0c;…...

【http】 get方法和Post方法区别;http和https

get方法和Post方法 get方法&#xff1a;通过url传参&#xff0c;回显输入的私密信息&#xff0c;不够私密 Post方法&#xff1a;通过正文传参&#xff0c;不会回显&#xff0c;一般私密性有保证。 一般如果上传的图片&#xff0c;音频比较大&#xff0c;推荐Post方法&#x…...

第三章 法的渊源与法的分类

目录 第一节 法的渊源的分类 一、法的渊源释义二、法的渊源种类 第二节 正式法源 一、正式法源的含义二、当代中国的正式法源三、正式法源的一般效力原则 第三节 非正式法源 一、当代中国的非正式法源 第四节 法的分类 一、法的一般分类二、法的特殊分类 第一节 法的渊源的…...

在Ubuntu18.04或者20.04下搭建edk2运行环境

#更新完之后依次执行下面两条命令 1.apt-get update 2.apt-get upgrade 如果执行之后出现源不能更新的问题,到/etc/apt/sources.list.d 下删除对应的ppa源重新更新即可解决 git clone https://github.com/tianocore/edk2.git cd edk2 git submodule update --init 如果git cl…...

AI Agent Harness Engineering 产品经理指南:如何定义智能体的“人设”与能力边界?

AI Agent Harness Engineering 产品经理指南:如何定义智能体的「人设」与能力边界 关键词:AI Agent、智能体管控工程(Harness Engineering)、产品经理、人设对齐、能力边界、智能体治理、生成式AI落地 摘要 随着生成式AI技术的成熟,AI Agent已经从概念验证阶段进入大规…...

个人自动化技能库构建指南:从Python脚本到Cron定时任务

1. 项目概述&#xff1a;一个为“摸鱼”场景设计的自动化技能库最近在GitHub上看到一个挺有意思的项目&#xff0c;叫my-copaw-skill。光看这个名字&#xff0c;就透着一股子“打工人”的幽默感——“copaw”这个词&#xff0c;我琢磨着应该是“copilot”&#xff08;副驾驶/助…...

对比直接使用厂商 API 体验 Taotoken 在模型切换上的便利性

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 对比直接使用厂商 API 体验 Taotoken 在模型切换上的便利性 在个人开发项目中接入大模型时&#xff0c;开发者通常面临一个选择&am…...

从零到一:Android Studio集成Uniapp离线SDK打包实战

1. 环境准备&#xff1a;工具选择与版本匹配 第一次接触Uniapp离线打包时&#xff0c;最让我头疼的就是工具版本匹配问题。记得去年接手一个混合开发项目时&#xff0c;因为HBuilderX和SDK版本不兼容&#xff0c;整整浪费了两天时间排查问题。为了避免大家重蹈覆辙&#xff0c…...

进化算法驱动机械爪设计优化:从原理到EvoClaw项目实践

1. 项目概述与核心价值最近在GitHub上看到一个挺有意思的项目&#xff0c;叫“EvoClaw”。光看这个名字&#xff0c;可能有点摸不着头脑&#xff0c;但点进去一看&#xff0c;发现这是一个关于“进化算法驱动的机械爪设计优化”的开源项目。简单来说&#xff0c;就是利用计算机…...

JVM调优实战:让你的服务性能提升50%

一、背景 线上一个核心订单服务&#xff0c;QPS 3000左右&#xff0c;经常出现接口超时告警。监控显示&#xff1a; 平均RT: 180ms&#xff08;要求<100ms&#xff09;Full GC频率: 每天20次&#xff0c;每次STW 1.5sCPU使用率: 峰值85%服务规格: 8C16G&#xff0c;堆内存…...

避坑指南:Unity游戏在Linux上运行报错?OpenCV依赖和文件权限问题排查实录

Unity游戏Linux部署避坑指南&#xff1a;从权限修复到OpenCV依赖全解析 当你在Ubuntu上双击那个刚导出的Unity游戏.x86_64文件时&#xff0c;屏幕却弹出一行冰冷的错误信息——这种从云端跌入谷底的体验&#xff0c;每个跨平台开发者都经历过。不同于Windows的一键运行&#xf…...

Unity游戏开发集成MCP协议:AI助手自动化操作指南

1. 项目概述&#xff1a;Unity游戏开发中的MCP革命如果你是一名Unity开发者&#xff0c;最近可能已经注意到一个名为“CoderGamester/mcp-unity”的项目在GitHub上悄然走红。这不仅仅是一个普通的插件或工具包&#xff0c;它代表了一种全新的工作流范式&#xff0c;旨在将大型语…...

人性最残忍的真相是:你越不把自己当回事,别人就越不把你当回事

那个总给别人买贵东西的人,最后都怎么样了? 目录 那个总给别人买贵东西的人,最后都怎么样了? 我们为什么会忍不住过度付出? 真正的爱,从来都不是单方面的牺牲 爱自己,是所有健康关系的前提 昨天刷到一句话,瞬间戳中了我:“永远不要拿自己辛苦钱,去给别人买自己都舍不…...

基于Circuit Playground Express与NeoPixel的四季交互灯光装置设计与实现

1. 项目概述与核心思路几年前&#xff0c;我在一个艺术展上看到一组悬挂在枯树枝上的玻璃瓶&#xff0c;里面装着会呼吸般变幻光线的LED灯&#xff0c;那种静谧又灵动的美感让我念念不忘。作为一个喜欢把代码和电路“藏”进生活场景里的硬件爱好者&#xff0c;我一直在琢磨如何…...