zoukankan      html  css  js  c++  java
  • linux8 redis集群槽+docker

    docker pull hello-world #不能推送,要把名字改一下

    错误1 :

    私有仓库搭建:

    刚开始 : 报错: server gave http response to https client #只支持https的格式,不支持http的,要改一下http的 ![http的不支持默认支持https的](E:Downloadqq_download eacher_huatu_downloads20pyLinuxday86 linux8http的不支持默认支持https的.png)

    改一下 :

    	vim /etc/docker/daemon.json  
    	2.写入如下信息,地址改成你自己的ip
    	{"registry-mirrors": ["http://f1361db2.m.daocloud.io"],
    		"insecure-registries":["192.168.16.142:5000"]
    	}
    

    正确:

    [root@liu ~]# docker push 192.168.230.132:5000/s20-hello-world
    The push refers to a repository [192.168.230.132:5000/s20-hello-world]
    af0b15c8625b: Pushed
    latest: digest: sha256:92c7f9c92844bbbb5d0a101b22f7c2a7949e40f8ea90c8b3bc396879d95e899a size: 524

    linux第八天笔记
    学习python的第86天

    1.redis-cluster集群

    背景

    1 并发问题
    
    2 数据另太大  
    新浪微博  这么大的数据 ,去哪买内存条,
    思想: 数据分片存储在多个redis中
    集群: twitter 开源 
    ​		codis 豌豆荚 开发c 和 go开发 
    不好的: 一台机器,超载了
    
    正确的是  分布式,加机器,分摊集中式压力,一堆机器做一件事(计算机是跟生活中的东西非常相似的),分了马鞍,马背上
    
    按key分片,实例化多个马
    节点取余分类 
    虚拟槽分区(官方)
    

    ![槽分类](E:Downloadqq_download eacher_huatu_downloads20pyLinuxday86 linux8槽分类.png)

    redis-cluster集群搭建
    1.环境准备,6个redis数据库节点

    ​ 也就是准备6个配置文件,6匹马
    ​ redis-7000.conf
    ​ redis-7001.conf
    ​ redis-7002.conf
    ​ redis-7003.conf
    ​ redis-7004.conf
    ​ redis-7005.conf
    ​ #每个配置文件的内容,仅仅是端口的不同7000~7005
    ​ #内容如下

    ​ port 7000
    ​ daemonize yes
    ​ dir "/opt/redis/data/7000"
    ​ logfile "7000.log"
    ​ dbfilename "dump-7000.rdb"
    ​ cluster-enabled yes #开启集群模式
    ​ cluster-config-file nodes-7000.conf  #集群内部的配置文件
    ​ cluster-require-full-coverage no 
    ​ #redis cluster需要16384个slot都正常的时候才能对外提供服务,换句话说,只要任何一个slot异常那么整个cluster不对外提供服务。 因此生产环境一般为no

    2.快速生成6个节点的配置文件
    mkdir -p /opt/redis/data/{7000,7001,7002,7003,7004,7005}
    sed "s/7000/7001/g" redis-7000.conf > redis-7001.conf
    .....

    3.启动6个redis节点(准备好了6匹马)
    redis-server redis-7000.conf
    .....

    4.马儿准备好了,分配槽位,开始放入数据,查看数据流向
    开启redis-cluster的集群功能,以及分配redis的slot槽位,基于ruby语言的脚本工具自动分配

    1.下载ruby的解释器

    ​ wget https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz

    2.解压缩ruby的源码包
    tar -zxvf ruby-2.3.1.tar.gz
    3.进入ruby的源码包目录,编译三部曲
    cd ruby-2.3.1
    ./configure --prefix=/opt/ruby231
    make && make install

    3.配置ruby的环境变量
    vim /etc/profile
    写入PATH=""

    4.读取这个/etc/profile
    source /etc/profile

    5.下载ruby操作redis的模块
    wget http://rubygems.org/downloads/redis-3.3.0.gem
    #安装ruby操作redis的模块
    gem install -l redis-3.3.0.gem (ruby 解释器 gem 类似于pip 包管理工具)

    6.一键分配redis集群的槽位
    #查找一下这个命令的绝对路径
    find / -name redis-trib.rb
    #这个数字 1 代表,每个redis主库,只有一个redis从库
    /opt/redis-4.0.10/src/redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 #(如果害怕主从都挂了的话就把那个1 设置为多个从)![杀死主进程奴进程上位](E:Downloadqq_download eacher_huatu_downloads20pyLinuxday86 linux8 edis-cluster杀死主进程奴进程上位.png)

    7.开启了集群状态功能后,登录数据库,查看数据写入流向

    ​ /opt/redis-4.0.10/src/redis-trib.rb add-node --slave 127.0.0.1:7003 127.0.0.1:7000

    8.防止redis-cluster主节点故障,可以搭配 redis-cluster + redis-sentinel ,用哨兵检测主节点状态,当主节点宕机,自动切换从节点为新的主库

    1.redis-sentinel配置方式如下,检测三个主节点7000  7001  7002
    port 27379
    dir "/var/redis/data"
    logfile "26379.log"
    sentinel monitor master1 127.0.0.1 7000 2  
    sentinel monitor master2 127.0.0.1 7001 2  
    sentinel monitor master3 127.0.0.1 7002 2  
    
    sentinel down-after-milliseconds master1 30000  
    sentinel down-after-milliseconds master2 30000  
    sentinel down-after-milliseconds master3 30000  
    
    sentinel parallel-syncs master1 1  
    sentinel parallel-syncs master2 1  
    sentinel parallel-syncs master3 1  
    
    sentinel failover-timeout master1 180000  
    sentinel failover-timeout master2 180000  
    sentinel failover-timeout master3 180000  
    
    2.启动哨兵,检测cluster的主节点
    redis-sentinel redis-26379.conf
    
    3.杀死redis-cluster的主节点,查看从节点状态(是否自动重启),可以运行多个从节点,保证数据安全
    
    查看集群状态
    redis-cli -p 7000 cluster info  
    
    redis-cli -p 7000 cluster nodes  #等同于查看nodes-7000.conf文件节点信息		(主仆关系
    查看一组的所有的状态)
    

    ![查看主仆命令,长的码对应三对主仆](E:Downloadqq_download eacher_huatu_downloads20pyLinuxday86 linux8 edis-cluster查看主仆命令,长的码对应三对主仆.png)

    在进入redis-cli
    输入:ping
    回复:pong --->连接成功(不是在外面(是ping baidu.com))

    问题1:

    CLUSTERDOWN Hash slot not served

    未提供clusterdown哈希槽
    

    当给redis-cli -c -p 7005 get name时,出现的错误,发现当redis-cli -p 7005 cluster nodes 时,只有一个 7005master的信息(0 connected),没有别的,而且,查看别的服务器信息时,发现有一个salve fail(未连接)

    当没给他写值却读取值是就显示这个错误

    ​ /opt/redis-4.0.10/src/redis-trib.rb fix 127.0.0.1:7005 执行这条命令之后便可以get 数据,说明给了哈希槽了,但是还是没有连接 到大部队

    问题2 :

    error

    操作不知哪儿出错了 master.fail (not connected) 把dphp.rdb 存放数据的删除了,但是还是不行
    老师让: 重新定义了端口,把六个端口都改了才可以的

    ![错误虚拟不分配了不连接](E:Downloadqq_download eacher_huatu_downloads20pyLinuxday86 linux8 edis-cluster错误虚拟不分配了不连接.png)

    琐碎的知识点

    cat /etc/os-release #查看当前版本

    docker rmi fce

    Error response from daemon: conflict: unable to delete fce289e99eb9 (must be forced) - image is being used by stopped container 812abef0cef8
    有依赖关系   : docker rm 812
    

    (一层层删除)

    问题3 :
    创建容器的时候报错WARNING: IPv4 forwarding is disabled. Networking will not work.
    
    # docker run -it -p 30001:22 --name=centos-ssh  centos /bin/bash
    
    WARNING: IPv4 forwarding is disabled. Networking will not work.  
     
    解决办法:
    
    # vim  /usr/lib/sysctl.d/00-system.conf
    添加如下代码:
    net.ipv4.ip_forward=1
     
    重启network服务
    # systemctl restart network
     查看是否开启了
    [root@liu ~]# sysctl net.ipv4.ip_forward
    net.ipv4.ip_forward = 1
    
    ## 完成以后,删除错误的容器,再次创建新容器,就不再报错了。
    # 作者:Locutus 
    来源:CSDN 
    原文:https://blog.csdn.net/yjk13703623757/article/details/68939183 
    版权声明:本文为博主原创文章,转载请附上博文链接!
    
    错误 3:

    /usr/bin/docker-current: Error response from daemon: oci runtime error: container_linux.go:235: starting container process caused "exec: "python.app.py": executable file not found in $PATH".

    docker run -d -P training/webapp python.app.py

    docker run -d -P training/webapp python app.py

    多写了个一个点

    现象1
    会变得啊
    [root@liu ~]# docker port 85f
    5000/tcp -> 0.0.0.0:32769
    [root@liu ~]# docker stop 85f
    85f
    [root@liu ~]# docker start 85f
    85f
    [root@liu ~]# docker port 85f
    5000/tcp -> 0.0.0.0:32770
    
    

    执行 flask的程序 时,有文件的

    root@85f2e9063034:/opt/webapp# ls
    Procfile  app.py  requirements.txt  tests.py
    

    2 docker

    vmare虚拟化内存俩个g, 数值是技术手段实现的假的

    docker :也是通过虚拟化搭建的假的,轻量级的虚拟化

    docker 和虚拟机对比

    ![docker对比](E:Downloadqq_download eacher_huatu_downloads20pyLinuxday86 linux8docker对比.png)

    用途:
    ali   多少万 很多
    jidong   15万个docker业务全部实例化  
    
    由go所写,所以并发厉害

    :开源 由go写的 ,所以 go为什么火 还有区块链

     python  之前16 shi openstack  现在ai tensflow
    

    : 对linux的封装 ,

    : 简单开发

    之前部署 :

    app <--->  os  <---> 物理
    
    虚拟化 hypervisor    appliaca(centos) 
    
    : 虚拟机是完整的操作系统 ,要分配系统资源,卡
    
    一栋楼一户人家  一个楼房一户人家    胶囊房
    
    物理机				虚拟机		容器
    

    ![能用图不写字](E:Downloadqq_download eacher_huatu_downloads20pyLinuxday86 linux8能用图不写字.png)

    容器是吧这个进程命令,文件放到一个docker镜像中取运行相当于在python3 manage.py runserver 这个镜像上,批了一个马甲

    ![docker容器](E:Downloadqq_download eacher_huatu_downloads20pyLinuxday86 linux8docker容器.png)

    环境配置

    每台计算机的环境不同,如何换一台机器能运行起来呢?

    把配置完整的复制过去 到另一个

    管理 - 克隆

    笑话 : 开发和测试 开发和运维(环境问题)

    解决方案二 linux容器

    自从用上docker容器后,可以实现开发、测试和生产环境的统一化和标准化

    iso 刻录 ,用此安装好,所有的是一样的

    三个生命周期

    镜像image # 相当于类,老板的光盘

    容器container

    仓库repository #存放镜像文件的,公共的仓库 dockerhub.com github.com

    docker整个生命周期就是这三个概念

    基于老板卖的dvd光盘,安装操作系统

    基于镜像,运行容器实例

    镜像 理解为python的class

    容器 理解为python的类的实例化

    容器也是可以自定义更改,在生成新的 镜像文件的

    class foo():

    def __init__(self):
    	self.name ='他大舅。。。'
    

    f1 = foo()

    面试(太白,大金链子)

    敲门的礼仪,技术水平,都要,合作伙伴,

    技术好,人又谦虚,不太狂(也不要,相处共事因为)

    阿里源 可能版本低

    性格:

    不走进去,出不来,出错随时(以前的缺点弱点),但是不要沉溺堕落。知来者只可追、

    2. 1.docker的安装方式

    ce 社区版
    ee 企业版

    安装方式
    1.选择官方的docker yum源,网速太慢

    2.由于网速问题,选择阿里云的docker软件

    yum install docker -y

    3.启动docker
    systemctl start docker

    4.检查docker运行状态,以及版本信息

    docker version

    5.配置docker加速器
    curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io
    这个命令是修改/etc/docker/daemon.json文件,写入一个json数据如下
    [root@s20 ~]# cat /etc/docker/daemon.json
    {"registry-mirrors": ["http://f1361db2.m.daocloud.io"]}
    配置好了docker加速器,下载镜像就快很多了


    6.下载centos的docker镜像

    docker pull centos #是取dockerhub 下载cnetos镜像的

    7.学习管理容器,镜像,仓库的增删改查
    容器
    docker run 镜像名/镜像id #运行处容器进程实例
    docker ps #查看正在运行的容器进程
    docker ps -a #显示所有运行过的容器进程(正在运行的,以及挂掉的容器进程)
    docker container ls -a #同上,旧的命令

    容器管理的重要点!!!

    容器管理的重要点!!!

    容器管理的重要点!!!

    容器管理的重要点!!!

    docker容器中必须有进程在后台运行,否则容器挂掉!!!
    docker镜像每次运行 都会生成新的容器id记录
    docker run hello-world 运行三次,出现三次容器新的记录
    docker run hello-world
    docker run hello-world

    运行一个交互式的ubuntu容器实例

    docker run -it ubuntu /bin/bash #参数解释 -i 交互式的命令操作 -t 开启一个终端界面 /bin/bash 指定linux的解释器 (这页面)

    ![docker运行变化unbtun页面](E:Downloadqq_download eacher_huatu_downloads20pyLinuxday86 linux8docker运行变化unbtun页面.png)

    交互式的运行一个centos容器

    docker run -it centos /bin/bash

    docker rm 容器id #删除容器id记录,只能删除挂掉的容器

    docker rm docker ps -aq #批量删除挂掉的容器记录

    在容器的后台运行一个进程,运行出活着的容器

    docker run -d centos /bin/sh -c "while true;do echo '佳增你真棒'; sleep 1;done"
    -d 就是daemonize 后台运行的意思
    centos 指定哪个镜像
    /bin/sh 指定linux的解释器
    -c 指定一段shell代码
    "while true;do echo '佳增你真棒'; sleep 1;done" 每秒打印一个

    进入容器空间内

    docker exec -it 运行着的容器id /bin/bash

    查看容器日志

    docker logs 容器id
    docker logs -f 容器id #检测容器内的日志

    dockerfile 的学习

    docker ps 查看容器id

    2.2 自定义docker镜像

    shell默认的解释器
    /bin/bash
    /bin/sh

    1.获取一个centos基础镜像,运行处容器后
    docker run -it centos /bin/bash

    2.进入容器空间内,默认没有python3 和其他软件
    进入之后,安装一个vim
    yum install vim -y

    3.自定义软件后,退出容器,提交这个容器,成为一个新的镜像 exit退出容器
    docker

    4.此时这个镜像文件,可以发送给其他同事了
    docker commit 容器id 新的镜像的名字
    docker commit 5c2 s20/centos-vim

    5.查看提交的镜像文件
    docker images

    6.导出这个镜像文件,指定导出的文件名和后缀
    docker save 镜像名/id > /opt/s20-centos-vim.tar.gz

    7.在本地测试导入这个镜像
    可以测试在本地,先删除原本的镜像
    导入命令
    docker load < /opt/s20-centos-vim.tar.gz

    8.给导入的镜像,修改tag别名
    docker tag 旧的镜像名 以dockerhub仓库id开头的/新的镜像名
    docker tag 621 liuyang/s20-centos-vim

    9.执行这个docker镜像,运行处容器后,查看是否携带了vim
    关键字 关键字 参数 镜像名 你要执行的命令
    docker run -it liuyang/s20-centos-vim /bin/bash

    镜像

    docker search centos #去docker hub 搜索有关centos的镜像文件

    docker pull centos #下载docker镜像 centos
    docker pull hello-world #获取一个hello-world镜像
    docker images #查看本地有哪些docker镜像
    docker image ls #命令同上

    docker rmi 镜像id或者镜像名 #删除本地docker镜像
    docker rmi -f 镜像id #强制删除镜像文件
    docker pull ubuntu #获取一个ubuntu镜像

    仓库

    2.3 运行一个web容器的操作

    1.获取一个python的flask的镜像
    #docker run的特点是,如果镜像不存在,会自动的先去docker pull
    docker run -d -P training/webapp python app.py
    -d 后台运行
    -P 端口映射,随机映射
    training/webapp 镜像名
    python app.py 你要执行的命令

    ​ (没有自动会去pull)

    docker容器的端口映射

    docker port 容器id

    ![docker _ flask映射](E:Downloadqq_download eacher_huatu_downloads20pyLinuxday86 linux8docker _ flask映射.png)

    容器的启停管理

    docker start 容器id
    docker stop 容器id

    2.4 dockerfile的学习

    这个文件就是定制docker镜像的一个脚本而已,学习里面的功能性的参数

    获取docker镜像的方式

    1.去docker仓库获取的方式,一个是公网仓库,一个是私有仓库
    docker pull

    2.获取别人发来的镜像,也就是自定义的镜像

    3.通过dockerfile构建docker镜像

    2.41 Dockerfile 参数

    指定以哪个系统为基础

    FROM scratch #制作base image 基础镜像,尽量使用官方的image作为base image
    FROM centos #使用base image
    FROM ubuntu:14.04 #带有tag的base image

    定义dockerfile一些参数信息的指令

    LABEL version=“1.0” #容器元信息,帮助信息,Metadata,类似于代码注释
    LABEL maintainer=“yc_uuu@163.com"

    对于复杂的RUN命令,避免无用的分层,多条命令用反斜线换行,合成一条命令!

    万能指令RUN

    RUN yum update && yum install -y vim
    Python-dev #反斜线换行
    RUN /bin/bash -c "source $HOME/.bashrc;echo $HOME”

    WORKDIR /root #相当于linux的cd命令,改变目录,尽量使用绝对路径!!!不要用RUN cd
    WORKDIR /test #如果没有就自动创建
    WORKDIR demo #再进入demo文件夹
    RUN pwd #打印结果应该是/test/demo

    ADD添加的意思

    ADD and COPY

    语法

    ADD 本地的资料 容器内的存放路径

    ADD除了有添加的作用,还有解压缩的作用

    ADD hello.txt / #把本地文件添加到镜像中,吧本地的hello可执行文件拷贝到镜像的/目录
    ADD test.tar.gz / #添加到根目录并解压,自动的解压test.tar.gz 解压为test

    ​ # 再写RUN tar -zvcf ... 会报错(不知道 )

    WORKDIR /root
    ADD hello test/ #进入/root/ 添加hello可执行命令到test目录下,也就是/root/test/hello 一个绝对路径
    COPY hello test/ #等同于上述ADD效果

    copy就是把本地的文件,拷贝到容器空间内,没有解压作用

    ADD与COPY

    • 优先使用COPY命令
    -ADD除了COPY功能还有解压功能
    

    添加远程文件/目录使用curl或wget

    ENV #环境变量,尽可能使用ENV增加可维护性

    ENV MYSQL_VERSION 5.8 #设置一个mysql常量

    RUN yum install -y mysql-server=“${MYSQL_VERSION}”
    RUN yum install -y mysql-server=“${MYSQL_VERSION}”
    RUN yum install -y mysql-server=“${MYSQL_VERSION}”
    RUN yum install -y mysql-server=“${MYSQL_VERSION}”
    RUN yum install -y mysql-server=“${MYSQL_VERSION}”

    2.5 通过dockerfile定制一个python flask web程序,运行处容器

    配置方法:

    1.准备一个flask代码文件
    touch s20flask.py
    vim s20flask.py

    coding:utf8

    from flask import Flask
    app=Flask(name)
    @app.route('/')
    def hello():
    return "20期学的都很棒,很厉害"
    if name=="main":
    app.run(host='0.0.0.0',port=8080)

    2.准备Dockerfile,写入如下内容
    FROM centos
    COPY CentOS-Base.repo /etc/yum.repos.d/
    COPY epel.repo /etc/yum.repos.d/
    RUN yum clean all
    RUN yum install python-setuptools -y
    RUN easy_install -i https://pypi.tuna.tsinghua.edu.cn/simple flask
    COPY s20flask.py /opt/
    WORKDIR /opt
    EXPOSE 8080 #暴露容器内的8080端口
    CMD ["python","s20flask.py"] #让容器执行如下命令

    copy 把本地的文件copy到容器空间内

    拷贝一份文件到本文件夹
    [root@liu s20docker]# cp /etc/yum.repos.d/CentOS-Base.repo .
    [root@liu s20docker]# cp /etc/yum.repos.d/epel.repo .
    

    有的 公司有python3 有的可能python2

    3.准备好齐全的文件,开始构建docker镜像
    [root@s20 s20docker]# ls
    CentOS-Base.repo Dockerfile epel.repo s20flask.py

    4.构建docker镜像的命令,这个命令得在Dockerfile的目录下执行
    docker build .

    5.构建镜像完成之后,查看镜像文件
    docker images
    docker tag 6f0 s20-flask-docker

    6.运行这个镜像,
    docker run -d -p 7777:8080 6f0

    没有easy_install

    [root@liu s20docker]# docker run -it centos
    [root@668cbafcdde2 /]# easy_install
    bash: easy_install: command not found
    
    

    配置python的包管理,安装flask
    easy_install -i https://pypi.tuna.tsinghua.edu.cn/simple flask

    2.6 docker仓库的学习(共有仓库(不安全))

    1.docker提供了一个类似于github的仓库dockerhub,
    网址https://hub.docker.com/需要注册使用
    2.注册docker id后,在linux中登录dockerhub
    docker login #输入你的账号密码 就可以成功登录

    注意要保证image的tag是账户名,如果镜像名字不对,需要改一下tag
    docker tag 你的dockerhub账号名/你的docker镜像名 本地的镜像id或名

    语法是: docker tag 仓库名 yuchao163/仓库名

    3.推送docker image到dockerhub
    docker push yuchao163/centps-cmd-exec:latest
    4.在dockerhub中检查镜像
    https://hub.docker.com/
    5.删除本地镜像,测试下载pull 镜像文件
    docker pull yuchao163/centos-entrypoint-exec

    定制docker镜像的一个脚本而已

    比如说:docker 一个centos 没有python 自定义就可以写进去了

    2.7 docker的私有仓库搭建

    配置方式
    1.下载一个registry 私有仓库镜像

    docker run -d
    -p 5000:5000
    -v /opt/data/registry:/var/lib/registry
    registry

    这个  是换行符的意思 
    -v 是数据文件夹挂载  ,宿主机的数据文件夹:容器内的文件夹
    
    5000 访问什么都没有,但是没有拒绝   # 不支持http方式的传送
    

    2.可以查看私有仓库的api数据地址,如下
    http://192.168.230.132:5000/v2/_catalog(我的ip)

    3.但是此时的私有仓库还没法使用,它不支持http方式的推送,修改默认的配置文件即可(好像是这个错误:ERRO[0000] error getting events from daemon: net/http: request canceled )
    1.编辑docker的配置文件
    vim /etc/docker/daemon.json
    2.写入如下信息,地址改成你自己的ip
    {"registry-mirrors": ["http://f1361db2.m.daocloud.io"],
    "insecure-registries":["192.168.16.142:5000"]
    }
    3.修改docker的配置文件
    vim /lib/systemd/system/docker.service
    第二步:添加如下配置,在[Service]的代码区域块中,添加如下参数
    [Service]
    EnvironmentFile=-/etc/docker/daemon.json

    4.重新加载这个文件
    systemctl daemon-reload 
    
    5.重启整个docker服务
    systemctl restart docker
    
    6.重新启动一个私有仓库
    docker run --privileged=true -d -p 5000:5000 -v /opt/data/registry:/var/lib/registry registry
    
    参数解释:
    	--privileged=true  docker容器的安全机制:设置特权级运行的容器
    
    7.推送本地的镜像,到私有仓库中去
        docker push 192.168.230.132:5000/s20-hello-world
    


    8.其他同事就可以通过这个私有仓库的镜像地址,获取拉

    docker pull 192.168.230.132:5000/s20-hello-world
    



    4.还得修改本地镜像的名字,以仓库地址为开头

    docker tag 你要修改的镜像 修改之后的镜像名

    docker tag fce 192.168.230.132:5000/s20-hello-world

  • 相关阅读:
    Sass开发环境搭建
    三款Javascript SPAs框架资料整理和总结
    Web纯前端“旭日图”实现元素周期表
    能在多种前端框架下使用的表格控件
    控件使用经验-MVP模式+控件封装
    最好的Angular2表格控件
    跨平台开发的两种方法及其对比
    是时候 UWP 了 !
    你的系统也可以拥有“数据透视表”功能!
    Xamarin 免费了,你能做什么?
  • 原文地址:https://www.cnblogs.com/Doner/p/11143660.html
Copyright © 2011-2022 走看看