Magenta魔改记-2:数据格式与数据集

本文探讨了MIDI和MusicXML两种音乐数据格式,MIDI主要用于音乐播放,格式复杂,而MusicXML以XML为基础,提供清晰的记谱排版,更适合符号化音乐分析。尽管MIDI文件广泛应用,但由于格式不统一,数据处理困难。MusicXML虽优,但原生数据集较少。对于计算机音乐研究,建议使用MusicXML格式。

Magenta魔改记-2:数据格式与数据集

数据格式:MusicXML与MIDI

上一节我们主要提到了两种数据格式:MIDI(.mid/.midi)和MusicXML(.xml/.mxl)。其实他们二者,包括提到的ABC notation,都是在计算机中用于记谱的文件格式。
在这其中,ABC notation是以文本形式储存的,更接近于简谱。并且,ABC notation也应用的不广泛,更不用说和打谱软件对接了,因此在此就不详细展开了,感兴趣的可以看https://en.wikipedia.org/wiki/ABC_notation
而对于MIDI与MusicXML二者,他们表达的内容很相似,但差别在文件储存的格式上。

MIDI

MIDI,全称为Musical Instrument Digital Interface。而现如今对于MIDI这个名称的含义有三重意思:

  1. 连接音乐设备的物理接口(Musical Instrument Digital Interface)
  2. 存储和回放音乐的文件格式(Standard MIDI File)
  3. 通用MIDI(General MIDI)

对于MIDI的历史,最早可以追溯到八世纪水力驱动的自动乐器,到后来的八音盒、自动钢琴等。
而我们重点关注的是第二个含义,标准MIDI文件(SMF)。
关于标准MIDI文件的格式,https://www.csie.ntu.edu.tw/~r92092/ref/midi/ 有着很详尽的介绍。
MIDI文件是一种二进制文件,其中绝大部分由一个个事件(Events)组成,每个事件都有其相对应的时间戳。这其中最普遍的时间就是音符(Note)。音符又可分为按下(Note on)和抬起(Note off)。这二者的参数都是(通道,音高,力度),其中通道指的是?,而音高就是MIDI中以八位二进制数相对应的音高(中央C对应60,各音高按十二平均律依次加减)。
其他的常见事件包括time_signature(节拍标记,例如4/4拍)、key_signature(调式标记,例如B小调)、以及control_changes(控制器输入变化,如踩踏板)。
因此,我们在上一节中,可以看到Magenta利用pretty_midi库将MIDI文件转化成了一个一个事件列表,其中音符事件又合并成了Note(start,end,key,instrument,programe),其中program又指的是这个音符应当播放的音色。
然而,我们可以发现,在MIDI文件中,音符的start和end的绝对时间非常不整,通常都是很多位小数。这是由于:

  1. 在相对节拍到绝对时间戳的转换时,很容易会有除不尽的情况。因此start的时间戳很容易就会是很多位的小数。
  2. 在真实演奏中,一个音和下一个音很少是完全连接的,人们会或故意或无意的对两个音进行间隔,例如在钢琴中弹奏一个音之后若要再弹奏下一个距离远的音,需要切换手的位置,因此两个音不可避免的会有间隔。MIDI文件是可以直接根据音符的start和end进行播放的,因此很多MIDI文件在导出时,为了让每个音符的结尾听起来更自然,都不
server: port: 8802 # tomcat: # uriEncoding: "UTF-8" # remoteip: # protocol-header-https-value: "https" # remote-ip-header: "RemoteIpValve" # protocol-header: "X-Forwarded-Proto" servlet: context-path: /gateway cors: allowedOrigin: "*" management: endpoints: web: exposure: include: "*" spring: data: redis: client-type: lettuce # 使用响应式客户端 config: import: - "nacos:uap-gateway-test.properties?group=latest&server-addr=uap.qctc.com:8800" - "nacos:common-config.properties?group=latest&server-addr=uap.qctc.com:8800" application: name: uap-gateway main: web-application-type: reactive allow-bean-definition-overriding: true profiles: active: test # group: # latest: [ test ] # 使用数组形式定义包含的profile # 可添加其他组: # production: [prod, metrics] resources: add-mappings: true cloud: config: profile: dev discovery: enabled: true service-id: zhny-config bus: enabled: false trace: enabled: false nacos: # 增加全局日志禁用参数(关键修复) bootstrap: log: enabled: false # 关闭Nacos启动时的日志系统初始化 logging: config: false # 禁用Nacos内部日志配置 naming: false remote: false default: config: enabled: false discovery: server-addr: uap.qctc.com:8801 #uap.qctc.com:8900 11.14.30.16:8848 group: latest config: server-addr: uap.qctc.com:8801 file-extension: properties namespace: public group: latest name: uap-gateway # Data ID prefix: uap-gateway # shared-configs: # - data-id: common-config.properties # group: latest # refresh: true import-check: enabled: false # 禁用导入检查(可选) gateway: # 全局连接池超时配置 httpclient: retry: false # 全局关闭重试 # 允许特殊字符 relaxed-cookies: true pool: max-connections: 2000 # 最大总连接数 [2,5](@ref) max-idle-time: 50000ms # 连接空闲超时 connect-timeout: 50000 # 连接超时(毫秒)[2](@ref) response-timeout: 50000 # 响应超时(毫秒)[2](@ref) protool: h2c keepalive: true # 全局跨域配置(按需启用) globalcors: add-to-simple-url-handler-mapping: true cors-configurations: '[/**]': allowed-origins: "*" allow-credentials: false # 保持凭证携带 allowed-methods: "GET,POST" allowedMethods: "GET,POST" allowed-headers: "*" max-age: 3600 # 预检请求缓存时间 # 全局默认过滤器:移除 /api 前缀 [1,4](@ref) default-filters: - RewritePath=/api/(?<segment>.*), /$\{segment} discovery: locator: enabled: true # 开启从注册中心动态创建路由的功能,利用微服务名进行路由 routes: - id: gateway_self_api uri: no://op # 特殊标记,表示不转发 predicates: - Path=/gateway/api/isLicenseOverdue filters: - SetPath=/ # 内置过滤器(仅作占位符) # - id: gateway_prefix_route # uri: lb://uap-base # predicates: # - Path=/gateway/api/uap/** # filters: # - StripPrefix=2 # 移除 /gateway/api,保留 /uap/... # 1. uap-base 服务 - id: base uri: lb://uap-base predicates: - Path=/gateway/api/uap/** filters: - StripPrefix=2 - id: customer uri: lb://uap-base predicates: - Path=/gateway/api/customer/** filters: - StripPrefix=2 # 2. zhny-publish-test 服务 - id: market uri: lb://zhny-publish-test predicates: - Path=/gateway/api/market/** filters: - StripPrefix=2 - id: cmsservice uri: lb://zhny-publish-test predicates: - Path=/gateway/api/cmsservice/** filters: - StripPrefix=2 - id: sns uri: lb://zhny-publish-test predicates: - Path=/gateway/api/sns/** filters: - StripPrefix=2 - id: trade uri: lb://zhny-publish-test predicates: - Path=/gateway/api/trade/** filters: - StripPrefix=2 - id: settle uri: lb://zhny-publish-test predicates: - Path=/gateway/api/settle/** filters: - StripPrefix=2 - id: vpp uri: lb://zhny-publish-test predicates: - Path=/gateway/api/vpp/** filters: - StripPrefix=2 - id: nbxy uri: lb://zhny-publish-test predicates: - Path=/gateway/api/nbxy/** filters: - StripPrefix=2 - id: pla uri: lb://zhny-publish-test predicates: - Path=/gateway/api/pla/** filters: - StripPrefix=2 # 3. 其他独立服务 - id: analysis # zhny-esf uri: lb://zhny-publish-test predicates: - Path=/gateway/api/analysis/** filters: - StripPrefix=2 - id: dta # zhny-dta uri: lb://zhny-dta predicates: - Path=/gateway/api/dta/** filters: - StripPrefix=2 - id: crd # zhny-crd uri: lb://zhny-crd predicates: - Path=/gateway/api/crd/** filters: - StripPrefix=2 - id: hnsd # zhny-hnsd uri: lb://zhny-hnsd predicates: - Path=/gateway/api/hnsd/** filters: - StripPrefix=2 - id: grc # zhny-grc uri: lb://zhny-grc predicates: - Path=/gateway/api/grc/** filters: - StripPrefix=2 - id: ecarbon # zhny-ecarbon uri: lb://zhny-ecarbon predicates: - Path=/gateway/api/ecarbon/** filters: - StripPrefix=2 - id: rpt # zhny-rpt uri: lb://zhny-rpt predicates: - Path=/gateway/api/rpt/** filters: - StripPrefix=2 - id: gdt # zhny-gdt uri: lb://zhny-gdt predicates: - Path=/gateway/api/gdt/** filters: - StripPrefix=2 - id: ems # zhny-ems uri: lb://zhny-ems predicates: - Path=/gateway/api/ems/** filters: - StripPrefix=2 - id: ecm # zhny-ecm uri: lb://zhny-ecm predicates: - Path=/gateway/api/ecm/** filters: - StripPrefix=2 - id: hbvpp # zhny-hbvpp uri: lb://zhny-hbvpp predicates: - Path=/gateway/api/hbvpp/** filters: - StripPrefix=2 - id: gcd # zhny-gcd uri: lb://zhny-publish-test predicates: - Path=/gateway/api/gcd/** filters: - StripPrefix=2 - id: hbdkclient # zhny-hbdkclient uri: lb://zhny-hbdkclient predicates: - Path=/gateway/api/hbdkclient/** filters: - StripPrefix=2 - id: fhjhjy # zhny-fhjhjy uri: lb://zhny-fhjhjy predicates: - Path=/gateway/api/fhjhjy/** filters: - StripPrefix=2 - id: sdpxvpp # sd-sdpxvpp uri: lb://sd-sdpxvpp predicates: - Path=/gateway/api/sdpxvpp/** filters: - StripPrefix=2 - id: dts # zhny-dts uri: lb://zhny-dts predicates: - Path=/gateway/api/dts/** filters: - StripPrefix=2 - id: rec # zhny-rec uri: lb://zhny-rec predicates: - Path=/gateway/api/rec/** filters: - StripPrefix=2 - id: ptc # zhny-ptc uri: lb://zhny-ptc predicates: - Path=/gateway/api/ptc/** filters: - StripPrefix=2 - id: lmp # zhny-lmp uri: lb://zhny-publish-test predicates: - Path=/gateway/api/lmp/** filters: - StripPrefix=2 eureka: client: fetch-registry: true # 必须显式启用 register-with-eureka: true # 必须显式启用 healthcheck: enabled: false serviceUrl: defaultZone: http://qctczhny:QCTCzhny6608!@uap.qctc.com:8800/eureka instance: metadata-map: management: context-path: ${server.servlet.context-path}/actuator prefer-ip-address: true instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${spring.application.instance_id:${server.port}} lease-renewal-interval-in-seconds: 2 #续约间隔 lease-expiration-duration-in-seconds: 4 #租约寿命 #status-page-url: http://${spring.cloud.client.ip-address}:${server.port}/api/doc.html health-check-url-path: ${server.servlet.context-path}/actuator/health #swagger: # enabled: true # name: QCTC统一开发平台 #api名称 # description: QCTC统一开发平台接口文档说明 #api描述 # termsOfServiceUrl: http://uap.qctc.com:8802${server.servlet.context-path} # developer: QCTC #api开发 # version: 3.0.0 #api开发 # basic: # enable: true # username: qctc # password: qctcadmin6608 feign: # 启用 Resilience4j circuitbreaker: enabled: true group: enabled: true httpclient: enabled: false okhttp: enabled: true compression: request: enabled: true mime-types: text/html,text/xml,text/plain,application/xml,application/json response: enabled: true # 定义客户端超时 client: config: default: # 全局默认配置 connectTimeout: 5000 # 连接超时(ms) readTimeout: 10000 # 读取超时(ms) # 绑定熔断器和超时器 resilience4jCircuitBreakerName: default resilience4jTimelimiterName: default ####超时配置#### resilience4j: circuitbreaker: instances: default: # 默认熔断器配置(作用于所有 Feign 调用) failureRateThreshold: 50 # 失败率阈值% minimumNumberOfCalls: 10 # 最小调用次数 slidingWindowType: COUNT_BASED slidingWindowSize: 10 # 统计窗口大小 waitDurationInOpenState: 10s # 熔断持续时间 timelimiter: instances: default: timeoutDuration: 5s # 单次调用超时时间 # 日志 logging: file: name: /usr/qctcapps/gateway/data/${spring.application.name}/debug.log #/usr/qctcapps/publish_test pattern: file: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wEx" level: root: info com.qctc.uap: info # com.alibaba.cloud.nacos.client.NacosPropertySourceBuilder: DEBUG # org.springframework.core.env.PropertySourcesPropertyResolver: DEBUG # org.springframework.cloud.gateway.filter: TRACE # reactor.netty.http.client: DEBUG 配置有问题吗
最新发布
09-02
<think> 我们面临的核心问题是:通过Nginx代理的POST登录请求返回403 Forbidden,而直接访问后端服务则成功(200 OK)。结合提供的Nginx配置、请求头和Spring Cloud Gateway日志,我们需要从Nginx配置和Spring Cloud Gateway配置两方面进行分析。 ### 一、Nginx配置分析(关键问题) 在用户提供的Nginx配置中,`/gateway`相关的配置如下: ```nginx location /gateway { client_max_body_size 20m; client_body_buffer_size 128k; proxy_pass http://192.168.1.95:10002; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-Port $remote_port; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; #必须配这个转发 } ``` #### 问题1:错误的`X-Forwarded-Proto`设置 - 当前设置:`proxy_set_header X-Forwarded-Proto https;` - 问题:实际前端访问使用的是HTTP(非HTTPS),但这里强制设置为`https`。 - 后果:后端服务(Spring Cloud Gateway)收到`X-Forwarded-Proto: https`,会认为请求是HTTPS,导致后续处理(如重定向、CORS检查)产生偏差。 #### 问题2:缺少`Origin`头处理 - 从日志中看到,Spring Cloud Gateway进行了CORS检查: ```log o.s.w.c.reactive.DefaultCorsProcessor : Reject: origin is malformed ``` - 原因:Nginx默认不会转发`Origin`头(除非显式设置),而后端需要此头进行CORS验证。 #### 问题3:Cookie解析失败 - 日志显示: ```log i.n.h.c.http.cookie.ServerCookieDecoder : Skipping cookie because name 'retype_30000/' contains invalid char '/' ``` - 根本原因:Cookie名称中包含非法字符`/`(如`retype_30000/=`),导致整个Cookie被丢弃。 ### 二、Spring Cloud Gateway日志分析 关键日志片段: ```log 2025-09-01T00:23:07.264+08:00 TRACE ... o.s.c.g.h.p.PathRoutePredicateFactory : Pattern "/gateway/api/uap/**" matches against value "/gateway/api/uap/login/v1/login" 2025-09-01T00:23:07.264+08:00 DEBUG ... o.s.c.g.h.RoutePredicateHandlerMapping : Route matched: base ... [其他路由匹配日志] ... 2025-09-01T00:23:07.265+08:00 DEBUG ... o.s.w.c.reactive.DefaultCorsProcessor : Reject: origin is malformed 2025-09-01T00:23:07.265+08:00 DEBUG ... o.s.w.s.adapter.HttpWebHandlerAdapter : [d2fa72ca-9] Completed 403 FORBIDDEN ``` #### 问题1:CORS校验失败 - 日志明确记录:`Reject: origin is malformed` - 可能的原因: - 请求中没有`Origin`头(Nginx未转发) - `Origin`头格式不正确(如包含端口但未在CORS配置中允许) #### 问题2:路由匹配成功但被CORS拦截 - 路由正确匹配到`base`(指向`uap-base`服务),说明路由配置无问题。 - 403发生在CORS检查阶段,证明问题在跨域配置。 ### 三、解决方案 #### 步骤1:修正Nginx配置 ```nginx location /gateway { client_max_body_size 20m; client_body_buffer_size 128k; proxy_pass http://192.168.1.95:10002; # 关键修正1:动态设置X-Forwarded-Proto(根据实际协议) proxy_set_header X-Forwarded-Proto $scheme; # 关键修正2:显式传递Origin头(若存在) proxy_set_header Origin $http_origin; # 保留原有其他头设置 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-Port $remote_port; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 新增:处理Cookie非法字符问题(避免Nginx丢弃Cookie) # 方案:重写Cookie,移除非法字符(示例移除名称中的斜杠) set $clean_cookie $http_cookie; if ($http_cookie ~* "(.*)(retype_30000/|abc666_30000/|pk_30000/)(.*)") { set $clean_cookie $1$3; } proxy_set_header Cookie $clean_cookie; } ``` #### 步骤2:调整Spring Cloud Gateway的CORS配置 在网关配置(如`application.yml`)中添加全局CORS配置: ```yaml spring: cloud: gateway: globalcors: cors-configurations: '[/**]': allowedOrigins: - "http://sz3_jdk17.qctc.com:30000" - "http://sz4_jdk17.qctc.com:30000" # 按需添加其他前端地址 allowedMethods: - GET - POST - PUT - DELETE - OPTIONS allowCredentials: true allowedHeaders: "*" ``` #### 步骤3:验证修复 1. **检查请求头**:确保Nginx转发后,后端收到的请求包含: - `X-Forwarded-Proto: http`(前端实际协议一致) - `Origin: http://sz3_jdk17.qctc.com:30000` - 有效的Cookie(无非法字符) 2. **测试命令**: ```bash # 模拟前端请求(注意指定Origin和Cookie) curl -v -X POST 'http://sz3_jdk17.qctc.com:30000/gateway/api/uap/login/v1/login' \ -H "Origin: http://sz3_jdk17.qctc.com:30000" \ -H "Cookie: retype_30000=SM2; abc666_30000=some_value; pk_30000=some_value" \ -H "Content-Type: application/json" \ -d '{"username":"test", "password":"test"}' ``` ### 四、根本原因总结 | 层级 | 问题 | 导致后果 | |---------------------|-----------------------------------------------|------------------------------| | **Nginx** | 硬编码`X-Forwarded-Proto: https` | 后端协议判断错误 | | | 未转发`Origin`头 | CORS检查失败 | | | Cookie名称含非法字符`/` | 会话丢失 | | **Spring Gateway** | 未显式配置CORS允许`http://sz3_jdk17.qctc.com:30000` | 拒绝跨域请求 | §§相关问题§§ 1. Nginx中如何处理Cookie包含特殊字符的问题? 2. Spring Cloud Gateway如何动态配置CORS允许的域名? 3. 如何验证`X-Forwarded-Proto`设置是否正确影响后端服务? 4. 除了CORS,还有哪些原因会导致POST请求返回403? </think> ### 分析NginxSpring Cloud Gateway配置解决403 Forbidden问题 #### 一、Nginx配置核心问题 1. **Cookie非法字符问题** ```log Skipping cookie because name 'retype_30000/' contains invalid char '/' ``` - 问题:Cookie名称包含非法字符`/`导致Nginx丢弃所有Cookie - 影响:会话验证失败触发403 - 修复方案: ```nginx # 在location /gateway 中添加Cookie重写 set $clean_cookie $http_cookie; if ($http_cookie ~* "(.*)(retype_30000/|abc666_30000/|pk_30000/)(.*)") { set $clean_cookie $1$3; } proxy_set_header Cookie $clean_cookie; ``` 2. **CORS配置缺失** - 问题:Nginx未处理`Origin`头且未返回CORS响应头 - 证据:后端日志`Reject: origin is malformed` - 修复方案: ```nginx # 在location /gateway 中添加 add_header 'Access-Control-Allow-Origin' "$http_origin" always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' '*'; ``` 3. **代理协议头错误** ```nginx proxy_set_header X-Forwarded-Proto https; # 强制HTTPS ``` - 问题:前端实际使用HTTP(`http://sz3_jdk17.qctc.com:30000`),但强制设为HTTPS - 修正方案: ```nginx proxy_set_header X-Forwarded-Proto $scheme; # 动态匹配协议 ``` #### 二、Spring Cloud Gateway问题 1. **CORS校验失败** ```log o.s.w.c.reactive.DefaultCorsProcessor : Reject: origin is malformed ``` - 根本原因:网关未收到有效的`Origin`头(被Nginx过滤) - 解决方案:显式配置允许源 ```yaml # application.yml spring: cloud: gateway: globalcors: cors-configurations: '[/**]': allowed-origins: - "http://sz3_jdk17.qctc.com:30000" allow-credentials: true ``` 2. **安全头冲突** - 现象:Nginx返回`X-Frame-Options: DENY`网关的`SAMEORIGIN`冲突 - 解决方案:统一策略(在Nginx中覆盖) ```nginx proxy_hide_header X-Frame-Options; add_header X-Frame-Options "SAMEORIGIN"; ``` #### 三、完整修复流程 1. **修改Nginx配置** (/etc/nginx/conf.d/sz3.conf) ```nginx location /gateway { client_max_body_size 20m; client_body_buffer_size 128k; proxy_pass http://192.168.1.95:10002; # 修复Cookie set $clean_cookie $http_cookie; if ($http_cookie ~* "(.*)(retype_30000/|abc666_30000/|pk_30000/)(.*)") { set $clean_cookie $1$3; } proxy_set_header Cookie $clean_cookie; # 修复CORS add_header 'Access-Control-Allow-Origin' "$http_origin" always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; # 修复协议头 proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host:$server_port; # 统一安全头 proxy_hide_header X-Frame-Options; add_header X-Frame-Options "SAMEORIGIN"; } ``` 2. **重启Nginx服务** ```bash sudo nginx -t && sudo systemctl restart nginx ``` 3. **验证修复** ```bash curl -X POST 'http://sz3_jdk17.qctc.com:30000/gateway/api/uap/login/v1/login' \ -H "Origin: http://sz3_jdk17.qctc.com:30000" \ -H "Cookie: retype_30000=SM2" \ -H "Content-Type: application/json" \ -d '{"username":"test"}' ``` #### 四、技术原理图 ```mermaid graph LR A[浏览器] -->|1. POST /login| B(Nginx) B -->|2. 修复Cookie/CORS| C[Spring Gateway] C -->|3. 认证请求| D[微服务] D -->|4. 200响应| C C -->|5. 添加CORS头| B B -->|6. 返回响应| A ``` #### 五、根本原因总结 | 层级 | 问题 | 导致后果 | |---------------------|-------------------------------|--------------------------| | **Nginx** | Cookie含非法字符`/` | 会话丢失 → 403 | | | 未转发/处理`Origin`头 | CORS校验失败 → 403 | | | 强制`X-Forwarded-Proto: https`| 协议不匹配 → 安全拒绝 | | **Spring Gateway** | 未配置显式CORS允许源 | 拒绝跨域请求 → 403 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值