• 微服务架构中间件安装部署


    微服务架构中间件安装部署

    jdk安装

    安装包jdk-8u144-linux-x64.tar.gz

    先检查系统原版本的jdk并卸载
    rpm -qa | grep java
    显示信息如下:
    tzdata-java-2014g-1.el6.noarch
    java-1.6.0-openjdk-1.6.0.0-11.1.13.4.el6.x86_64
    java-1.7.0-openjdk-1.7.0.65-2.5.1.2.el6_5.x86_64
    卸载OpenJDK,执行以下操作:
    rpm -e --nodeps tzdata-java-2014g-1.el6.noarch
    rpm -e --nodeps java-1.6.0-openjdk-1.6.0.0-11.1.13.4.el6.x86_64
    rpm -e --nodeps java-1.7.0-openjdk-1.7.0.65-2.5.1.2.el6_5.x86_64
    再次查看JDK信息,确认已经卸载成功
    rpm –qa | grep java
    上传jdk-8u144-linux-x64.tar.gz到/home目录下
    tar xvf jdk-8u144-linux-x64.tar.gz # 压缩包解压
    mv jdk-8u144 jdk1.8 # 将jdk目录更名,以便配置环境变量
    打开环境变量配置文件,向文件最后追加以下内容
    vim /etc/profile
    export JAVA_HOME=/home/jdk1.8
    export JRE_HOME= J A V A H O M E / j r e e x p o r t P A T H = JAVA_HOME/jre export PATH= JAVAHOME/jreexportPATH=PATH: J A V A H O M E / b i n e x p o r t C L A S S P A T H = . / : JAVA_HOME/bin export CLASSPATH=./: JAVAHOME/binexportCLASSPATH=./:JAVA_HOME/lib:$JAVA_HOME/jre/lib
    保存退出
    使修改立即生效,执行如下命令
    source /etc/profile
    java -version # 查看jdk版本是否为1.8

    nginx安装

    请使用root用户登录执行以下命令,安装nginx依赖包,两台服务器都执行如下命令

    tar zxvf nginx-1.14.2.tar.gz
    cd nginx-1.14.2
    ./configure --prefix=/opt/nginx
    make
    make install
    cd /opt/nginx
    修改主配置/opt/nginx/conf/nginx.conf
    在http{
    }里添加
    include /opt/nginx/conf.d/*.conf;
    创建目录和虚拟配置文件
    mkdir /opt/nginx/conf.d
    vim /opt/nginx/conf.d/gateway.conf
    内容如下
    server {
    listen 80;
    server_name localhost;
    location / {
    gzip on;
    gzip_buffers 32 4K;
    gzip_comp_level 6;
    gzip_min_length 100;
    gzip_types application/javascript text/css text/xml;
    root /opt/dist/;
    try_files $uri KaTeX parse error: Expected 'EOF', got '}' at position 36: …x index.html; }̲ location @rou… /index.html last;
    }
    location /adt/ {
    proxy_pass http://127.0.0.1:81/;
    client_max_body_size 100m;
    }
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
    root html;
    }
    }
    解释:
    /opt/dist/是前端页面文件
    location /adt/ {
    proxy_pass http://127.0.0.1:81/;
    client_max_body_size 100m;
    }
    跳转网关jar包sc-gateway-1.0.0.jar的启动ip和端口,具体ip需要修改
    nginx检查和启动
    /sbin/nginx -t #配置文件检查
    ./sbin/nginx #启动nginx
    ./sbin/nginx -s reload #nginx平滑重启

    rocketmq集群安装

    集群方式:双主双从
    机器数量:两台。
    IP分别是1.1.1.1和1.1.1.2 (ip只做示范用,根据实际情况来)
    两台需要先安装jdk1.8,参照jdk安装步骤。

    把安装包上传到两台服务器/opt/下
    unzip rocketmq-all-4.7.0-bin-release.zip
    mv rocketmq-all-4.7.0-bin-release rocketmq
    我们需要修改两台机器/opt/rocketmq/conf/2m-2s-asyn/下的
    broker-a.properties (1.1.1.1机器修改)
    broker-a-s.properties (1.1.1.1机器修改)
    broker-b.properties (1.1.1.2机器修改)
    broker-b-s.properties (1.1.1.2机器修改)
    四个文件。

    1.1.1.1修改/opt/rocketmq/conf/2m-2s-async/broker-a.properties

    namesrvAddr=1.1.1.1:9876;1.1.1.2:9876
    brokerClusterName=DefaultCluster
    brokerName=broker-a
    brokerIP1=1.1.1.1
    brokerId=0
    autoCreateTopicEnable=false
    sendMessageThreadPoolNums=128
    deleteWhen=04
    fileReservedTime=48
    brokerRole=SYNC_MASTER
    flushDiskType=ASYNC_FLUSH
    #存储路径
    storePathRootDir=/opt/rocketmq/store
    #commitLog存储路径
    storePathCommitLog=/opt/rocketmq/store/commitlog
    #消费队列存储路径
    storePathConsumeQueue=/opt/rocketmq/store/consumequeue
    #消息索引存储路径
    storePathIndex=/opt/rocketmq/store/index
    #checkpoint 文件存储路径
    storeCheckpoint=/opt/rocketmq/store/checkpoint
    #abort 文件存储路径
    abortFile=/opt/rocketmq/store/abort
    #发送消息是否使用可重入锁
    useReentrantLockWhenPutMessage=true
    #消息在发送队列超时时间
    waitTimeMillsInSendQueue=300

    1.1.1.2修改/opt/rocketmq/conf/2m-2s-async/broker-a-s.properties

    namesrvAddr=1.1.1.1:9876;1.1.1.2:9876
    brokerClusterName=DefaultCluster
    brokerName=broker-a
    brokerIP1=1.1.1.1
    listenPort=10950
    brokerId=1
    autoCreateTopicEnable=false
    sendMessageThreadPoolNums=128
    deleteWhen=04
    fileReservedTime=48
    brokerRole=SLAVE
    flushDiskType=ASYNC_FLUSH
    #存储路径
    storePathRootDir=/opt/rocketmq/store/slave
    #commitLog存储路径
    storePathCommitLog=/opt/rocketmq/store/slave/commitlog
    #消费队列存储路径
    storePathConsumeQueue=/opt/rocketmq/store/slave/consumequeue
    #消息索引存储路径
    storePathIndex=/opt/rocketmq/store/slave/index
    #checkpoint 文件存储路径
    storeCheckpoint=/opt/rocketmq/store/slave/checkpoint
    #abort 文件存储路径
    abortFile=/opt/rocketmq/store/slave/abort
    #发送消息是否使用可重入锁
    useReentrantLockWhenPutMessage=true
    #消息在发送队列超时时间
    waitTimeMillsInSendQueue=300

    1.1.1.3修改/opt/rocketmq/conf/2m-2s-async/broker-b.properties

    namesrvAddr=1.1.1.1:9876;1.1.1.2:9876
    brokerClusterName=DefaultCluster
    brokerName=broker-b
    brokerIP1=1.1.1.2
    brokerId=0
    autoCreateTopicEnable=false
    sendMessageThreadPoolNums=128
    deleteWhen=04
    fileReservedTime=48
    brokerRole=SYNC_MASTER
    flushDiskType=ASYNC_FLUSH
    #存储路径
    storePathRootDir=/opt/rocketmq/store
    #commitLog存储路径
    storePathCommitLog=/opt/rocketmq/store/commitlog
    #消费队列存储路径
    storePathConsumeQueue=/opt/rocketmq/store/consumequeue
    #消息索引存储路径
    storePathIndex=/opt/rocketmq/store/index
    #checkpoint 文件存储路径
    storeCheckpoint=/opt/rocketmq/store/checkpoint
    #abort 文件存储路径
    abortFile=/opt/rocketmq/store/abort
    #发送消息是否使用可重入锁
    useReentrantLockWhenPutMessage=true
    #消息在发送队列超时时间
    waitTimeMillsInSendQueue=300

    1.1.1.4修改/opt/rocketmq/conf/2m-2s-async/broker-b-s.properties

    namesrvAddr=1.1.1.1:9876;1.1.1.2:9876
    brokerClusterName=DefaultCluster
    brokerName=broker-b
    brokerIP1=1.1.1.2
    listenPort=10950
    brokerId=1
    autoCreateTopicEnable=false
    sendMessageThreadPoolNums=128
    deleteWhen=04
    fileReservedTime=48
    brokerRole=SLAVE
    flushDiskType=ASYNC_FLUSH
    #存储路径
    storePathRootDir=/opt/rocketmq/store/slave
    #commitLog存储路径
    storePathCommitLog=/opt/rocketmq/store/slave/commitlog
    #消费队列存储路径
    storePathConsumeQueue=/opt/rocketmq/store/slave/consumequeue
    #消息索引存储路径
    storePathIndex=/opt/rocketmq/store/slave/index
    #checkpoint 文件存储路径
    storeCheckpoint=/opt/rocketmq/store/slave/checkpoint
    #abort 文件存储路径
    abortFile=/opt/rocketmq/store/slave/abort
    #发送消息是否使用可重入锁
    useReentrantLockWhenPutMessage=true
    #消息在发送队列超时时间
    waitTimeMillsInSendQueue=300

    修改启动参数

    默认启动一般需要4-8G的虚拟机jvm参数空间,修改为2g
    两台机器都修改/opt/rocketmq/bin/runserver.sh中的

    JAVA_OPT="${JAVA_OPT} -server -Xms2g -Xmx2g -Xmn2g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
    两台机器都修改/opt/rocketmq/bin/runbroker.sh中的
    JAVA_OPT="${JAVA_OPT} -server -Xms2g -Xmx2g -Xmn2g"
    
    启动服务

    两台服务器都启动mqnamesrv

    nohup sh /opt/rocketmq/bin/mqnamesrv &

    1.1.1.1启动broker

    nohup sh /opt/rocketmq/bin/mqbroker -c /opt/rocketmq/conf/2m-2s-async/broker-a.properties > broker-a.log &

    nohup sh /opt/rocketmq/bin/mqbroker -c /opt/rocketmq/conf/2m-2s-async/broker-a-s.properties > broker-a-s.log &

    1.1.1.2启动broker

    nohup sh /opt/rocketmq/bin/mqbroker -c /opt/rocketmq/conf/2m-2s-async/broker-b.properties > broker-b.log &

    nohup sh /opt/rocketmq/bin/mqbroker -c /opt/rocketmq/conf/2m-2s-async/broker-b-s.properties > broker-b-s.log &

    界面化安装

    上传 rocketmq-console-ng-1.0.1.jar

    nohup java -jar rocketmq-console-ng-1.0.1.jar --server.port=8080 --rocketmq.config.namesrvAddr=127.0.0.1:9876 > mqconsole.log &
    浏览器访问8080端口
    可以看到集群情况

    添加topic
    sc-charge-service-topic
    sc-credit-service-topic
    sc-decision-service-topic
    sc-process-controller-topic
    sc-service-async-topic
    sc-variable-execute-topic

    redis集群安装

    安装包 redis-5.0.4.tar.gz
    redis集群需要6个节点,每台服务器两个节点,所以需要三台中间件服务器
    17.1.111.172 17.1.111.173 17.1.111.174
    (ip只做示范,具体根据实际来)
    redis安装包上传至上面三台服务器指定安装目录后解压
    在每台服务器做如下操作(可开启多个xshell批量发送命令)
    tar zxvf redis-5.0.4.tar.gz
    进入解压后目录进行编译安装

    cd redis-5.0.4
    make && make install
    期间如果有报错就是系统缺少依赖包,根据提示安装即可
    mkdir -p /home/redis-cluster/7001 # 创建集群目录及节点
    mkdir -p /home/redis-cluster/7002 # 创建集群目录及节点
    cp redis.conf /home/redis-cluster/7001
    cp redis.conf /home/redis-cluster/7002
    然后都进行修改配置文件,此处列举一个,其他节点请按实际修改
    vim /home/redis-cluster/7001/redis.conf
    bind 17.1.111.172 //修改为本机ip地址
    port 7001 //定义端口号
    daemonize yes //开启redis后台运行
    masterauth test@redis2019 //设置集群redis连接密码
    requirepass test@redis2019 //修改redis连接密码
    pidfile /home/redis-cluster/7001/redis_7001.pid //pid文件
    logfile “/home/redis-cluster/7001/7001.log” //开启redis的日志文件
    cluster-enabled yes //开启集群
    cluster-config-file nodes_7001.conf //集群的配置 配置文件首次启动自动生成
    cluster-node-timeout 15000 //请求超时
    appendonly yes //aof日志开启

    cp redis.conf …/7002/ //配置文件拷贝到7002文件夹
    替换7002配置文件里的7001配置
    配置都完成后可以启动各个节点,进入配置文件所在目录启动各个节点
    redis-server /home/redis-cluster/7001/redis.conf
    ps -ef | grep redis #查看服务
    其他几台服务也是按上述步骤操作即可,相应ip、目录按实际修改即可
    搭建好redis节点后,现在要创建集群,确认所有的节点都启动
    集群创建方式
    redis-cli -a test@redis2019 --cluster create --cluster-replicas 1 17.1.111.172:7001 17.1.111.172:7002 17.1.111.173:7001 17.1.111.173:7002 17.1.111.174:7001 17.1.111.174:7002
    解释 --replicas 1 表示自动为每一个master节点分配一个slave节点,上面有6个节点,程序会按照一定规则生成3个master(主)3个slave(从)
    运行,提示输入yes
    这里集群已经初步搭建完成
    集群创建成功登陆任意redis结点查询集群中的节点情况。
    redis-cli -c -a test@redis2019 -h 17.1.111.172 -p 7001 // -c表示以集群方式连接redis
    cluster nodes 查询集群结点信息
    cluster info 查询集群状态信息

    终于解决了,问题真出在redis.conf里,该文件里被添加了新的命令如下:

    #新添加
    rename-command FLUSHALL “”
    rename-command FLUSHDB “”
    rename-command KEYS “”
    rename-command SHUTDOWN “”
    rename-command DEL “”
    rename-command EVAL “”

    nacos安装

    安装包

    tar zxvf nacos-server-1.2.1.tar.gz
    1.安装数据库和jdk,版本要求:5.6.5+,jdk1.8
    2.初始化mysql数据库,数据库初始化文件:nacos-mysql.sql
    3.修改conf/application.properties文件,增加支持mysql数据源配置(目前只支持mysql),添加mysql数据源的url、用户名和密码。类似如下
    数据库名字需要自己创建,还有相应的授权。
    4.集群模式在nacos的解压目录nacos/的conf目录下,有配置文件cluster.conf,请每行配置成ip:port。(请配置3个或3个以上节点)
    例如
    192.168.1.1:8848
    192.168.1.2:8848
    192.168.1.3:8848
    5.startup.sh启动配置里面
    exprot MODE=”cluster”#集群模式启动
    exprot MODE=”standalone”#单机模式启动
    sh nacos/bin/startup.sh 启动nacos
    启动后浏览器访问http://ip:8848/nacos
    即可成功访问
    默认账号密码nacos:nacos
    集群模式给三个nacos架构前面搭建一台nginx,nginx搭建参考nginx安装。
    6.由nginx负载三个nacos。配置文件如下:
    upstream nacos {
    server 192.168.1.1:8848;
    server 192.168.1.2:8848;
    server 192.168.1.3:8848;
    }
    server {
    listen 8838;
    server_name localhost;
    location / {
    proxy_pass http://nacos;
    }
    }
    默认账号密码nacos:nacos

    ELK安装

    es安装
    需要jdk1.8版本,具体参照jdk安装
    首先请先优化limits.conf sysctl.conf 文件参数,否则后面启动会报错

    vim /etc/security/limits.conf

    添加
    root soft nofile 65535
    root hard nofile 65535
    * soft nofile 65535
    * hard nofile 65535
    vim /etc/sysctl.conf
    添加
    vm.max_map_count=655360
    sysctl -p
    

    开始部署es集群
    服务器:3台。
    ip分别为192.168.1.1,192.168.1.2,192.168.1.3(实际生产请修改)
    三台机器都操作。

    上传包至/opt/下
    创建一个普通用户
    useradd es
    切换root用户操作
    tar xvf elasticsearch-6.8.6.tar.gz
    mv elasticsearch-6.8.6 elasticsearch
    cd elasticsearch/config/
    vim elasticsearch.yml
    cluster.name: sc #集群名字,三台集群的集群名字都必须一致
    node.name: es1 #节点名字,三台ES节点字都必须不一样
    path.data: /opt/elasticsearch/data
    path.logs: /opt/elasticsearch/logs
    network.host: 192.168.1.1 # 本机IP
    http.port: 9200
    transport.tcp.port: 9300
    transport.tcp.compress: true #压缩tcp传输时的数据
    discovery.zen.ping.unicast.hosts: [“192.168.1.1”,“192.168.1.2”,“192.168.1.3”]
    discovery.zen.minimum_master_nodes: 2 #集群最少的master数
    xpack.security.enabled: true #es访问开启密码认证
    xpack.security.transport.ssl.enabled: true
    http.cors.enabled: true
    http.cors.allow-origin: “*”
    http.cors.allow-headers: Authorization,X-Requested-With,Content-Length,Content-Type
    xpack.security.enabled: true
    xpack.license.self_generated.type: basic
    xpack.security.transport.ssl.enabled: true
    xpack.security.transport.ssl.verification_mode: certificate
    xpack.security.transport.ssl.keystore.path: elastic-certificates.p12
    xpack.security.transport.ssl.truststore.path: elastic-certificates.p12

    bin/elasticsearch-certutil ca
    bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12
    生成的证书放在 config下
    三台机器不一样的配置点如下
    node.name: es1 #192.168.1.1
    node.name: es1 #192.168.1.2
    node.name: es1 #192.168.1.3

    创建目录和修改权限

    mkdir -p /opt/elasticsearch/data
    mkdir -p /opt/elasticsearch/logs
    chown -R es:es /opt/elasticsearch

    切换到es用户

    su es
    cd /opt/elasticsearch
    ./bin/elasticsearch -d #后台运行模式
    浏览器访问9200
    http://localhost:9200/_cluster/health?pretty #查看集群状态
    status:green

    创建es各个组件密码,三台机器都执行

    elasticsearch-setup-passwords interactive
    按提示输入各个组件的账号密码
    密码都是elastic

    logstash安装:

    文件上传到/opt/下

    tar zxvf logstash-6.8.6.tar.gz

    cd logstash-6.8.6/config
    vim logstash.conf # 编辑一个config文件
    input{
    tcp{
    port=> 5044
    codec=> “json”
    }
    }

    output{
    elasticsearch {
    hosts => “192.168.1.10:9200”# es地址
    index => “%{[appname]}-%{+YYYY.MM.dd}”
    user =>“elastic”
    password => “elastic”
    }
    }

    kibana安装:

    安装包上传到/opt/下

    tar zxvf kibana-6.8.6-linux-x86_64.tar.gz
    cd kibana-6.8.6-linux-x86_64/
    vim config/kibana.yml
    server.port: 5601
    server.host: “192.168.1.10”
    elasticsearch.hosts:[“http://192.168.1.10:9200”] # elasticsearch的地址及端口
    elasticsearch.username: “elastic” #连接es的账号密码
    elasticsearch.password:”test@2020
    i18n.locale:”zh-CN”#中文
    grep -vE “$|#” config/kibana.yml # 验证修改的
    screen ./bin/kibana #启动kibana,访问IP:5601

    添加索引

    此时可查看日志是否输出成功,成功即可

    mysql安装

    安装包mysql-5.7.16-linux-glibc2.5-x86_64.tar.gz
    在操作系统中安装MySQL时需将系统自带的MySQL卸载掉,卸载步骤如下:
    检查原来mysql是否安装,有则删除

    rpm -qa | grep mysql

    创建mysql用户

    useradd -M -s /sbin/nologin mysql

    将下载的tar包上传到服务器,解压 (我下载的是免编译的包,解压后可以直接用)

    tar zxvf mysql-5.7.16-linux-glibc2.5-x86_64.tar.gz -C /opt/
    cd /opt/
    mv mysql-5.7.16-linux-glibc2.5-x86_64 mysql
    chown -R mysql:mysql /opt/mysql/
    初始化数据库
    cd /opt/mysql/
    ./bin/mysql_install_db --user=mysql --basedir=/opt/mysql --datadir=/opt/mysql/data 注意看是否有报错
    如有报错 按提示安装系统依赖包 类似安装下这两个
    yum -y install libaio
    yum -y install library
    cp -a ./support-files/my-default.cnf /etc/my.cnf
    cp -a ./support-files/mysql.server /etc/init.d/mysqld
    ./bin/mysqld_safe --user=mysql &

    vim /etc/my.cnf # 修改一下端口号
    [mysqld]
    port=3306

    systemctl enable mysqld
    systemctl restart mysqld
    ps -ef | grep mysql # 注意看是服务是否开启
    cat /root/.mysql_secret # 查看mysql初始化密码
    ln -s /opt/mysql/bin/* /usr/local/sbin/
    mysql -uroot -p
    alter user user() identified by “test@mysql2019”; #修改mysql root用户密码
    flush privileges;
    重启数据库,建议杀死进程
    ps -ef | grep mysql
    kill -9 mysql-pid
    编辑配置文件
    vim /etc/my.cnf
    [mysql]
    default-character-set = utf8

    [mysqld]
    port = 3306
    basedir = /usr/local/mysql
    datadir = /usr/local/mysql/data
    character-set-server = utf8
    collation-server = utf8_general_ci
    default-storage-engine = INNODB
    lower_case_table_names = 1
    tmpdir = /tmp
    socket = /tmp/mysql.sock
    log-error = /opt/mysql/data/error.log
    pid-file = /opt/mysql/data/mysql.pid
    max_connections = 8000
    back_log = 3000
    wait_timeout = 7200
    interactive_timeout = 7200
    key_buffer_size = 1024M
    query_cache_size = 1024M
    query_cache_type = 1
    sort_buffer_size = 1024M
    join_buffer_size = 1024M
    thread_cache_size = 1000
    thread_stack = 1024M
    tmp_table_size = 1024M
    innodb_buffer_pool_size = 30720M
    innodb_flush_log_at_trx_commit = 1
    innodb_thread_concurrrency = 0
    innodb_log_buffer_size = 4096M
    innodb_log_file_size = 4096M
    innodb_flush_method = O_DIRECT

    systemctl start mysqld
    mysql -uroot -p # 新密码登录
    授权远程访问(注意防火墙,selinux是否关闭)
    GRANT ALL PRIVILEGES ON . TO ‘root’@‘%’ IDENTIFIED BY ’ testmysql2019’ WITH GRANT OPTION;
    flush privileges;
    类似grant all on . to user1 identified by ‘123456’;

    设置主从

    两台服务器都需要安装上mysql 以下IP为示例IP

    mysql 主 17.1.111.179
    mysql 从 17.1.111.180
    主mysql配置
    vim my.cnf
    [mysqld]
    log-bin = mysql-bin #开启二进制日志
    binlog_cache_size = 512M
    max_binlog_cache_size = 4096M
    max_binlog_size = 512M
    server-id = 1 #设置server-id
    expire_logs_days = 7 #设置binlog日志保存天数
    sync_binlog = 1
    slow_query_log = on
    slow_query_log_file = /opt/mysql/data/mysql_slow_query.log
    log_queries_not_using_indexs = on
    long_query_time = 1

    重启mysql,创建用于同步的用户账号

    systemctl restart mysqld

    创建用户并授权:用户:test@slave 密码:test@2019

    CREATE USER ‘test@slave’@‘17.1.111.180’ IDENTIFIED BY ‘pwd@2019’; #创建用户
    GRANT REPLICATION SLAVE ON . TO ‘test@slave’@‘17.1.111.180’; #分配权限
    flush privileges;
    SHOW MASTER STATUS; #查看master状态,记录二进制文件名(mysql-bin.000001)和位置(779)

    从mysql配置

    vim my.cnf
    [mysqld]
    server-id=2 #必须唯一

    重启mysql,打开mysql会话,执行同步SQL语句

    systemctl restart mysqld
    mysql -uroot -p
    CHANGE MASTER TO MASTER_HOST=‘17.1.111.180’,MASTER_USER=‘test@slave’,MASTER_PASSWORD=‘test@2019’,MASTER_LOG_FILE=‘mysql-bin.000001’,MASTER_LOG_POS=779;
    start slave; # 启动slave同步进程
    show slave status\G # 查看slave状态

    测试同步,在主mysql建库,看从库是否同步,能同步即可

    CREATE DATABASE database_name # 建库
    CREATE TABLE 表名(
    id int not null,
    name char(20)
    );
    INSERT INTO 表名(列1,列2) VALUES (值1,值2)
    DROP DATABASE 数据库名

  • 相关阅读:
    Ubuntu部分实用工具安装记录
    使用 Qt for Android 获取并利用手机传感器数据(1)开发环境省心搭建
    连接数据库时遇到的bug1号
    大量需求测不过来怎么破?
    TypeScript_抓取酒店价格数据
    《设计模式的运用》使用策略模式+工厂模式优化代码中的if else
    Docker+github actions部署前端项目
    ps神经网络滤镜安装包,ai神经网络滤镜安装包
    Spring Boot集成Elasticsearch实战
    关于docker启动时报错binlog权限问题
  • 原文地址:https://blog.csdn.net/shang_xs/article/details/139771241