织梦源码模板下载商城网站模板 整站带栏目高端大气上档次含数据/seo诊断网站
sentinel无法读取nacos配置问题分析
- 1.spring-cloud-gateway整合sentinel
- 2.问题现象
- 3.原因猜测
- 4.源码分析
- 4. 结语
最近公司需要上线一个集约项目,虽然为内网项目,但曾经有过内网被攻破,导致内部系统被攻击的案例,且集约系统同时在线人数较多,所以需要对系统整体进行流控。市面上的流控方案有很多,不过新系统已经集成了sprin-cloud-alibaba-nacos,所以技术选型就选择了阿里的流控系统sentinel。
1.spring-cloud-gateway整合sentinel
- springcloud项目整合sentinel需要引入sentinel相关组件
<!-- SpringCloud Alibaba Sentinel --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency><!-- SpringCloud Alibaba Sentinel Gateway --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId></dependency>
- 因为我们选择将流控规则持久化到nacos中,所以还需要引入sentinel的nacos数据库插件依赖
<!-- Sentinel Datasource Nacos --><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId></dependency>
- 配置sentinel控制台地址及nacos相关信息
spring:cloud:nacos:username: your-namepassword: your-passdiscovery:# 服务注册地址server-addr: your-addrnamespace: your-namespaceconfig:# 配置中心地址server-addr: your-addrnamespace: your-namespace# 配置文件格式file-extension: ymlsentinel:# 取消控制台懒加载eager: truetransport:# 控制台地址dashboard: your-dashboard-addr# nacos配置持久化datasource:ds1:nacos:server-addr: ${spring.cloud.nacos.discovery.server-addr}namespace: ${spring.cloud.nacos.discovery.namespace}username: ${spring.cloud.nacos.username}password: ${spring.cloud.nacos.password}# 限流规则的nacos配置名称dataId: sentinel-gatewaygroupId: DEFAULT_GROUPdata-type: json# 规则类型:网关限流# 这是枚举类,其他类型可以在com.alibaba.cloud.sentinel.datasource.RuleType这个枚举类中查看rule-type: gw-flow
- 下载sentinel-dashboard的jar包【传送门】;执行启动命令:
还可以指定用户名及密码,通过java -Dserver.port=8088 -Dcsp.sentinel.dashboard.server=localhost:8088 -Dcsp.sentinel.app.type=1 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.8.jar
-Dsentinel.dashboard.auth.username
和-Dsentinel.dashboard.auth.password
配置,不配置默认用户名密码都是sentinel。 - 启动网关及sentinel控制台,查看网关是否已经注册,查看控制台是否已经有服务注册
2.问题现象
- 上面一通操作之后,本地启动了个nacos,gateway和sentinel控制台看了一下,嗯,没问题,提交,发布测试
- 测试环境使用k8s部署,部署完网关及sentinel控制台服务后,访问控制台。网关成功注册到nacos及sentinel控制台,再查看流控规则,居然没有读取到nacos中持久化的流控策略
3.原因猜测
- 问题一出肯定要排查呀,百度了一下有没有人遇到相似的问题,百度的结果很多,但是都不符合我的情况。
- 猜测问题应该出现在环境问题上。测试环境jdk和本地版本相同,nacos版本相同,sentinel-dashboard版本相同。可能问题出现在配置上。
- 还记得我们上面怎么配置sentinel datasource的吗
因为我们是部署在k8s中,nacos的访问地址密码等都配置在环境变量中,相当于bootstrap.yml的配置的配置其实一直是本地的配置,而 ${spring.cloud.nacos.discovery.server-addr}这种配置方式是直接读取bootstrap.yml中的nacos地址,其他的属性也是如此,相当于读取的全部都是本地环境的nacos配置,导致sentinel读取配置文件失败。datasource:ds1:nacos:server-addr: ${spring.cloud.nacos.discovery.server-addr}namespace: ${spring.cloud.nacos.discovery.namespace}username: ${spring.cloud.nacos.username}password: ${spring.cloud.nacos.password}# 限流规则的nacos配置名称dataId: sentinel-gatewaygroupId: DEFAULT_GROUPdata-type: json# 规则类型:网关限流# 这是枚举类,其他类型可以在com.alibaba.cloud.sentinel.datasource.RuleType这个枚举类中查看rule-type: gw-flow
- 解决方法:springboot支持直接读取系统环境变量,配置方法也是
${系统变量名}
,并开启了sentinel日志配置,配置如下:
再次发布版本启动网关,查看sentinel控制台发现已经能够从nacos中读取持久化流控策略。问题到这里已经解决了,如果你和我一样好奇sentinel是如何从nacos配置文件中读取配置文件的话,那就继续往下看吧sentinel:# 取消控制台懒加载eager: truetransport:# 控制台地址dashboard: 127.0.0.1:8088# nacos配置持久化ds1:datasource:nacos:server-addr: ${NacosServerAddr}namespace: ${ConfigNamespace}username: ${username}password: ${password}dataId: sentinel-iwos-gatewaygroupId: DEFAULT_GROUPdata-type: jsonrule-type: gw-flowlog:dir: /usr/local/logs/iwos-gateway
4.源码分析
-
sentinel控制台是从哪里获取的配置文件
-
sentinel控制台有访问页面,既然有页面那么可以从页面查看获取数据入口
-
sentinel控制台是调用了http://127.0.0.1:8088/gateway/flow/list.json?app=mygateway&ip=127.0.0.1&port=8720获取了配置的流控规则。到git上把sentinel源码拉下来,我们来看看这个接口:
@GetMapping("/list.json") @AuthAction(AuthService.PrivilegeType.READ_RULE) public Result<List<GatewayFlowRuleEntity>> queryFlowRules(String app, String ip, Integer port) {// 上面是一些参数校验,不重要,可以不看try {// 这里是获取配置的核心代码// 简单就是网关将自己注册到sentinel时,携带自身的ip和端口(这里可以在启动项配置固定值,如果不配置就是默认本地的ip和网关sentinel端口)// sentinel控制台访问网关集成的sentinel开放的端口,查询持久化在配置中心的配置文件List<GatewayFlowRuleEntity> rules = sentinelApiClient.fetchGatewayFlowRules(app, ip, port).get();repository.saveAll(rules);return Result.ofSuccess(rules);} catch (Throwable throwable) {logger.error("query gateway flow rules error:", throwable);return Result.ofThrowable(-1, throwable);} }
所以其实配置文件不是dashboard控制台去读取的,而是从网关的sentinel开放的restapi中拉取。
public CompletableFuture<List<GatewayFlowRuleEntity>> fetchGatewayFlowRules(String app, String ip, int port) {if (StringUtil.isBlank(ip) || port <= 0) {return AsyncUtils.newFailedFuture(new IllegalArgumentException("Invalid parameter"));}try {// FETCH_GATEWAY_FLOW_RULE_PATH: gateway/getRules// 这里就是通过rest请求获取配置文件return executeCommand(ip, port, FETCH_GATEWAY_FLOW_RULE_PATH, false).thenApply(r -> {List<GatewayFlowRule> gatewayFlowRules = JSON.parseArray(r, GatewayFlowRule.class);List<GatewayFlowRuleEntity> entities = gatewayFlowRules.stream().map(rule -> GatewayFlowRuleEntity.fromGatewayFlowRule(app, ip, port, rule)).collect(Collectors.toList());return entities;});} catch (Exception ex) {logger.warn("Error when fetching gateway flow rules", ex);return AsyncUtils.newFailedFuture(ex);}}
控制台是请求网关gateway/getRules这个路径来获取配置文件的,完整的url为:
http://ip:port/gateway/getRules
。
来看看网关sentinel这个api是怎么工作的。@CommandMapping( name = "gateway/getRules", desc = "Fetch all gateway rules" ) public class GetGatewayRuleCommandHandler implements CommandHandler<String> {public GetGatewayRuleCommandHandler() {}// 获取配置文件public CommandResponse<String> handle(CommandRequest request) {// 有效代码就是GatewayRuleManager.getRules()return CommandResponse.ofSuccess(JSON.toJSONString(GatewayRuleManager.getRules()));} }
看一下GatewayRuleManager.getRules()
public static Set<GatewayFlowRule> getRules() {Set<GatewayFlowRule> rules = new HashSet();// 这里是读的内存中的一个map,往下看这个map是GatewayRulePropertyListener在监听器中进行加载和更新的Iterator var1 = GATEWAY_RULE_MAP.values().iterator();while(var1.hasNext()) {Set<GatewayFlowRule> ruleSet = (Set)var1.next();rules.addAll(ruleSet);}return rules; }
GatewayRulePropertyListener中的逻辑简单看下
private static final class GatewayRulePropertyListener implements PropertyListener<Set<GatewayFlowRule>> {private GatewayRulePropertyListener() {}public void configUpdate(Set<GatewayFlowRule> conf) {this.applyGatewayRuleInternal(conf);RecordLog.info("[GatewayRuleManager] Gateway flow rules received: {}", new Object[]{GatewayRuleManager.GATEWAY_RULE_MAP});}public void configLoad(Set<GatewayFlowRule> conf) {this.applyGatewayRuleInternal(conf);RecordLog.info("[GatewayRuleManager] Gateway flow rules loaded: {}", new Object[]{GatewayRuleManager.GATEWAY_RULE_MAP});} }
这里是通过监听器调用configLoad方法来初始化加载配置规则,但是哪里创建监听器,创建的什么监听器,从这里已经无法再看出来了。线索中断了。。。。。要放弃吗?不!小小监听器,拿下。既然这个方向已经查不到什么信息了,那么我们换一个思路,来看看网关这边是在哪里读取nacos配置信息,然后顺藤摸瓜应该就能找出到底是哪里读取的文件。
-
-
sentinel是如何读取你的配置文件
想要知道哪个类读取的你的配置文件,这里,使用IDEA的朋友们可以按住control,同时单击配置项,就能快速定位到引用配置文件。
下面是我们定位到的地方:@ConfigurationProperties(// 读取spring.cloud.sentinel下的所有属性配置prefix = "spring.cloud.sentinel" ) public class SentinelProperties {// 省略其他代码...private Map<String, DataSourcePropertiesConfiguration> datasource;// 省略其他代码// 我们的配置文件就是映射到Map<String, DataSourcePropertiesConfiguration>中// map整体结构就是{"ds1:":{"nacos":{....[配置的nacos属性]}}}public void setDatasource(Map<String, DataSourcePropertiesConfiguration> datasource) {this.datasource = datasource;} }
如果不是用IDEA开发的要怎么看呢,其实也有个通用的方法,
去看resources中META-INFO目录下spring自动装配的类。sentinel入口jar包是spring-cloud-starter-alibaba-sentinel-2021.0.6.0.jar
。META-INFO下有一个spring.factories
文件,spring会在启动的时候加载这个文件中的工厂类。看看这个文件里有哪些:org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.alibaba.cloud.sentinel.SentinelWebAutoConfiguration,\ com.alibaba.cloud.sentinel.SentinelWebFluxAutoConfiguration,\ com.alibaba.cloud.sentinel.endpoint.SentinelEndpointAutoConfiguration,\ com.alibaba.cloud.sentinel.custom.SentinelAutoConfiguration,\ com.alibaba.cloud.sentinel.feign.SentinelFeignAutoConfiguration
加载用户配置的是
SentinelAutoConfiguration
类。@Configuration(proxyBeanMethods = false) @ConditionalOnProperty(name = "spring.cloud.sentinel.enabled", matchIfMissing = true) @EnableConfigurationProperties(SentinelProperties.class) public class SentinelAutoConfiguration {@Value("${project.name:${spring.application.name:}}")private String projectName;@Autowiredprivate SentinelProperties properties;// 其他代码省略.... }
可以看到这里在创建bean的时候注入了
SentinelProperties
,也就是刚才我们通过IDEA定位到的配置类。两种方法都了解之后我们继续看
SentinelProperties
中的DataSourcePropertiesConfiguration
。public class DataSourcePropertiesConfiguration {// 省略其他数据源的代码配置...// 刚才的setDatasource就是拿到map中的value找到对应的属性类,也就是{"nacos":{...[配置的nacos属性]}}// 从这里可以看出datasource的key是无所谓写什么值得,也就是配置类中的ds1.nacos可以替换成任意key.nacos// 测试了一下改成datasource.nacos也完全没有问题private NacosDataSourceProperties nacos; }
nacos配置类
public class NacosDataSourceProperties extends AbstractDataSourceProperties {// 这些都是sentinel可以配置的nacos配置项private String serverAddr;private String contextPath;private String username;private String password;@NotEmptyprivate String groupId = "DEFAULT_GROUP";@NotEmptyprivate String dataId;private String endpoint;private String namespace;private String accessKey;private String secretKey;public NacosDataSourceProperties() {super(NacosDataSourceFactoryBean.class.getName());}// 预先检查,如果地址为空就设置一个默认的nacos地址@Overridepublic void preCheck(String dataSourceName) {if (StringUtils.isEmpty(serverAddr)) {serverAddr = this.getEnv().getProperty("spring.cloud.sentinel.datasource.nacos.server-addr","127.0.0.1:8848");}} }
nacos配置类就是我们常规的配置,还记得sentinel是在哪个key下找到nacos的配置吗,可以回去看看
sentinelProperties
。它从spring.cloud.sentinel
下读取一个map作为数据源。这个map的结构是Map<String, DataSourcePropertiesConfiguration> datasource
。也就是spring会把spring.cloud.sentinel.任意key
下的配置全部映射到DataSourcePropertiesConfiguration
中。如果你配置的是nacos数据源,那么就需要将nacos配置在spring.cloud.sentinel.任意key.nacos
下,spring会将属性值自动映射到名为nacos的成员变量上,这个成员变量的类就是NacosDataSourceProperties
。
4. 结语
好了,到这里sentinel已经全部拿到nacos的配置信息了,后面就是调用nacos rpc接口进行认证及获取配置文件。如果觉得有用就点个赞吧
相关文章:

网关整合sentinel无法读取nacos配置问题分析
sentinel无法读取nacos配置问题分析 1.spring-cloud-gateway整合sentinel2.问题现象3.原因猜测4.源码分析4. 结语 最近公司需要上线一个集约项目,虽然为内网项目,但曾经有过内网被攻破,导致内部系统被攻击的案例,且集约系统同时在…...

简化XPath表达式的方法与实践
XPath表达式用于在XML或HTML文档中定位元素。有时候,XPath表达式可能会变得非常冗长和复杂,这不仅难以阅读和维护,而且也可能影响性能。因此,学会如何简化XPath表达式是非常重要的。本文将介绍几种简化XPath表达式的方法ÿ…...

【文件下载】接口传递文件成功和失败时,前端的处理方式
问题 使用bold类型从后端接口获取文件流,获取成功的时候通过a标签下载;失败的时候,后端返回的是json,这个时候就无法向用户展示后端返回的错误提示信息。 思路 根据返回类型是否为 application/json 区分是否返回成功ÿ…...

html+css网页设计马林旅行社移动端4个页面
htmlcss网页设计马林旅行社移动端4个页面 网页作品代码简单,可使用任意HTML辑软件(如:Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作)。 获取源码 1&#…...

视频 的 音频通道提取 以及 视频转URL 的在线工具!
视频 的 音频通道提取 以及 视频转URL 的在线工具! 工具地址: https://www.lingyuzhao.top/toolsPage/VideoTo.html 它提供了便捷的方法来处理视频文件,具体来说是帮助用户从视频中提取音频轨道,并将视频转换为可以通过网络访问的URL链接。无…...

容易被遗忘的测试用例
网络服务器启动了吗?应用程序服务器启动了吗?数据库上线了吗?测试数据是否预先加载到数据库中?每当我们准备开始测试应用程序时,一切都应该已经准备妥当。 然而,当测试开始后,我们可能会漏掉一些…...

uni-app写的微信小程序如何实现账号密码登录后获取token,并且每天的第一次登录后都会直接获取参数而不是耀重新登录(2)
接uni-app写的微信小程序如何实现账号密码登录后获取token,并且每天的第一次登录后都会直接获取参数而不是耀重新登录(1), 在main.js中 import App from ./App// #ifndef VUE3 import Vue from vue import ./uni.promisify.adap…...

统计中间件稳定性指标
目前订单业务域涉及中间件:MySQL、Redis、TiDB、MQ、ES。(遗漏项请补充) 一、RDS 资源使用率 实例ID实例名称规格maxCPUavgCPUmaxDISKmaxIOPSavgIOPS活跃会话maxTPSavgTPSmaxQPSavgQPS实例风险 慢查询 慢查询会消耗大量的系统资源&#x…...

移动端使用REM插件postcss之postcss-px2rem
目录 一、概念 二、核心特性 三、功能 四、插件模块 注意事项: 五、使用 安装: 配置 一、概念 工具类型:PostCSS是一个基于JavaScript的工具,用于转换CSS的工作流。核心理念:PostCSS的核心理念是“转换而非替…...

FPGA Xilinx维特比译码器实现卷积码译码
FPGA Xilinx维特比译码器实现卷积码译码 文章目录 FPGA Xilinx维特比译码器实现卷积码译码1 Xilinx维特比译码器实现2 完整代码3 仿真结果 MATLAB (n,k,m)卷积码原理及仿真代码(你值得拥有)_matlab仿真后代码-CSDN博客 MATLAB 仿真…...

hive 行转列
行转列的常规做法是,group bysum(if())【或count(if())】 建表: CREATE TABLE table2 (year INT,month INT,amount DOUBLE );INSERT INTO table2 (year, month, amount) VALUES(1991, 2, 1.2),(1991, 3, 1.3),(1991, 4, 1.4),(1992, 1, 2.1),(1992, 2, 2.2),(1992…...

Vue中使用ECharts图表中的阈值标记(附源码)
在数据处理和可视化领域,我们经常需要对一系列数据点进行分析。本文将介绍如何在给定的数据点中找到对应于特定Y值的X值,并设置标线起始点标记在ECharts图表中,效果图如下: 实现步骤 1、数据准备 let seriesData [// 提供日期…...

【特征融合】融合空间域和频率域提升边缘检测能力
基于深度学习的边缘检测方法已显示出巨大的优势,并获得了可喜的性能。然而,目前大多数方法只能从空间(RGB)域提取特征进行边缘检测,可挖掘的信息有限。因此,这些方法无法很好地应用于物体与背景颜色相似的场景。为了应对这一挑战,提出了一种融合空间域和频率域特征的新型…...

深入理解AVL树:结构、旋转及C++实现
1. AVL树的概念 什么是AVL树? AVL树是一种自平衡的二叉搜索树,其发明者是Adelson-Velsky和Landis,因此得名“AVL”。AVL树是首个自平衡二叉搜索树,通过对树的平衡因子进行控制,确保任何节点的左右子树高度差最多为1&…...

AUTOSAR AP 汽车API知识点总结(Automotive API )R24-11
汽车API知识点总结 一、背景与目标 背景:智能互联汽车正逐步依赖远程诊断、软件更新等功能以确保行驶安全,并且用户已习惯于通过智能设备中的应用程序控制连接设备。虽然AUTOSAR标准支持车辆软件的可更新性,但尚未提供将AUTOSAR应用产生的数据和功能安全可靠地暴露给非AUTO…...

【HarmonyOS开发】超详细的ArkTS入门
安装DevEco Studio和新建项目就不多说了,可以移步官网 就可以把他们拆成这几个部分了,如果看不懂可以暂时忽略下面冒号后面的内容 装饰器:用于装饰类、结构、方法以及变量,并赋予其特殊的含义。如上述示例中Entry、Component和St…...

Springboot(五十一)SpringBoot3整合Sentinel-nacos持久化策略
上文中我记录了在Springboot项目中链接sentinel-dashboard使用限流规则的全过程。 但是呢,有一个小小的问题,我重启了一下我本地的sentinel-dashboard服务,然后,我之前创建的所有的流控规则都没了…… 这……好像有点不合理啊,咱就不能找地儿存储一下?你这一重启就没了,…...

[go-redis]客户端的创建与配置说明
创建redis client 使用go-redis库进行创建redis客户端比较简单,只需要调用redis.NewClient接口创建一个客户端 redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379",Password: "",DB: 0, })NewClient接口只接收一个参数red…...

Qt入门7——Qt事件
目录 1. Qt事件介绍: 2. 事件的处理 示例1:鼠标进入(enterEvent)与离开事件(leaveEvent) 示例2:鼠标点击事件(mousePressEvent) 示例3:鼠标移动事件(mouseMoveEvent) 3. 按键事件 4. 定时器 5. 窗口事件 1. Qt事件介绍&a…...

CTF之密码学(仓颉编码)
一、仓颉码(用于建立中文索引) 定义与目标: 仓颉码是为了建立中文的索引观念而设计的一种编码方式。其主要目标是方便对中文资料或程式进行索引功能的处理。 工作原理: 仓颉码的索引以ASCII的字符码为基准,但在内部会转…...

面向人工智能安全的多维应对策略
• 制定并实施人工智能伦理框架 国家和行业层面需建立AI伦理原则,将其融入研发与应用中,强化科研人员的伦理培训,推动全球AI伦理框架的制定。 • 加强可信数字内容体系建设 构建可信的互联网内容体系以应对深度伪造带来的安全威胁ÿ…...

考研英语翻译与大小作文
名词动化词 1 持有 harbor2 2 反映 mirror 3 缩短 bridge 4 使用 harness 5 掩饰 mask/veil 6 修改 tailor 7 汇集 pool 8 控制 curb 9 想象 picture 10 激发 trigger 拉丁…...

视频监控汇聚平台Liveweb视频安防监控实时视频监控系统操作方案
Liveweb国标GB28181视频平台是一种基于国标GB/T28181协议的安防视频流媒体能力平台。它支持多种视频功能,包括实时监控直播、录像、检索与回看、语音对讲、云存储、告警以及平台级联等功能。该平台部署简单、可扩展性强,支持全终端、全平台分发接入的视频…...

算法第一弹-----双指针
目录 1.移动零 2.复写零 3.快乐数 4.盛水最多的容器 5.有效三角形的个数 6.查找总价值为目标值的两个商品 7.三数之和 8.四数之和 双指针通常是指在解决问题时,同时使用两个指针(变量,常用来指向数组、链表等数据结构中的元素位置&am…...

linux环境GitLab服务部署安装及使用
一、GitLab介绍 GitLab是利用Ruby onRails一个开源的版本管理系统,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目。 二、GitLab安装 1、先安装相关依赖 yum -y install policycoreutils openssh-server openssh-clients postf…...

MotorCAD:定子绕组中的趋肤效应和邻近效应损耗
MotorCAD 有助于减少定子绕组中的集肤效应和邻近效应损失,优化电动机性能。 了解集肤和邻近效应损失 集肤效应:交流电场在导体中感应出电流回路,增加了中心的磁通链路,导致该位置的电抗更高,结果是电流在表面附近流动…...

R语言机器学习论文(二):数据准备
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据一、数据描述二、数据预处理(一)修改元素名称(二)剔除无关变量(三)缺失值检查(四)重复值检查(五)异常值检查三、描述性统计(一)连续变量数据情…...

FFmpeg:强大的音视频处理工具指南
FFmpeg:强大的音视频处理工具指南 1. FFmpeg简介2. 核心特性2.1 基础功能2.2 支持的格式和编解码器 3. 主要组件3.1 命令行工具3.2 开发库 4. 最新发展5. 安装指南5.1 Windows系统安装5.1.1 直接下载可执行文件5.1.2 使用包管理器安装 5.2 Linux系统安装5.2.1 Ubunt…...

NiFi-从部署到开发(图文详解)
NiFi简介 Apache NiFi 是一款强大的开源数据集成工具,旨在简化数据流的管理、传输和自动化。它提供了直观的用户界面和可视化工具,使用户能够轻松设计、控制和监控复杂的数据流程,NiFi 具备强大的扩展性和可靠性,可用于处理海量数…...

Scala的条件匹配
条件匹配 在 Scala 中,条件匹配主要通过match表达式来实现,它类似于其他语言中的switch语句,但功能更强。 基本语法:match表达式通常与case关键字一起使用。语法格式如下: 输入一段数字,判断属于那个范围…...