微服务seata解析部署使用全流程

官网地址: Seata 是什么? | Apache Seata

1、Seata术语

用来管理分布式事务,由阿里巴巴出品。

【1、TC (Transaction Coordinator) - 事务协调者】

用来维护事务的,包括主事务和分支事务。

【2、TM (Transaction Manager) - 事务管理器】

管理事务的,决定了事务什么时候开启,什么时候结束,提交还是回滚。

【3、RM (Resource Manager) - 资源管理器】

监视分支事务的状态,和TC做数据交互,把分支事务状态告诉TC。

2、SEATA 的分布式事务解决方案

seata提供了4种方式,分别是AT、TCC、SAGA、XA

①AT----该模式是Seata中最常用的模式,使用于大多数业务场景,特别是对性能要求较高时,(通过记录数据的快照,来支持事务的回滚)

原理:事务执行中Seata会保存数据执行前的快照,提交时,如果发生异常时就会回滚

优点:实现简单,性能高,适用于读多写少的场景

缺点:对数据库要求高

②TCC---适用于业务逻辑复杂,需要严格控制使用场景

三个阶段:try(尝试)、confirm(确认)、Cancke(取消)

原理:try执行预留操作,锁定必要资源、confirm如果操作都成功,确认操作、Cancle如果某操作失败,则取消所有操作

优点:控制力强,适合需要一致性的复杂业务场景

缺点:实现复杂

③Saga---长事务处理方式

使用:适用于微服务架构中,将大事务分解成小事务,实现事务的一致性和可靠性,具有继承性,可靠性和强一致性

优点:性能高,无锁,参与者可异步,高吞吐,实现简单

缺点:没有锁,会哟脏写,时效性差

④AX----使用两个阶段提交,保证事务的一致性和可靠性

原理:所有参与的资源管理器再提交前准备好,记录事务状态

优点:一致性、可靠性、标准化

缺点:会引入额外的性能开销,导致延迟增加、有阻塞风险,影响系统的吞吐量和并发性、易发生单点故障

3、安装seata 【13分钟】

1、基于操作系统环境安装

Releases · apache/incubator-seata · GitHub

2、拉取docker镜像

复制代码
docker pull seataio/seata-server:1.3.0

3、拷贝配置文件

先启动seata,将seata-server目录下的文件拷贝到虚拟机中

#执行命令1:

docker run -d --name seata -p 8091:8091 seataio/seata-server:1.3.0

虚拟机里,创建/usr/local/docker/seata目录。

然后执行拷贝任务,拷贝seata:/seata-server 里的资源到/usr/local/docker/seata目录下。

#执行命令2:

docker cp seata:/seata-server /usr/local/docker/seata

【file.conf文件】

file.conf 文件,用来告诉seata 数据存放再哪里的。

修改store.mode为db,修改db相关配置,保存该文件在宿主机本地

transaction log store, only used in seata-server

store {

store mode: file、db、redis

mode = "db"

file store property

file {

store location dir

dir = "sessionStore"

branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions

maxBranchSessionSize = 16384

globe session size , if exceeded throws exceptions

maxGlobalSessionSize = 512

file buffer size , if exceeded allocate new buffer

fileWriteBufferCacheSize = 16384

when recover batch read size

sessionReloadReadSize = 100

async, sync

flushDiskMode = async

}

database store property

db {

the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.

datasource = "druid"

mysql/oracle/postgresql/h2/oceanbase etc.

dbType = "mysql"

driverClassName = "com.mysql.cj.jdbc.Driver"

url = "jdbc:mysql://192.168.43.8:3306/seata"

user = "root"

password = "123456"

minConn = 5

maxConn = 30

globalTable = "global_table"

branchTable = "branch_table"

lockTable = "lock_table"

queryLimit = 100

maxWait = 5000

}

redis store property

redis {

host = "127.0.0.1"

port = "6379"

password = ""

database = "0"

minConn = 1

maxConn = 10

queryLimit = 100

}

}

【registry.conf】

registry.conf 告诉seata,我们的注册中心和配置中心用的是什么,保存该文件在宿主机本地。

修改类型为nacos,修改nacos相关配置,包括registry和config的两组。在nacos中为seata创建一个属于自己的命名空间,它的配置比较多,避免和其他配置公用。

[Linux启动nacos,配置新的命名空间]

registry {

file 、nacos 、eureka、redis、zk、consul、etcd3、sofa

type = "nacos"

nacos {

application = "seata-server"

serverAddr = "192.168.43.8:8848"

group = "SEATA_GROUP"

namespace = "6bb9bfd3-2af4-4fd8-8f75-c91482ba43f8"

cluster = "default"

username = "nacos"

password = "nacos"

}

eureka {

serviceUrl = "http://localhost:8761/eureka"

application = "default"

weight = "1"

}

redis {

serverAddr = "localhost:6379"

db = 0

password = ""

cluster = "default"

timeout = 0

}

zk {

cluster = "default"

serverAddr = "127.0.0.1:2181"

sessionTimeout = 6000

connectTimeout = 2000

username = ""

password = ""

}

consul {

cluster = "default"

serverAddr = "127.0.0.1:8500"

}

etcd3 {

cluster = "default"

serverAddr = "http://localhost:2379"

}

sofa {

serverAddr = "127.0.0.1:9603"

application = "default"

region = "DEFAULT_ZONE"

datacenter = "DefaultDataCenter"

cluster = "default"

group = "SEATA_GROUP"

addressWaitTime = "3000"

}

file {

name = "file.conf"

}

}

config {

file、nacos 、apollo、zk、consul、etcd3

type = "nacos"

nacos {

serverAddr = "192.168.43.8:8848"

group = "SEATA_GROUP"

namespace = "6bb9bfd3-2af4-4fd8-8f75-c91482ba43f8"

username = "nacos"

password = "nacos"

}

consul {

serverAddr = "127.0.0.1:8500"

}

apollo {

appId = "seata-server"

apolloMeta = "http://192.168.1.204:8801"

namespace = "application"

}

zk {

serverAddr = "127.0.0.1:2181"

sessionTimeout = 6000

connectTimeout = 2000

username = ""

password = ""

}

etcd3 {

serverAddr = "http://localhost:2379"

}

file {

name = "file.conf"

}

}

4、创建seata在nacos配置中心的配置文件

官方文件模板所在路径: https://github.com/seata/seata/blob/develop/script/config-center/config.txt

创建一个config.txt文件,将以下内容改成自己的信息,粘贴进去保存。

#For details about configuration items, see https://seata.io/zh-cn/docs/user/configurations.html

#Transport configuration, for client and server

transport.type=TCP

transport.server=NIO

transport.heartbeat=true

transport.enableTmClientBatchSendRequest=false

transport.enableRmClientBatchSendRequest=true

transport.enableTcServerBatchSendResponse=false

transport.rpcRmRequestTimeout=30000

transport.rpcTmRequestTimeout=30000

transport.rpcTcRequestTimeout=30000

transport.threadFactory.bossThreadPrefix=NettyBoss

transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker

transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler

transport.threadFactory.shareBossWorker=false

transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector

transport.threadFactory.clientSelectorThreadSize=1

transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread

transport.threadFactory.bossThreadSize=1

transport.threadFactory.workerThreadSize=default

transport.shutdown.wait=3

transport.serialization=seata

transport.compressor=none

#Transaction routing rules configuration, only for the client

---------------------------------------------------

service.vgroupMapping.my_tx_group=default

---------------------------------------------------

#If you use a registry, you can ignore it

service.default.grouplist=127.0.0.1:8091

service.enableDegrade=false

service.disableGlobalTransaction=false

#Transaction rule configuration, only for the client

client.rm.asyncCommitBufferLimit=10000

client.rm.lock.retryInterval=10

client.rm.lock.retryTimes=30

client.rm.lock.retryPolicyBranchRollbackOnConflict=true

client.rm.reportRetryCount=5

client.rm.tableMetaCheckEnable=true

client.rm.tableMetaCheckerInterval=60000

client.rm.sqlParserType=druid

client.rm.reportSuccessEnable=false

client.rm.sagaBranchRegisterEnable=false

client.rm.sagaJsonParser=fastjson

client.rm.tccActionInterceptorOrder=-2147482648

client.tm.commitRetryCount=5

client.tm.rollbackRetryCount=5

client.tm.defaultGlobalTransactionTimeout=60000

client.tm.degradeCheck=false

client.tm.degradeCheckAllowTimes=10

client.tm.degradeCheckPeriod=2000

client.tm.interceptorOrder=-2147482648

client.undo.dataValidation=true

client.undo.logSerialization=jackson

client.undo.onlyCareUpdateColumns=true

server.undo.logSaveDays=7

server.undo.logDeletePeriod=86400000

client.undo.logTable=undo_log

client.undo.compress.enable=true

client.undo.compress.type=zip

client.undo.compress.threshold=64k

#For TCC transaction mode

tcc.fence.logTableName=tcc_fence_log

tcc.fence.cleanPeriod=1h

#Log rule configuration, for client and server

log.exceptionRate=100

#Transaction storage configuration, only for the server. The file, db, and redis configuration values are optional.

---------------------------------------------------

store.mode=db

store.lock.mode=db

store.session.mode=db

---------------------------------------------------

#Used for password encryption

store.publicKey=

#If `store.mode,store.lock.mode,store.session.mode` are not equal to `file`, you can remove the configuration block.

store.file.dir=file_store/data

store.file.maxBranchSessionSize=16384

store.file.maxGlobalSessionSize=512

store.file.fileWriteBufferCacheSize=16384

store.file.flushDiskMode=async

store.file.sessionReloadReadSize=100

#These configurations are required if the `store mode` is `db`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `db`, you can remove the configuration block.

store.db.datasource=druid

store.db.dbType=mysql

---------------------------------------------------

store.db.driverClassName=com.mysql.cj.jdbc.Driver

store.db.url=jdbc:mysql://192.168.43.8:3306/seata?useUnicode=true&rewriteBatchedStatements=true

store.db.user=root

store.db.password=123456

---------------------------------------------------

store.db.minConn=5

store.db.maxConn=30

store.db.globalTable=global_table

store.db.branchTable=branch_table

store.db.distributedLockTable=distributed_lock

store.db.queryLimit=100

store.db.lockTable=lock_table

store.db.maxWait=5000

#These configurations are required if the `store mode` is `redis`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `redis`, you can remove the configuration block.

store.redis.mode=single

store.redis.single.host=127.0.0.1

store.redis.single.port=6379

store.redis.sentinel.masterName=

store.redis.sentinel.sentinelHosts=

store.redis.maxConn=10

store.redis.minConn=1

store.redis.maxTotal=100

store.redis.database=0

store.redis.password=

store.redis.queryLimit=100

#Transaction rule configuration, only for the server

server.recovery.committingRetryPeriod=1000

server.recovery.asynCommittingRetryPeriod=1000

server.recovery.rollbackingRetryPeriod=1000

server.recovery.timeoutRetryPeriod=1000

server.maxCommitRetryTimeout=-1

server.maxRollbackRetryTimeout=-1

server.rollbackRetryTimeoutUnlockEnable=false

server.distributedLockExpireTime=10000

server.xaerNotaRetryTimeout=60000

server.session.branchAsyncQueueSize=5000

server.session.enableBranchAsyncRemove=false

server.enableParallelRequestHandle=false

#Metrics configuration, only for the server

metrics.enabled=false

metrics.registryType=compact

metrics.exporterList=prometheus

metrics.exporterPrometheusPort=9898

修改的内容

service.vgroupMapping.my_tx_group=default

store.mode=db

store.lock.mode=db

store.session.mode=db

store.db.driverClassName=com.mysql.cj.jdbc.Driver

store.db.url=jdbc:mysql://192.168.43.8:3306/seata?useUnicode=true&rewriteBatchedStatements=true

store.db.user=root

store.db.password=123456

5、创建导入config.txt到nacos的脚本

官方文件模板所在路径: https://github.com/seata/seata/blob/develop/script/config-center/nacos/nacos-config.sh

创建 nacos-config.sh 文件,粘贴以下内容,没有内容更改。

#!/bin/sh

Copyright 1999-2019 Seata.io Group.

Licensed under the Apache License, Version 2.0 (the "License");

you may not use this file except in compliance with the License.

You may obtain a copy of the License at、

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software

distributed under the License is distributed on an "AS IS" BASIS,

WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

See the License for the specific language governing permissions and

limitations under the License.

while getopts ":h:p:g:t:u:w:" opt

do

case $opt in

h)

host=$OPTARG

;;

p)

port=$OPTARG

;;

g)

group=$OPTARG

;;

t)

tenant=$OPTARG

;;

u)

username=$OPTARG

;;

w)

password=$OPTARG

;;

?)

echo " USAGE OPTION: $0 [-h host] [-p port] [-g group] [-t tenant] [-u username] [-w password] "

exit 1

;;

esac

done

if [ -z ${host} ]; then

host=localhost

fi

if [ -z ${port} ]; then

port=8848

fi

if [ -z ${group} ]; then

group="SEATA_GROUP"

fi

if [ -z ${tenant} ]; then

tenant=""

fi

if [ -z ${username} ]; then

username=""

fi

if [ -z ${password} ]; then

password=""

fi

nacosAddr=host:port

contentType="content-type:application/json;charset=UTF-8"

echo "set nacosAddr=$nacosAddr"

echo "set group=$group"

urlencode() {

length="${#1}"

i=0

while [ length -gt i ]; do

char="{1:i:1}"

case $char in

a-zA-Z0-9.\~_-\]) printf $char ;; \*) printf '%%%02X' "'$char" ;; esac i=\`expr $i + 1\` done } failCount=0 tempLog=$(mktemp -u) function addConfig() { dataId=\`urlencode $1\` content=\`urlencode $2\` curl -X POST -H "${contentType}" "http://$nacosAddr/nacos/v1/cs/configs?dataId=$dataId\&group=$group\&content=$content\&tenant=$tenant\&username=$username\&password=$password" \>"${tempLog}" 2\>/dev/null if \[ -z $(cat "${tempLog}") \]; then echo " Please check the cluster status. " exit 1 fi if \[ "$(cat "${tempLog}")" == "true" \]; then echo "Set $1=$2 successfully " else echo "Set $1=$2 failure " failCount=\`expr $failCount + 1\` fi } count=0 COMMENT_START="#" for line in $(cat $(dirname "$PWD")/config.txt \| sed s/\[\[:space:\]\]//g); do if \[\[ "$line" =\~ \^"${COMMENT_START}".\* \]\]; then continue fi count=\`expr $count + 1\` key=${line%%=\*} value=${line#\*=} addConfig "${key}" "${value}" done echo "=========================================================================" echo " Complete initialization parameters, total-count:$count , failure-count:$failCount " echo "=========================================================================" if \[ ${failCount} -eq 0 \]; then echo " Init nacos config finished, please start seata-server. " else echo " init nacos config fail. " fi

6、导入nacos配置

#循环 不需要确认 删除 某一目录以及该目录下的文件和子目录。

rm -rf seata-server

将 config.txt文件添加到seata文件夹里,同时创建子目录nacos;将nacos-config.sh文件放到nacos目录里。

导入前要启动nacos并关闭防火墙,执行如下命令:为该文件分配一个执行的权限。

复制代码
#命令1:为该文件分配一个执行的权限。
chmod +x nacos-config.sh

修改下面命令里的内容,包括ip和Id。

#命令2:

sh nacos-config.sh -h 192.168.43.8 -p 8848 -g SEATA_GROUP -t 6bb9bfd3-2af4-4fd8-8f75-c91482ba43f8 -u nacos -w nacos

报错说含/r的错误,是因为windows下文件的换行符合Linux不同导致的,执行以下命令:

#命令3:

sed -i 's/\r//' nacos-config.sh

#然后再重新执行一遍命令2:

sh nacos-config.sh -h 192.168.43.8 -p 8848 -g SEATA_GROUP -t 6bb9bfd3-2af4-4fd8-8f75-c91482ba43f8 -u nacos -w nacos

7、复制配置文件

seata目录下原资源可以全部删掉了。

将file.conf和registry.conf文件复制到/usr/local/docker/seata/config下,为再次创建seata容器做配置准备。

为config目录授权:

复制代码
chmod 777 config

8、关闭并删除之前的seata容器

停掉刚才启动的seata,而且它以后也用不到了,可以删除。

9、数据库配置

启动seata需要有以下几张表的基础支持,所以在启动前,先创建如下数据库表。启动mysql数据库。

seata需要创建三张表:

全局事务---global_table

分支事务---branch_table

全局锁-----lock_table

建表语句

DROP TABLE

IF

EXISTS `global_table`;

CREATE TABLE `global_table` (

`xid` VARCHAR ( 128 ) NOT NULL,

`transaction_id` BIGINT,

`status` TINYINT NOT NULL,

`application_id` VARCHAR ( 32 ),

`transaction_service_group` VARCHAR ( 32 ),

`transaction_name` VARCHAR ( 64 ),

`timeout` INT,

`begin_time` BIGINT,

`application_data` VARCHAR ( 2000 ),

`gmt_create` datetime,

`gmt_modified` datetime,

PRIMARY KEY ( `xid` ),

KEY `idx_gmt_modified_status` ( `gmt_modified`, `status` ),

KEY `idx_transaction_id` ( `transaction_id` )

);

DROP TABLE

IF

EXISTS `branch_table`;

CREATE TABLE `branch_table` (

`branch_id` BIGINT NOT NULL,

`xid` VARCHAR ( 128 ) NOT NULL,

`transaction_id` BIGINT,

`resource_group_id` VARCHAR ( 32 ),

`resource_id` VARCHAR ( 256 ),

`lock_key` VARCHAR ( 128 ),

`branch_type` VARCHAR ( 8 ),

`status` TINYINT,

`client_id` VARCHAR ( 64 ),

`application_data` VARCHAR ( 2000 ),

`gmt_create` datetime,

`gmt_modified` datetime,

PRIMARY KEY ( `branch_id` ),

KEY `idx_xid` ( `xid` )

);

DROP TABLE

IF

EXISTS `lock_table`;

CREATE TABLE `lock_table` (

`row_key` VARCHAR ( 128 ) NOT NULL,

`xid` VARCHAR ( 96 ),

`transaction_id` LONG,

`branch_id` LONG,

`resource_id` VARCHAR ( 256 ),

`table_name` VARCHAR ( 100 ),

`pk` VARCHAR ( 36 ),

`gmt_create` datetime,

`gmt_modified` datetime,

PRIMARY KEY ( `row_key` )

);

10、启动seata

在执行启动命令前要先配置seata数据库

docker run --name seata \

-p 8091:8091 \

-e SEATA_IP=192.168.43.8 \

-e SEATA_PORT=8091 \

-e SEATA_CONFIG_NAME=file:/root/seata-config/registry \

-v /usr/local/docker/seata/config:/root/seata-config \

-d seataio/seata-server:1.3.0

查看日志信息,能看到端口号8091 就是启动成功了。

#查看上面的启动命令日志:

docker logs -f seata

4、应用seata

1.准备项目:

创建两个seata工程,分别是seata1 和 seata2,还是以openfeign工程做为例子,实现整合mybatis连接数据库两张表的添加功能。

2.准备数据库表:

#建表代码

CREATE TABLE `score` (

`id` varchar(50) NOT NULL,

`name` varchar(50) NULL,

`score` double(7, 2) NULL ,

PRIMARY KEY (`id`) USING BTREE

)

CREATE TABLE `user` (

`id` varchar(50) NOT NULL,

`name` varchar(50) NULL,

`password` varchar(50) NULL,

PRIMARY KEY (`id`) USING BTREE

)

##undo_log表的创建语句,在下面的4.2里。

3.准备阶段,运行项目

【正常运行】

没有异常,成功运行,两张表里都有数据。

【添加异常】

添加异常,失败运行,两张表都添加数据成功了居然

【添加Spring事务】

两个工程添加事务注解,成绩添加数据成功,用户添加数据失败

===以上是分布式的情况下,事务没有统一管理。

4.使用seata

以下操作,每个工程项目里都操作一遍。

1、添加依赖

<dependency>

<groupId>com.alibaba.cloud</groupId>

<artifactId>spring-cloud-starter-alibaba-seata</artifactId>

</dependency>

2、各自数据库中创建UNDO_LOG表

给每个微服务的数据库都创建这张表才能应用seata

要求:具有InnoDB引擎的MySQL。

-- 注意此处0.3.0+ 增加唯一索引 ux_undo_log

CREATE TABLE `undo_log` (

`id` BIGINT ( 20 ) NOT NULL AUTO_INCREMENT,

`branch_id` BIGINT ( 20 ) NOT NULL,

`xid` VARCHAR ( 100 ) NOT NULL,

`context` VARCHAR ( 128 ) NOT NULL,

`rollback_info` LONGBLOB NOT NULL,

`log_status` INT ( 11 ) NOT NULL,

`log_created` datetime NOT NULL,

`log_modified` datetime NOT NULL,

`ext` VARCHAR ( 100 ) DEFAULT NULL,

PRIMARY KEY ( `id` ),

UNIQUE KEY `ux_undo_log` ( `xid`, `branch_id` )

) ENGINE = INNODB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8;

3、修改启动类

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)

4、添加配置文件

在配置文件application.yml中,添加如下配置信息:

seata:

application-id: ${spring.application.name}

enabled: true

tx-service-group: my_tx_group

registry:

type: nacos

nacos:

server-addr: 172.19.186.247:8848

namespace: c05aaf00-2701-4d2e-8710-318752481731

group: SEATA_GROUP

username: nacos

password: nacos

config:

type: nacos

nacos:

server-addr: 172.19.186.247:8848

namespace: c05aaf00-2701-4d2e-8710-318752481731

group: SEATA_GROUP

username: nacos

password: nacos

service:

vgroup-mapping:

my_tx_group: default

feign:

httpclient:

connection-timeout: 600000

connection-timer-repeat: 30000

tx-service-group: my_tx_group

service: vgroup-mapping: my_tx_group: default

与nacos的配置要一致,nacos的配置是tx-service-group.my_tx_group=default

5、添加数据源配置

com.jr.config包下,创建下面的配置文件类。

import com.alibaba.druid.pool.DruidDataSource;

import io.seata.rm.datasource.DataSourceProxy;

import org.springframework.boot.context.properties.ConfigurationProperties;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.annotation.Primary;

@Configuration

public class DataSourceProxyConfig {

@Bean

@ConfigurationProperties(prefix = "spring.datasource")

public DruidDataSource druidDataSource() {

return new DruidDataSource();

}

@Bean

@Primary

public DataSourceProxy dataSourceProxy(DruidDataSource druidDataSource) {

return new DataSourceProxy(druidDataSource);

}

}

6、添加事务注解

更改之前ServletImpl类方法里的事务注解@Transactional(rollbackFor = Exception.class),改为下面注解:

@GlobalTransactional(rollbackFor = Exception.class,timeoutMills = 300000)

7、完成上述配置,运行结果

【有bug代码时】

两张表里都没有添加进数据,事务回滚。

【没有bug代码时】

数据添加成功

8、解决报错

相关推荐
前端市界9 小时前
用 React 手搓一个 3D 翻页书籍组件,呼吸海浪式翻页,交互体验带感!
前端·架构·github
文艺理科生9 小时前
Nginx 路径映射深度解析:从本地开发到生产交付的底层哲学
前端·后端·架构
C澒9 小时前
Vue 项目渐进式迁移 React:组件库接入与跨框架协同技术方案
前端·vue.js·react.js·架构·系统架构
消失的旧时光-19439 小时前
从 Kotlin 到 Dart:为什么 sealed 是处理「多种返回结果」的最佳方式?
android·开发语言·flutter·架构·kotlin·sealed
惊讶的猫10 小时前
OpenFeign(声明式HTTP客户端)
网络·网络协议·http·微服务·openfeign
鹏北海10 小时前
micro-app 微前端项目部署指南
前端·nginx·微服务
L5434144610 小时前
告别代码堆砌匠厂架构让你的系统吞吐量翻倍提升
大数据·人工智能·架构·自动化·rpa
子春一11 小时前
Flutter for OpenHarmony:色彩捕手:基于 CIELAB 色差模型与人眼感知的高保真色彩匹配游戏架构解析
flutter·游戏·架构
冻感糕人~12 小时前
收藏备用|小白&程序员必看!AI Agent入门详解(附工业落地实操关联)
大数据·人工智能·架构·大模型·agent·ai大模型·大模型学习
ai_xiaogui12 小时前
【开源前瞻】从“咸鱼”到“超级个体”:谈谈 Panelai 分布式子服务器管理系统的设计架构与 UI 演进
服务器·分布式·架构·分布式架构·panelai·开源面板·ai工具开发