ShardingSphere之ShardingProxy实战操作、分布式事务

news2024/9/22 21:36:33

文章目录

    • 简介
    • 基础使用
      • 部署ShardingProxy
      • 配置分库分表策略
    • 分布式事务机制
      • 介绍
      • XA事务Demo
      • 使用另外两种XA事务管理器



简介

ShardingSphere的两个核心产品分别为ShardingJDBC和ShardingProxy。前文已经详细介绍了ShardingJDBC的具体使用,接下来介绍服务端的分库分表ShardingProxy。

定位为一个透明化的数据库代理,目前提供MySQL和PostgreSQL协议,透明化数据库操作。简单理解就是,他会部署成一个MySQL或者PostgreSQL的数据库服务,应用程序只需要像操作单个数据库一样去访问ShardingSphere-proxy,由ShardingProxy去完成分库分表功能。

在这里插入图片描述



ShardingProxy的主要功能如下:

  • 配合 ORM 框架使用更友好

    当使用 ShardingSphere-JDBC 时,需要在代码中直接编写分库分表的逻辑,如果使用 ORM 框架,会产生冲突。ShardingSphere-Proxy 作为服务端中间件,可以无缝对接 ORM 框架。

  • 对 DBA 更加友好

    ShardingSphere-Proxy 作为服务端代理,对 DBA 完全透明。DBA 可以直接操作原始数据源,而不需要了解 ShardingSphere 的功能和 API。这简化了 DBA 的工作,也不会产生额外学习成本。

  • 避免在项目中侵入分库分表逻辑

    使用 ShardingSphere-JDBC,需要在业务代码中编写分库分表规则配置,这会使代码显得繁琐,且一旦规则变更,需要修改大量代码。ShardingSphere-Proxy 通过外部配置实现规则管理,可以避免这种情况。

  • 提供分布式事务支持

    ShardingSphere-Proxy 可以与第三方事务管理器对接,提供对分布式数据库的分布式事务支持。而 ShardingSphere-JDBC 仅支持本地事务。

  • 实现无中心化数据治理

    通过 ShardingSphere-Proxy,可以将多个数据源注册到同一个代理服务中,实现跨数据源的数据治理、监控和报警等功能。这有利于大规模微服务系统的运维。



基础使用

部署ShardingProxy

ShardingProxy 5.2.1版本下载

直接下载地址

ShardingProxy在windows和Linux上提供了一套统一的部署发布包。下载apache-shardingsphere-5.2.1-shardingsphere-proxy-bin.tar.gz文件后,直接进行解压



解压完成后,我们需要把MySQL的JDBC驱动包mysql-connector-java-8.0.15.jar手动复制到%SHARDINGSPHERE_PROXY_HOME%/ext-lib目录下,ext-lib目录需要我们自己创建,所有扩展的jar包都丢在这里面。ShardingProxy默认只附带了PostgreSQL的JDBC驱动包,而不包含MySQL的JDBC驱动包。

在这里插入图片描述



接下来进入conf目录,进行相关的配置,常见的几个配置文件如下所示

每个配置文件里都给出了配置的示例,照着改改就行。再加上我们学习过ShardingJDBC,所以基本上是无门槛看懂这些配资

在这里插入图片描述



先打开server.yaml,更改其中的配置

mode:
  type: standalone    # 我这里先以单机启动
#  type: Cluster
#  repository:
#    type: ZooKeeper
#    props:
#      namespace: governance_ds
#      server-lists: localhost:2181
#      retryIntervalMilliseconds: 500
#      timeToLiveSeconds: 60
#      maxRetries: 3
#      operationTimeoutMilliseconds: 500

rules:
  - !AUTHORITY
    users:				# 连接用户名密码
      - root@%:root
      - sharding@:sharding
    provider:				# 权限
      type: ALL_PERMITTED
  - !TRANSACTION			# 分布式事务
    defaultType: XA
    providerType: Atomikos
  - !SQL_PARSER
    sqlCommentParseEnabled: true
    sqlStatementCache:
      initialCapacity: 2000
      maximumSize: 65535
    parseTreeCache:
      initialCapacity: 128
      maximumSize: 1024

props:
  max-connections-size-per-query: 1
  kernel-executor-size: 16  # Infinite by default.
  proxy-frontend-flush-threshold: 128  # The default value is 128.
  proxy-hint-enabled: false		# 是否允许hint
  sql-show: false			# 是否打印日志
  check-table-metadata-enabled: false
    # Proxy backend query fetch size. A larger value may increase the memory usage of ShardingSphere Proxy.
    # The default value is -1, which means set the minimum value for different JDBC drivers.
  proxy-backend-query-fetch-size: -1
  proxy-frontend-executor-size: 0 # Proxy frontend executor size. The default value is 0, which means let Netty decide.
    # Available options of proxy backend executor suitable: OLAP(default), OLTP. The OLTP option may reduce time cost of writing packets to client, but it may increase the latency of SQL execution
    # and block other clients if client connections are more than `proxy-frontend-executor-size`, especially executing slow SQL.
  proxy-backend-executor-suitable: OLAP
  proxy-frontend-max-connections: 0 # Less than or equal to 0 means no limitation.
    # Available sql federation type: NONE (default), ORIGINAL, ADVANCED
  sql-federation-type: NONE
    # Available proxy backend driver type: JDBC (default), ExperimentalVertx
  proxy-backend-driver-type: JDBC
  proxy-mysql-default-version: 8.0.15 # 修改成我们自己的版本
  proxy-default-port: 3307 # 连接端口
  proxy-netty-backlog: 1024 # Proxy netty backlog.



  • mode部分的配置就是ShardingProxy的启动方式,默认是集群方式启动的,配置中心使用的是zookeeper,我们也可以先暂时改为单机启动

  • rules

    • AUTHORITY部分就是登录用户名密码以及权限,前文就介绍过ShardingProxy是一个数据库代代理,我们可以把它当成一个数据库,这里就是该数据库的登录用户
    • TRANSACTION部分分布式事务控制器,下文会详细介绍
  • props部分配置服务端的一些参数

    • max-connections-size-per-query参数是对于ShardingProxy最重要的优化参数,表示一个数据库连接对象最大执行的sql数。在上一章节介绍ShardingSphere的执行引擎以及结果归并时介绍到了,

      如果只需要一个数据库连接就能完成相关操作就是内存限制模式,结果归并时是流式分组归并,查询相对慢,结果归并效率相对高;如果需要多个数据库连接才能完成相关操作就是连接限制模式,结果归并时是内存分组归并,因为多个连接同时查询所以查询相对快,结果归并效率相对慢。

      举例:通过sql解析我知道了一次业务请求需要执行5条sql,但是我max-connections-size-per-query参数设置了1就表示一个连接对象只能执行一条sql,那么就需要5个连接对象,如果max-connections-size-per-query参数设置了5,就表示我只需要一个连接对象

    • proxy-mysql-default-version表示ShardingProxy所模拟的MySQL服务版本。为了与之前的示例兼容,我们这里可以将它改成8.0.15版本。

    • proxy-default-port表示模拟的MySQL服务的端口。 最好和本机mysql真实启动端口区分开,避免端口冲突



接下来运行bin/start.bat进行启动

在这里插入图片描述



进行连接测试

在这里插入图片描述



配置分库分表策略

我们此时连接,发下会报错,因为我们还没有配置相关的分库分表路由策略

在这里插入图片描述



接下来操作conf/config-sharding.yaml文件,该文件中上方是postgresql配置,下方是mysql配置。具体的配置内容就和ShardingJDBC一样,具体配置如下

# 指定数据库名,也就是连接ShardingProxy时 使用的是哪一个数据库
databaseName: sharding_hs_db

dataSources:
  ds_0:
    url: jdbc:mysql://localhost:3306/sharding_sphere1?serverTimezone=UTC&useSSL=false
    username: root
    password: 1234
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
  ds_1:
    url: jdbc:mysql://localhost:3306/sharding_sphere2?serverTimezone=UTC&useSSL=false
    username: root
    password: 1234
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1

rules:
- !SHARDING
  tables:
    # 逻辑表
    sys_user:
      actualDataNodes: ds_${0..1}.sys_user${1..2}
      # 分表策略
      tableStrategy:
        standard:
          shardingColumn: uid
          shardingAlgorithmName: sys_user_tab_alg
      # 分布式主键生成策略
      keyGenerateStrategy:
        column: uid
        keyGeneratorName: alg_snowflake


  # 默认分库策略
  defaultDatabaseStrategy:
    standard:
      shardingColumn: uid
      shardingAlgorithmName: database_inline
  # 默认分表策略
  defaultTableStrategy:
    none:

  # 分片策略
  shardingAlgorithms:
    database_inline:
      type: INLINE
      props:
        algorithm-expression: ds_${uid % 2}
    sys_user_tab_alg:
      type: INLINE
      props:
        algorithm-expression: sys_user$->{((uid+1)%4).intdiv(2)+1}
  
  # 分布式主键生成策略
  keyGenerators:
    alg_snowflake:
      type: COSID_SNOWFLAKE



接下来再重启ShardingProxy服务,在进行连接

在这里插入图片描述



多数据库,出现为分片数据表同名情况

这里有一个小问题,如下图所示,我两个真实数据库中都存在user_info1 user_info2数据表,我没有在ShardingProxy中配置user_info数据表相关的分片规则,此时只有一个sys_user表的分片规则,在ShardingProxy中保存是user_info1 user_info2数据表的内容只有下面两个数据库的其中一个数据库中的内容。

在这里插入图片描述



真实库中,存在真实表和分片逻辑表同名情况

直接访问ShardingProxy的sys_user逻辑表,只会查询到对应分片路由规则真实表数据,而不会存在下方uid=1026的数据

在这里插入图片描述



分布式事务机制

介绍

开发者手册

用户手册

在ShardingProxy的conf/server.yaml配置文件中,有以下的默认配置项

在这里插入图片描述



ShardingProxy默认是使用的XA方式来保证的分布式事务,而且默认使用的是Atomikos框架。

我们从开发者手册可以得知,目前它支持三种XA分布式事务管理器



全限定类名:org.apache.shardingsphere.transaction.xa.spi.XATransactionManagerProvider

XA 分布式事务管理器,已知实现

配置标识详细说明类名
Atomikos基于 Atomikos 的 XA 分布式事务管理器AtomikosTransactionManagerProvider
Narayana基于 Narayana 的 XA 分布式事务管理器NarayanaXATransactionManagerProvider
Bitronix基于 Bitronix 的 XA 分布式事务管理器BitronixXATransactionManagerProvider



XA事务Demo

引入Maven依赖

<!--XA 分布式事务 -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-transaction-xa-core</artifactId>
    <version>5.2.1</version>
    <exclusions>
        <exclusion>
            <artifactId>transactions-jdbc</artifactId>
            <groupId>com.atomikos</groupId>
        </exclusion>
        <exclusion>
            <artifactId>transactions-jta</artifactId>
            <groupId>com.atomikos</groupId>
        </exclusion>
    </exclusions>
</dependency>
<!-- 版本滞后了 -->
<dependency>
    <artifactId>transactions-jdbc</artifactId>
    <groupId>com.atomikos</groupId>
    <version>5.0.8</version>
</dependency>
<dependency>
    <artifactId>transactions-jta</artifactId>
    <groupId>com.atomikos</groupId>
    <version>5.0.8</version>
</dependency>

<!-- 使用XA事务时,可以引入其他几种事务管理器 -->
<!--        <dependency>-->
<!--            <groupId>org.apache.shardingsphere</groupId>-->
<!--            <artifactId>shardingsphere-transaction-xa-bitronix</artifactId>-->
<!--            <version>5.2.1</version>-->
<!--        </dependency>-->
<!--        <dependency>-->
<!--            <groupId>org.apache.shardingsphere</groupId>-->
<!--            <artifactId>shardingsphere-transaction-xa-narayana</artifactId>-->
<!--            <version>5.2.1</version>-->
<!--        </dependency>-->



配置事务管理器

@Configuration
@EnableTransactionManagement
public class TransactionConfiguration {
    
    @Bean
    public PlatformTransactionManager txManager(final DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}



然后就可以写一个示例

public class MySQLXAConnectionTest {
    public static void main(String[] args) throws SQLException {
        //true表示打印XA语句,,用于调试
        boolean logXaCommands = true;
        // 获得资源管理器操作接口实例 RM1
        Connection conn1 = DriverManager.getConnection("jdbc:mysql://localhost:3306/coursedb?serverTimezone=UTC", "root", "root");
        XAConnection xaConn1 = new MysqlXAConnection((com.mysql.cj.jdbc.JdbcConnection) conn1, logXaCommands);
        XAResource rm1 = xaConn1.getXAResource();
        
        // 获得资源管理器操作接口实例 RM2
        Connection conn2 = DriverManager.getConnection("jdbc:mysql://localhost:3306/coursedb2?serverTimezone=UTC", "root", "root");
        XAConnection xaConn2 = new MysqlXAConnection((com.mysql.cj.jdbc.JdbcConnection) conn2, logXaCommands);
        XAResource rm2 = xaConn2.getXAResource();
        
        // AP请求TM执行一个分布式事务,TM生成全局事务id
        byte[] gtrid = "g12345".getBytes();
        int formatId = 1;
        try {
            // ==============分别执行RM1和RM2上的事务分支====================
            // TM生成rm1上的事务分支id
            byte[] bqual1 = "b00001".getBytes();
            Xid xid1 = new MysqlXid(gtrid, bqual1, formatId);
            // 执行rm1上的事务分支
            rm1.start(xid1, XAResource.TMNOFLAGS);//One of TMNOFLAGS, TMJOIN, or TMRESUME.
            PreparedStatement ps1 = conn1.prepareStatement("INSERT INTO `dict` VALUES (1, 'T', '测试1');");
            ps1.execute();
            rm1.end(xid1, XAResource.TMSUCCESS);
            
            // TM生成rm2上的事务分支id
            byte[] bqual2 = "b00002".getBytes();
            Xid xid2 = new MysqlXid(gtrid, bqual2, formatId);
            // 执行rm2上的事务分支
            rm2.start(xid2, XAResource.TMNOFLAGS);
            PreparedStatement ps2 = conn2.prepareStatement("INSERT INTO `dict` VALUES (2, 'F', '测试2');");
            ps2.execute();
            rm2.end(xid2, XAResource.TMSUCCESS);
            
            // ===================两阶段提交================================
            // phase1:询问所有的RM 准备提交事务分支
            int rm1_prepare = rm1.prepare(xid1);
            int rm2_prepare = rm2.prepare(xid2);
            // phase2:提交所有事务分支
            boolean onePhase = false; //TM判断有2个事务分支,所以不能优化为一阶段提交
            if (rm1_prepare == XAResource.XA_OK
                    && rm2_prepare == XAResource.XA_OK
            ) {//所有事务分支都prepare成功,提交所有事务分支
                rm1.commit(xid1, onePhase);
                rm2.commit(xid2, onePhase);
            } else {//如果有事务分支没有成功,则回滚
                rm1.rollback(xid1);
                rm1.rollback(xid2);
            }
        } catch (XAException e) {
            // 如果出现异常,也要进行回滚
            e.printStackTrace();
        }
    }
}



这其中,XA标准规范了事务XID的格式。有三个部分: gtrid [, bqual [, formatID ]] 其中

  • gtrid 是一个全局事务标识符 global transaction identifier
  • bqual 是一个分支限定符 branch qualifier 。如果没有提供,会使用默认值就是一个空字符串。
  • formatID 是一个数字,用于标记gtrid和bqual值的格式,这是一个正整数,最小为0,默认值就是1。



但是使用XA事务时需要注意以下几点:

  • XA事务无法自动提交
  • XA事务效率非常低下,全局事务的状态都需要持久化。性能非常低下,通常耗时能达到本地事务的10倍。
  • XA事务在提交前出现故障的话,很难将问题隔离开。



使用另外两种XA事务管理器

我们从开发者手册可以得知,在ShardingProxy5.2.1版本中它支持三种XA分布式事务管理器。如果不想使用默认的Atomikos,而去使用Narayana,具体的操作如下所示:

全限定类名:org.apache.shardingsphere.transaction.xa.spi.XATransactionManagerProvider

XA 分布式事务管理器,已知实现

配置标识详细说明类名
Atomikos基于 Atomikos 的 XA 分布式事务管理器AtomikosTransactionManagerProvider
Narayana基于 Narayana 的 XA 分布式事务管理器NarayanaXATransactionManagerProvider
Bitronix基于 Bitronix 的 XA 分布式事务管理器BitronixXATransactionManagerProvider



我们微服务项目中,默认情况下都是没有这个包的

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
    <version>5.2.1</version>
</dependency>

在这里插入图片描述



我们可以通过下载ShardingProxy的源码包,从源码包中找上上方对应的NarayanaXATransactionManagerProvider,然后查看这个类所在是pom文件,最终找到pom依赖

<!--        <dependency>-->
<!--            <groupId>org.apache.shardingsphere</groupId>-->
<!--            <artifactId>shardingsphere-transaction-xa-bitronix</artifactId>-->
<!--            <version>5.2.1</version>-->
<!--        </dependency>-->
<!--        <dependency>-->
<!--            <groupId>org.apache.shardingsphere</groupId>-->
<!--            <artifactId>shardingsphere-transaction-xa-narayana</artifactId>-->
<!--            <version>5.2.1</version>-->
<!--        </dependency>-->

我们在微服务中导入上面对应的依赖,再从本地maven仓库中拿到对应的jar包,丢到%SHARDINGSPHERE_PROXY_HOME%/ext-lib目录下



在server.yaml中就可以将事务的Provider配置成Narayana

下面这个Narayana字符串是通过源码NarayanaXATransactionManagerProvider类的getType()方法中定义的

rules:
  - !TRANSACTION
    defaultType: XA
    providerType: Narayana

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1982402.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MyBatis搭建和增删改查

MyBatis是一个开源的持久层框架&#xff0c;用于处理数据库的增删改查操作。它能够将Java对象与数据库中的数据进行映射关系的配置&#xff0c;并自动生成对应的SQL语句&#xff0c;从而简化了数据库操作的编码工作。 MyBatis的核心思想是将SQL语句与Java代码分离&#xff0c;…

Java01 Java预备知识

第一节&#xff1a;Java预备知识 进制转化 &#xff08;1&#xff09;&#xff1a;二进制转十进制采用数字与阶码相乘并相加&#xff0c;阶码从右往左依次增大&#xff0c;从左往右依次减小。 例&#xff1a;100&#xff08;2&#xff09;0*2^00*2^11*2^44(10) (2)&#xff1a…

【远程桌面】远程连接服务器时出现“这可能是由于CredSSP加密数据库修正”的错误提示的解决办法

转发原文&#xff1a;https://blog.csdn.net/juanjuan_01/article/details/127005255 错误提示 Windows10系统中远程连接服务器的时候出现如下错误的提示&#xff1a; 解决方案一&#xff1a; 步骤1、winR打开运行窗口 步骤2、输入gpedit.msc命令&#xff0c;点击“确定”&a…

Go语言-- 版本管理go module以及go.sum详解

为了确保一致性构建&#xff0c;Go语言中引入了go.mod文件来标记每个依赖包的版本&#xff0c;在构建过程中go命令会下载go.mod中的依赖包&#xff0c;下载的依赖包会缓存在本地&#xff0c;以便下次构建。 在进行go语言项目开发的时候&#xff0c;会依赖3种类型的库包&#x…

使用ThreadLocal来存取单线程内的数据

一.什么是ThreadLocal&#xff1f; ThreadLocal&#xff0c;即线程本地变量。如果你创建了一个 ThreadLocal变量&#xff0c;那么访问这个变量的每个线程都会有这个变量的一个本地拷贝&#xff0c;多个线程操作这个变量的时候&#xff0c;实际是在操作自己本地内存里面的变量&…

Selenium+Python自动化测试:解决无法启动IE浏览器及报错问题

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 前言&#xff1a;记录启动IE浏览器的报错及解决方法。 错误1&#xff1a; selenium.common.exceptions.WebDriverException: Message: IEDriverServer.exe execu…

MySQL:索引(Index)语句

索引的限制 每个表最多可以有 16 个索引&#xff08;InnoDB 表的限制&#xff09;。 单个索引最多可以包含 16 列。 索引列的最大长度为 767 字节&#xff08;对于 CHAR, VARCHAR, 和 BINARY 类型&#xff09;&#xff0c;3072 字节&#xff08;对于 BLOB 类型&#xff09;。…

网鼎杯比赛二次注入技巧

文章目录 前端的网页展示分析题目暴力破解寻找代码找到注入点进行注入查询想要的文件 前端的网页展示 分析题目 1.目前我们能看到的只有三个页面&#xff0c;但是我们可以看到三个*号。 2.考虑三个*的密码是什么&#xff0c;这里可以采用暴力破解&#xff08;我们先猜这是三个…

【精选】6款一键生成论文的软件3000字论文网站

千笔-AIPassPaPer是一款功能强大且全面的AI论文写作工具&#xff0c;特别适合学术研究者和学生使用。它不仅能够一键生成高质量的论文初稿&#xff0c;还涵盖了700多个学科专业方向&#xff0c;满足各种学术需求。 一、千笔-AIPassPaPer 传送门&#xff1a;https://www.aipape…

Codeforces Round 963 (Div. 2) A-C

A. Question Marks 直接模拟一遍&#xff0c;&#xff1f;跳过&#xff0c;其他统计 #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<map> using namespace std; int t, n; int w[200005]; int main() …

论文辅导 | 基于概率密度估计与时序Transformer网络的风功率日前区间预测

辅导文章 模型描述 本文所提出的时序优化Transformer 结构&#xff0c;该模型从结构上看由三部分组成&#xff1a;向量映射、编码器和解码器。编码器输入为数值天气预报数据以及相应的时间编码。解码器输入为预测日之前输出功率历史数据以及相应的时间编码。这些数据在经过向量…

【C++高阶】深入理解C++异常处理机制:从try到catch的全面解析

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;Lambda表达式 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀C异常 &#x1f4d2;1. C异常概念…

MySQL基础:int(1) 和 int(10) 有什么区别

在数据库设计与维护的日常工作中&#xff0c;一个常见但易引发误解的话题围绕着整型字段&#xff08;如INT&#xff09;的显示宽度&#xff08;如int(1)、int(10)&#xff09;的实际作用。这一现象不仅在新手中频繁出现&#xff0c;就连经验丰富的开发者也时常陷入误区。最近&a…

2024年【山东省安全员B证】考试报名及山东省安全员B证证考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 山东省安全员B证考试报名参考答案及山东省安全员B证考试试题解析是安全生产模拟考试一点通题库老师及山东省安全员B证操作证已考过的学员汇总&#xff0c;相对有效帮助山东省安全员B证证考试学员顺利通过考试。 1、【…

Linux驱动开发—设备树基本概念,语法详解

文章目录 什么是设备树&#xff0c;为什么引入设备树&#xff1f;设备树基本概念相关术语解释设备树源码所在地使用DTC编译设备树基本的DTC编译命令基本的反编译命令效果演示&#xff08;编译与反编译&#xff09; 设备树语法1. 节点 (Node)2. 属性 (Property)3. 包含文件 (Inc…

uniapp svgIcon组件封装

utils/svg/index.ts 存放处理svg的相关方法 // svg 转成url export function svgToUrl(url: any) {var encoded url.replace(/<!--(.*)-->/g, "").replace(/[\r\n]/g, " ").replace(/"/g, ).replace(/%/g, "%25").replace(/&/…

CSDN 僵尸粉 机器人

CSDN 僵尸粉 机器人 1. 前言 不知道什么时候开始每天创作2篇就有1500流量爆光&#xff0c;每次都能收获一些关注和收藏&#xff0c;感觉还是挻开心的感觉CSDN人气还是挻可以的以前各把月一个收藏和关注都没有写的动力了。 2. 正文 后面又连接做了2天的每日创建2篇任务&…

计算机网络408 2017

https://www.zhihu.com/people/suixinyuan1990 【CN】数据链路层.滑动窗口.GBN协议传输过程信道利用率分析_哔哩哔哩_bilibili okokokok 408考研 计算机网络历年真题 分类汇总和解析—【信道利用率】&#xff08;字幕版&#xff09; 408考研 计算机网络历年真题 分类汇总和…

能见度怎么测?应该用什么仪器测呢?

在气象观测、交通安全以及环境监测等多个领域&#xff0c;能见度的准确测量至关重要。那么&#xff0c;能见度究竟是如何测量的呢&#xff1f;答案就是借助先进的能见度测量仪。 能见度测量仪利用光学原理&#xff0c;通过测量空气中微小颗粒&#xff08;如气体分子、气溶胶粒子…

盐城销量比赛 -- YR Tech团队比赛攻略

关联比赛: [印象盐城]数创未来大数据竞赛 - 乘用车零售量预测 查看更多内容&#xff0c;欢迎访问天池技术圈官方地址&#xff1a;盐城销量比赛 -- YR Tech团队比赛攻略_天池技术圈-阿里云天池