IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Ceph RGW对象存储 -> 正文阅读

[移动开发]Ceph RGW对象存储

目录

1.对象存储概述

1.1 基本概念

1.2 认证与授权方式

1.3 RADOS网关

1.4 rados网关部署步骤

1.5 什么是S3存储

1.5.1 rgw中s3的API支持

1.5.2 S3中的用户管理

1.5.3 管理用户密钥

1.5.4 S3设置配额数

1.5.5 检索用户信息

1.5.6 统计数据

1.5.7 配置DNS实现数据传输

1.5.8 启用S3-api客户端s3cmd

1.5.9 Bucket常用操作

1.6 什么是Swift

1.6.1 Swift-API操作

1.6.2 Swift用户管理

1.6.3 Swift客户端

1.6.4 swift读写练习

1.7 Ceph多区域网关

1.7.1 Periods和Epochs

1.7.2 多区域同步流程

1.7.3 多区域网关配置

1.7.4 故障恢复与切换

1.7.5 迁移Single-Zone至Multi-Zone


1.对象存储概述

对象是对象存储系统中数据存储的基本单位,每个Object是数据和数据属性集的综合体,数据属性可以根据应用的需求进行设置,包括数据分布、服务质量等每个对象自我维护其属性,从而简化了存储系统的管理任务对象的大小可以不同,甚至可以包含整个数据结构,如文件、数据库表项等对象存储系统一般是一类智能设备,它具有自己的存储介质、处理器、内存以及网络系统等,负责管理本地的对象,是对象存储系统的核心

  • 对象存储(Object Storage)是无层次结构的数据存储方法,通常用于云计算环境中
  • 不同于其他数据存储方法,基于对象的存储不使用目录树
    • 数据作为单独的对象进行存储
    • 数据并不放置在目录层次结构中,而是存在于平面地址空间内的同一级别
    • 应用通过唯一地址来识别每个单独的数据对象
    • 每个对象可包含有助于检索的元数据
    • 专为使用API在应用级别(而非用户级别)进行访问而设计

1.1 基本概念

虽然在设计与实现上有所区别,但大多数对象存储系统对外呈现的核心资源类型大同小异

  • Amazon S3:提供了user、bucket和object分别表示用户、存储桶和对象,其中bucket隶属于user,因此user名称即可做为bucket的名称空间,不同用户允许使用相同名称的bucket

  • OpenStack Swift:提供了user、container和object分别对应于用户、存储桶和对象,不过它还额外为user提供了父级组件account,用于表示一个项目或租户,因此一个account中可包含一到多个user,它们可共享使用同一组container,并为container提供名称空间

  • RadosGW:提供了user、subuser、bucket和object,其中的user对应于S3的user,而subuser则对应于Swift的user,不过user和subuser都不支持为bucket提供名称空间,因此,不同用户的存储桶也不允许同名;不过,自Jewel版本起,RadosGW引入了tenant(租户)用于为user和bucket提供名称空间,但它是个可选组件

  • Jewel版本之前,radosgw的所有user位于同一名称空间,它要求所有user的ID必须惟一,并且即便是不同user的bucket也不允许使用相同的bucket ID

各pool的意义

  • 当创建RGW时候默认会创建对应的池信息,不需要人为创建
rgw.root 
default.rgw.control        #控制器信息
default.rgw.meta           #记录元数据
default.rgw.log            #日志信息
default.rgw.buckets.index  #为rgw的bucket信息
default.rqw.buckets.data   #是实际存储的数据信息

1.2 认证与授权方式

S3和Swift使用了不同的认证机制

  • 用户账号是认证(Authentication)、授权(Authorization)及存储配额(Quota)功能的载体,RGW依赖它对RESTfulAPI进行请求认证、控制资源(存储桶和对象等)的访问权限并设定可用存储空间上限
    • S3主要采用的是基于访问密钥(access key)和私有密钥(secret key)进行认证,RGW兼容其V2和V4两种认证机制,其中V2认证机制支持本地认证、LDAP认证和kerberos认证三种方式,所有未能通过认证的用户统统被视为匿名用户

    • Swift结合Swift私有密钥(swift key)使用令牌(token)认证方式,它支持临时URL认证、本地认证、OpenStack Keystone认证、第三方认证和匿名认证等方式

  • 通过身份认证后,RGW针对用户的每次资源操作请求都会进行授权检查,仅那些能够满足授权定义(ACL)的请求会被允许执行

    • S3使用bucket acl和object acl分别来控制bucket和object的访问控制权限,一般用于向bucket或object属主之外的其它用户进行授权
    • Swift API中的权限控制则分为user访问控制列表和bucket访问控制列表两种,前一种针对user进行设定,而后一定则专用于bucket及内部的object,且只有read和write两种权限

1.3 RADOS网关

为了支持通用的云存储功能,Ceph在RADOS集群的基础上提供了RGW(RADOS GateWay)数据抽象和管理层,它是原生兼容S3和SwiftAPI的对象存储服务,支持数据压缩和多站点(Multi-Site)多活机制,并支持NFS协议访问接口等特性。RADOS网关也称为Ceph对象网关、RADOSGW、RGW,是一种服务,使客户端能够利用标准对象存储API来访问Ceph集群。它支持S3和Swift API

  • radosgw的http/https服务由内建的Civeweb提供,它同时也能支持多种主流的Web服务程序以代理的形式接收用户请求并转发至ceph-radosgw进程,这些Web服务程序包括nginx和haproxy等

  • rgw客户端通过s3或者swift api使用rgw用户进行身份验证,S3和Swift是RESTful风格的API,它们基于http/https协议完成通信和数据交换。然后rgw网关代表用户利用cephx与ceph存储进行身份验证

功能概述

RGW的功能依赖于Ceph对象网关守护进程(ceph-radosgw)实现,它负责向客户端提供RESTAPI接口,并将数据操作请求转换为底层RADOS存储集群的相关操作

  • 出于冗余及负载均衡的需要,一个Ceph集群上的ceph-radosgw守护进程通常不止一个,这些支撑同一对象存储服务的守护进程联合起来构成一个zone(区域)用于代表一个独立的存储服务和存储空间

  • 在容灾设计的架构中,管理员会基于两个或以上的Ceph集群定义出多个zone,这些zone之间通过同步机制实现冗余功能,并组成一个新的父级逻辑组件zonegroup

企业级部署架构

以下图为生产环境常用架构方式

正在上传…重新上传取消

1.4 rados网关部署步骤

  • 手工开启方式
#1.生成用于网关验证的cephx用户
ceph auth get-or-create client.rgw.servera mon 'allow rwx' osd 'allow rwx' -o /etc/ceph/ceph.client.rgw.servera.keyring 

#2.修改ceph.conf配置文件
[client.rgw.servera]
host = server
keyring = /etc/ceph/ceph.client.rgw.servera.keyring
rgw_frontends = civetweb port=80  #默认端口7480

#3.安装ceph-radosgw
yum install -y ceph-radosgw

#4.启动ceph-radosgw
systemctl restart ceph-radosgw@rgw.servera

配置Citeweb

  • 自0.80版本起,Ceph放弃了基于apache和fastcgi提供radosgw服务的传统而代之以默认嵌入在ceph-radosgw进程中的Citeweb,这种新的实现方式更加轻便和简洁,但直到Ceph 11.0.1版本,Citeweb才开始支持SSL协议

  • Citeweb默认监听于TCP协议的7480端口提供http服务,修改配置需要编辑ceph.conf配置文件,以如下格式进行定义

  • 配置https

    • 额外添加参数ssl certificate=/PATH/TO/PEM FILE
    • 定义port=443s,或者port=80+443s
[client.rgw.<gateway-node>]
rgw host=<hostname OR ipaddr>
rgw frontends="civetweb port=80"

#配置完成后需要重启ceph-radosgw进程以生效新配置
systemctl restart ceph-radosgw@rgw.<gateway-node>

常用的配置项

参数选项信息描述
ssl_certificate配置默认https的证书位置开启加密访问(生产基本不用,因为会在前加个负载均衡器)
access_log_ file定义访问日志的路径
error_log_file定义错误日志的路径
num_threadsCiteweb以线程模型处理客户端请求,它为每个连接请求分配一个专用线程,因而此参数定义了其支持的最大并发连接数,默认值为50
request_timeout_ms网络发送与接收操作的超时时长,以ms为单位,默认值为30000,可以在必要时通过增大此值实现长连接的效果
  • 具体的配置示例
/etc/ceph/ceph.conf
#也可以全部写在rgw_frontends=""中空格分割开
[client.rgw.servera]
rgw_frontends="civetweb port=80"
#生产环境中指向负载均衡器的域名后缀
rgw_dns_name=servera
log_file=/var/log/ceph/servera.rgw.log
access_log_file=/var/log/ceph/civetweb.access.log
error_log_file=/var/log/ceph/civetweb.error.log
num_threads=100

访问测试

  • curl http://servera

1.5 什么是S3存储

S3由Amazon于2006年推出,全称为Simple Storage Service,S3定义了对象存储,是对象存储事实上的标准,从某种意义上说,S3就是对象存储,对象存储就是S3,它对象存储市场的霸主,后续的对象存储都是对S3的模仿

S3的特点

  • 跨区域复制
  • 事件通知
  • 版本控制
  • 安全加密
  • 访问管理切可编程

1.5.1 rgw中s3的API支持

对象存储在bucket中若要利用S3 API访问对象,需要为RADOS网关配置用户每个用户具有一个access key和一个secret key。access key标识用户,secret key验证用户身份

  • S3服务的RESTAPI使用用户账号(user)、存储桶(bucket)和对象(object)三个组件来组织存储的数据对象,对象保存于存储桶中,而存储桶则支持授权给特定账号进行读写及创建/删除等操作

  • Amazon S3 API授权和身份验证模型具有单层设计。一个用户可以有多个access key和secret key,用于在同一帐户中提供不同类型的访问

  • radosgw-admin是用于管理radowgw服务的命令行接口,它有着众多的分别用于不同管理功能的命令,例如user、subuser、key、bucket和object等

#创建示例
radosgw-admin user create--uid=john --display-name="John Doe" --email=iohn@example.com --access-key=12345 --secret=67890 --id rgw.servername
    -uid 指定用户名
    --display-name 指定备注名
    --email 指定邮箱
    --access-key 指定access key,如果不指定,会自动生成
    --secret 指定secret key如果不指定,会自动生成
    --id 如果没有权限则需要指定有权限的cephX用户去执行命令
#当radosgw-admin自动生成密钥时,有时会在access key和secretkey中包含josn转义符"\”。在使用的时候,不能包含这个字符

1.5.2 S3中的用户管理

#修改用户:
radosgw-admin user modify --uid=uid --display-name="John E.Doe" --max-buckets=2000

#禁用用户:
radosgw-admin user suspend --uid=uid

#启用用户:
radosgw-admin user enable --uid=uid

#删除用户:
radosgw-admin user rm --uid=uid[--purge-data][--purge-keys]

1.5.3 管理用户密钥

#创建一个用户的key
radosgw-admin key create --uid=uid--key-type=s3[--access-key=key][--secret=secret]

#删除一个用户的key
radosgw-admin key rm --uid=uid --access-key=key在创建密钥时,可以通过--gen-access-key和--gen-secret来生成随机的access key和secret key

1.5.4 S3设置配额数

#基于用户的配额
radosgw-admin quota set --quota-scope=user --uid=uid[--max-objects=number][--max-
size=sizeinbytes]

#基于bucket的配额
radosgw-admin quota set --quota-scope=bucket --uid=uid[--max-ob.jects=number][--max-
size=sizeinbytes]

#启用配额
radosgw-admin quota enable --quota-scope=[user|bucket] --uid=uid

#禁用配额
radosgw-admin quota disable --quota-scope=[userlbucket] --uid=uid

1.5.5 检索用户信息

#查看某个用户信息
radosgw-admin user info --uid=user

#查看所有的用户信息
radosgw-admin user list

1.5.6 统计数据

#用户在具体的时间段写入了多少的数据
radosgw-admin usage show --uid=uid --start-date=start --end-date=end
radosgw-admin usage trim --start-date=start --end-date=end
radosgw-admin usage show --show-log-entries=false

#时间的方式
data表示方式:YYYY-MM-DD hh:mm:ss

1.5.7 配置DNS实现数据传输

配置泛域名解析

  • S3的存储桶是用于存储对象的容器,每个对象都必须储存在一个特定的存储桶中,且每个对象都要直接通过RESTfulAPI基于URL进行访问,URL格式为http(s)://bucket-name.radowgw-host[:port]/key"

  • 例如,对于存储在rgw01.test.io上的S3API对象存储系统上eshop存储桶中的名为images/test.ipg的对象,可通过http://eshop.rgw01.test.io/images/test.jpg对其进行寻址

  • 因此,radosgw的S3API接口的功能强依赖于DNS的泛域名解析服务,它必须能够正常解析任何<bucket-name>.<radowgw-host>格式的名称至radosgw主机

  • 另外,还需要配置每个radowgw守护进程的rgw dns name为其DNS名称

#下面是一个在bind中用于泛域名解析的配置示例
         IN   NS   ns
ns       IN   A        172.29.1.199
rgw01    IN   A        172.29.0.11
rgw02    IN   A        172.29.0.12
*.rgW01  IN CNAME      rgw01
*.rgW02  IN CNAME      rgw02

rados网关访问S3对象

#修改网关服务的/etc/ceph/ceph.conf,添加如下内容:
rgw_dns_name = lab.example.com

1.5.8 启用S3-api客户端s3cmd

如果基于编程的方式过于复杂切大量重复操作所以S3为了简化操作退出了命令行版本的客户端

  • 使用s3cmd命令之前需要事先配置其工作环境,包括指定Access Key和Secret Key,以及S3服务的访问端点和默认的Region(Ceph的新版本中称作zonegroup)等
  • s3cmd –configure,配置的结果将保存于~/.s3cmd.cfg配置文件中,用户随后可通过编辑此文件修改配置参数,或者再次运行此配置命令为其指定新的配置信息
#安装客户端
yum install -y s3cmd
#配置客户端信息
s3cmd --configure
1.配置密钥
2.配置cloudfront_host
3.配置host_base
4.配置host_bucket
5.配置website_endpoint

命令测试

#创建bucket
s3cmd mb s3://demobucket

#上传文件至bucket
s3cmd put --acl-public /tmp/demoobject s3://demobucket/demoobject

#获取文件
s3cmd get s3://demobucket/demoobject ./demoobject
curl http://demobucket.lab.test.io/demoobject
curl http://lab.test.io/test/demoobject

1.5.9 Bucket常用操作

#列出bucket
radosgw-admin bucket list

#删除bucket
radosgw-admin bucket rm --bucket=bucket

#查看bucket信息
radosgw-admin bucket stats --bucket=bucket

#检查bucket
radosgw-admin bucket check --bucket=bucket

1.6 什么是Swift

openstack swift是openstack开源云计算项目开源的对象存储,提供了强大的扩展性、冗余和持久性

Swift特性

  • 极高的数据持久性

  • 完全对称的系统架构

  • 无限的可扩展性

  • 无单点故障

1.6.1 Swift-API操作

Swift-API的上下文中,存储桶以container表示,而非S3中的bucket,但二者在功用上类同,都是对象数据的容器,且对象存储在容器中。Openstack Swift API的用户模型与Amazon S3 API稍有不同。若要使用swift api通过rados网关的身份验证,需要为rados网关用户帐户配置子用户。swift有租户概念,rados网关用户对应swift的租户,而子帐号则对应swift的api用户

  • Swift的用户账号对应于radosgw中的subuser(子用户),它隶属于某个事先存在的user(用户账号)
#创建主账户
radosgw-admin user create--uid="swiftuser"--display-name="Swift Testing User"

#创建swift子用户
radosgw-admin subuser create --uid 主帐户名 --subuser 主帐户名:swift子账户 --access=指定权限
    --uid 指定现有的rgw网关用户
    --subuser 指定子用户
    --access 指定用户权限
        - r 读取
        - w 写入
        - rw 读写
        - full 完全
  • 例如:Python Swiftclient是一个用于与Swift API交互的Python客户端程序,它包含了Python API(swift 模块)和一个命令行工具swift
#安装pythonswift的工具方式
pip instal--upgrade python-swiftclient
swift命令可以通过Swift API完成容器和对象数据的管理操作,其基础语法格式为
ccswift [-A Auth URL][-U username][-K password]subcommand

1.6.2 Swift用户管理

#修改子用户
rados-admin subuser modify --subuser=uid:subuserid --access=full

#删除子用户
radosgw-admin subuser rm --subuser=uid:subuserid [--purge-data] [--purge-keys]

#修改子用户密钥
radosgw-admin key create --subuser=uid:subuserid --key-type=swift [--access-key=key] [--secret=secret]

#删除子用户密钥
radosgw-admin key rm --subuser=uid:subuserid

1.6.3 Swift客户端

  • swift客户端不像s3客户端一样有本地的配置信息文件,所以没有次操作都要带上账号的认证信息

  • RADOS网关支持Swift v1.0以及OpenStack keystone v2.0身份验证

#3安装swift客户端
yum install -y python-swiftclient

#创建一个容器
swift -V 1.0 -A http://servera/auth -U john:swift -K secret post container

#向容器中上传一个文件
swift -A http://servera/auth/v1.0 -U john:swift -K secret upload container filepath

#列出容器中的文件
swift -A http://servera/auth/v1.0 -U john:swift -K secret list [container]

#查看容器状态
swift -A http://servera/auth/v1.0 -U john:swift -K secret stat

1.6.4 swift读写练习

使用openstack swift提供对象存储

  • 使用openstack swift接口创建一个可访问ceph集群的用户

  • 使用openstack swift接口管理对象的存储

# servera上操作

ssh servera

systemtl status ceph-radosgw@*

su - ceph

# 创建swift子用户

radosgw-admin subuser create --uid="operator" --subuser="operator:swift" --access="full" --secret="opswift"

# 安装swift客户端

sudo yum install -y python-swiftclient


# 查看swift状态

swift -V 1.0 -A http://servera/auth/v1 -U operator:swift -K opswift stat

# 列出containers
swift -V 1.0 -A http://servera/auth/v1 -U operator:swift -K opswift list

# 创建container
swift -V 1.0 -A http://servera/auth/v1 -U operator:swift -K opswift post my-container

swift -V 1.0 -A http://servera/auth/v1 -U operator:swift -K opswift list

# 创建一个10M的文件并上传

dd if=/dev/zero of=/tmp/swift.dat bs=1024k count=10

swift -V 1.0 -A http://servera/auth/v1 -U operator:swift -K opswift upload my-container /tmp/swift.dat

# 查看my-container状态

swift -V 1.0 -A http://servera/auth/v1 -U operator:swift -K opswift stat my-container

# 查看operator:swift用户状态

1.7 Ceph多区域网关

多区域的概念

Multi-Site功能是从J版本开始的。一个single zone配置通常由一个zone group组成,该zone group包含一个zone和多个用于负载均衡的RGW实例。从K版本开始,ceph为RGW提供了Multi-Site的配置选项。为Ceph存储集群启用radosgw服务之后,它会默认生成一个名为default的zonegroup,其内含一个名为default的zone,管理员可按需扩展使用更多的zone或zonegroup

  • 区域(zone): 一个ceph集群可以包含多个区域,一个区域只属于一个集群,一个区域可以有多个RGW

  • 区域组(zonegroup):由一个或多个区域组成,包含一个主区域(master zone),其他区域称为Secondary Zone,区域组内的所有区域之间同步数据

  • 域(realm): 同一个或多个区域组组成,包含一个主区域组,其他都次区域组。域中的所有rados网关都从位于主区域组和主区域中的rados网关拉取配置

  • 注意:?master zone group中的master zone处理所有元数据更新,因此创建用户、bucket等操作都必须经由master zone

架构图

  • single-zone:一个realm中只有一个zonegroup和一个zone,可以有多个RGW

  • multi-zone:一个relam中只有一个zonegroup,但是有多个zone。一个realm中存储的数据复制到该zonegroup中的所有zone中

  • multi-zonegroup:一个realm中有多个zonegroup,每个zonegroup中又有一个或多个zone

  • multi-realms:多个realm

1.7.1 Periods和Epochs

  • 每个zone有关联的period,每个period有关联的epoch。

  • period用于跟踪zone、zone group和realm的配置状态

  • epoch用于跟踪zone period的配置变更的版本号

  • 每个period具有唯一ID,含有zone配置,并且知道其先前period的id

  • 在更改zone的配置时,需要更新zone的当前period

1.7.2 多区域同步流程

  • RGW在所有zone group集合之间同步元数据和数据操作。元数据操作与bucket相关:创建、删除、启用和禁用版本控制、管理用户。meta master位于master zone group中的master zone,负责管理元数据更新

  • 多区域配置后处于活跃状态时,RGW会在master和secondary区域之间执行一次初始的完整同步。随后的更新是增量更新

  • 当RGW将数据写入zone group的任意zone时,它会在该zone group的所有其他zone之间同步这一数据

  • 当RGW同步数据时,所有活跃的网关会更新数据日志并通知其他网关

  • 当RGW网关因用户操作而同步元数据时,主网关会更新元数据日志并通知其他RGW网关

1.7.3 多区域网关配置

  • Secondary区域配置例子
#拉取realm
radosgw-admin realm pull --url http://servera.lab.example.com --access-key access-key --secret secret-key   # 主区域中syncuser的key

#拉取period
radosgw-admin period pull --url http://servera.lab.example.com --access-key access-key --secret secret-key

#创建 Secondary Zone
radosgw-admin zone create --rgw-zonegroup wuhan --rgw-zone hankou --access-key access-key --secret secret-key --endpoints http://serverf.lab.example.com [--read-only]

#更新rgw配置文件
[client.rgw.serverf]
rgw_zone = hankou

#更新period
radosgw-admin period update --commit 

#启动RGW
systemctl restart ceph-radosgw@rgw.serverf

#检查同步状态
radosgw-admin sync status

1.7.4 故障恢复与切换

故障恢复步骤

1.原master zone恢复以后,将该zone再恢复到master
2.拉取period
3.设置恢复后的zone为master zone
4.重启恢复后的zone的rgw
5.更新period以使修改生效
6.重启secondary zone的rgw

维护

  • 查看同步状态
radosgw-admin sync status
  • 变更metadata master zone(需要在元数据完全同步完成之后才能进行变更操作,否则可能会丢失数据):
radosgw-admin zone modify --rgw-zonegroup wuhan --rgw-zone hankou --master
radosgw-admin period update --commit

故障切换

  • 假如当前master zone故障,需切换到secondary zone以进行容灾恢复:
#提升secondary zone为master zone
radosgw-admin zone modify --rgw-zone hankou --master --default [--read-only=False]
  • 更新period以使修改生效,重启RGW
radosgw-admin period update --commit
systemctl restart ceph-radosgw@rgw.serverf  

1.7.5 迁移Single-Zone至Multi-Zone

1. 创建realm
2. 重命名default zone和zonegroup(可不修改)
radosgw-admin zonegroup rename --rgw-zonegroup default --zonegroup-new-name newgroup
radosgw-admin zone rename --rgw-zonegroup newgroup --rgw-zone default --zone-new-name newzone
3. 修改default zonegroup将其加入到realm,并将其设置为master zonegroup
4. 将default zone配置为master zone
5. 创建系统用户
6. 将master zone与系统用户关联
7. 提交更新的配置
8. 重启RGW

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-07-04 23:03:58  更:2022-07-04 23:06:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 2:59:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码