【Nginx34】Nginx学习:安全链接、范围分片以及请求分流模块

Nginx学习:安全链接、范围分片以及请求分流模块

又迎来新的模块了,今天的内容不多,但我们都进行了详细的测试,所以可能看起来会多一点哦。这三个模块之前也从来都没用过,但是通过学习之后发现,貌似还都挺有用。当然,还是要根据具体业务情况来看,如果你的业务中有用到,那么就可以尝试一下哦。

安全链接是实现请求 URL 的验证模块,通过签名密钥来判断请求是否可以返回相应的数据。范围分片一般用于分段下载,主要用于代理时请求后端的 Range 头的设置。最后的请求分流不太好说清楚,咱们到文章中详细再说明吧。

今天的内容大部分可以在 http、server、location 下配置,仅有两个只能在 http 或 location 下配置,我会单独说。

安全链接

安全链接模块 ngx_http_secure_link_module(0.7.18),可以用于检查请求链接的真实性,保护资源免受未经授权的访问,并限制链接寿命。

请求链接的真实性通过将请求中传递的校验和值与为请求计算的值进行比较来验证。这个其实就像我们做 App 接口时,一般都会加个 sign 签名一样,客户端使用和服务端相同的方式进行签名,用于验证客户端发来的请求是否有效。另外,这个模块还可以根据链接的生命周期来进行验证,如果生命周期有限且时间已过,则认为该链接已过期。这些检查的状态在 $secure_link 变量中可用。

该模块提供了两种可选的操作模式。第一种模式由secure_link_secret 指令启用,用于检查请求链接的真实性以及保护资源免受未经授权的访问。第二种模式 (0.8.50) 由secure_link 和secure_link_md5 指令启用,也用于限制链接的生命周期。这两种形式我们后面都会进行测试。

它不包含在 Nginx 核心源码中,需要通过 --with-http_secure_link_module 编译安装。我们还是先来看看这个模块所包含的配置项,然后再进行综合的测试。

secure_link

定义一个带有变量的字符串,将从中提取链接的校验和值(md5+base64)和生命周期。

secure_link expression;

表达式中使用的变量通常与请求相关联,一般可以设置为 $arg_md5 ,这个变量名是可以自己起的,目的就是获取到这个加密值。将从字符串中提取的校验和值与 secure_link_md5 指令定义的表达式的 MD5 哈希值进行比较。如果校验和不同,则 $secure_link 变量设置为空字符串。如果校验和相同,则检查链路寿命。

如果链接的生命周期有限且时间已过,则 $secure_link 变量设置为“0”。否则,设置为“1”。请求中传递的 MD5 哈希值以 base64url 编码。如果链接的生命周期有限,则过期时间设置为自 Epoch(1970 年 1 月 1 日星期四 00:00:00 GMT)以来的秒数。

该值在 MD5 哈希后的表达式中指定,并以逗号分隔,比如 $arg_sign$arg_expires ,后面这个 expires 就是可以通过 GET 获取的过期时间值。请求中传递的过期时间可通过 $secure_link_expires 变量在secure_link_md5 指令中使用,不使用也行,后面测试时我们会看到。如果未指定过期时间,则链接具有无限的生命周期。

secure_link_md5

定义一个表达式,将计算 MD5 哈希值并将其与请求中传递的值进行比较。

secure_link_md5 expression;

表达式应包含链接(资源)的安全部分和秘密成分。如果链接的生命周期有限,则表达式还应包含 $secure_link_expires 。为了防止未经授权的访问,表达式可能包含有关客户端的一些信息,例如其地址和浏览器版本。

比如我们可以指定为 secure_link_md5 '$uri zzyy'; ,那么上面 secure_link 第一个设置的值就是 base64_encode(md5('请求的链接地址 zzyy')) 这样的结果就可以和 secure_link_md5 的值匹配上。如果不匹配,$secure_link 会是空,如果使用了过期时间,并且时间确实过期了,那么就是 0 ,这时就可以使用 if 指令判断是否验证成功做出不同的操作。

看不懂是吧?没事,一会测试例子运行一下就明白了。

secure_link_secret

定义用于检查所请求链接的真实性的秘钥。

secure_link_secret word;

仅能在 location 下配置。请求链接的完整 URI 如下所示:

/prefix/hash/link

其中 hash 是 MD5 散列的十六进制表示,用于连接链接和秘钥,prefix 是不带斜杠的任意字符串。如果请求的链接通过了真实性检查,则 $secure_link 变量设置为从请求 URI 中提取的链接。否则,$secure_link 变量设置为空字符串。

这个又是啥玩意?注意,它是单独使用的,和上面那两个没关系。假如我们设置 secure_link_secret zyblog; 请求地址为 /p/17ceb6c14933609f0ab68e37fe633b1a/1.html ,那么中间加密的部分其实就是 md5('1.htmlzyblog') 。前面的 /p/ 是没啥用的,因为这个配置只能在 location 下配置,所以这个前缀就是 location 的 URI 部分。

使用上面的链接可以将 $secure_link 设置为 1.html ,然后我们就可以通过 rewrite 去请求真实的 1.html 了,这里可以加个判断,如果 $secure_link 为空,就返回异常页面,这样就实现了链接的验证。

嗯,说不明白,还是一会看测试效果吧。

变量

  • $secure_link 链接检查的状态。具体值取决于所选的操作模式

  • $secure_link_expires 请求中传递的链接的生命周期,仅用于 secure_link_md5 指令

安全链接测试(一)secure_link 与 secure_link_md5

好了,看完了配置指令,咱们就来看看怎么使用。首先看第一种方式,就是 secure_link 与 secure_link_md5 组合的方式。先添加以下的测试代码。

log_format securelink 'secure_link_expires=$secure_link_expires, secure_link=$secure_link';server{listen 8034;location /securelink1/ {access_log logs/34.securelink.log securelink;alias html/;secure_link $arg_md5,$arg_expires;secure_link_md5 "$secure_link_expires$uri$remote_addr zyblog secret";if ($secure_link = "") {return 200 nosecure;}if ($secure_link = "0") {return 200 timeexpire;}}}

上面的日志记录,是为了看两个变量的变化情况。然后我们指定 secure_link 的值,分别是从 GET 获取到的 md5 参数和 expires 参数。expires 可以给个时间戳,我们给的是明天的一个时间点。secure_link_md5 我们设置的内容是通过 "过期时间+请求链接URI+IP地址+空格+zyblog+空格+secret" 这一个字符串进行加密的。

然后就是使用两个 if 指令进行判断,如果 secure_link 为空,表示安全验证没通过,如果 $secure_link 是 0 ,表示过期了,分别通过 return 返回不同的内容。

然后咱们先测试一下啥参数都不带的。

➜  ~ curl 'http://192.168.56.88:8034/securelink1/'
nosecure

直接返回 nosecure 。再看下日志。

// 34.securelink.log
secure_link_expires=-, secure_link=-

两个变量都是空的。然后我们准备一下要加密的签名数据,根据 secure_link_md5 的设置,我们可以直接通过 Linux 的 openssl 工具进行加密,如果没有安装这个的话可以自己安装一下哦,或者使用 PHP 以及其它动态语言也是可以的,就是md5 之后再 base64 一下。

[root@localhost article.http.d]# echo -n '1663719873/securelink1/192.168.56.1 zyblog secret' | openssl md5 -binary | openssl base64 | tr +/ -_ | tr -d =
VEJ41JfqBbXXaGJRXWK3rw

1663719873 是我们一会要通过 expires 参数传过来的过期时间,现在用当前时间,后面我们才会测试过期的问题,在 secure_link 配置中逗号后面第二个参数我们放置的就是它,然后它就会到 $secure_link_expires 变量中。secure_link_md5 中第一个变量就是它,所以我们要拼接在最前面,然后是请求的地址,这里就是请求根目录,URI 就是 /securelink1/ ,然后就是客户端 IP 地址,我这里是 192.168.56.1,最后接上空格和固定的字符串,加密后的结果就是 VEJ41JfqBbXXaGJRXWK3rw 。然后发送请求时使用 GET 带上这两个参数吧。

curl 'http://192.168.56.88:8034/securelink1/?md5=VEJ41JfqBbXXaGJRXWK3rw&expires=1663719873'

是不是发现可以打开首页了?因为我们做了 alias ,所以就是直接打开 html 目录下的首页了。再看下日志。

// 34.securelink.log
secure_link_expires=1663719873, secure_link=1

两个值都取到了,secure_link 的值是 1 ,不符合 if 每个人的中的内容,不会直接 return 返回,正常向下执行。

secure_link_expires=1662769473, secure_link=1

接下来试试过期问题,先改造一下。

secure_link $arg_md5,1662769473;
secure_link_md5 "$uri$remote_addr zyblog secret";

这回我们让过期时间的设置不使用传递过来的参数了,而是一个固定值,这个值是比现在的时间稍微早一点的时间。然后 secure_link_md5 也改了下,不使用 secure_link_expires

➜  ~ curl 'http://192.168.56.88:8034/securelink1/?md5=EzLUxfpwyLdp7bDv0m0l0Q'
timeexpire

查看日志,secure_link 被设置成了 0 ,而 secure_link_expires 则是我们 secure_link 中设置的那个值。

// 34.securelink.log
secure_link_expires=1662769473, secure_link=0

然后我们再将过期时间设置为比现在晚一点的时候,比如比当前时间多个几分钟。

secure_link $arg_md5,1663644527;

现在访问又正常了,从这里可以看出,过期时间是基于当前系统的时间值的,如果小于当前系统时间,就是过期的,如果大于当前系统时间,就是正常的。而如果将 $secure_link_expires 加入到 secure_link_md5 中一起加密的话,则是保证这个请求必须在 1 秒内到达。假设有代理或者黑客大佬中间拦截了请求,就会导致时间过期,而如果时间参数对不上加密内容,则会导致验证不通过。这里和我们之前讲过的接口签名 sign 是一样的概念。

时间参数最重要的作用,就是让签名产生变化,如果没有这个动态值,那么签名就会一直是一样的,这种签名有跟没有不就没啥区别了。

不过就像做接口签名一样,客户端和服务端如果时间不一致,就可能导致签名失败。一般有两种解决方式,一是对发来的时间参数判断,比如1分钟或几分钟内的都有效,二是每次接口请求都返回服务器的时间,让客户端保存一份,并以这个时间戳为基准进行计时。通常来说,第一种方式是我们用动态语言时常用的方式,第二种则可以应用在 Nginx 这个配置中。

对于接口签名不太了解的同学,可以查阅下相关的资料哦。一般都是通过 URI+请求参数排序+时间戳 这种加密形式进行接口签名的。

当然,我们也可以不使用过期时间,secure_link 不加过期时间参数就可以了。

secure_link $arg_md5;
secure_link_md5 "$uri$remote_addr zyblog secret";

然后对参数进行加密。

[root@localhost article.http.d]# echo -n '/securelink1/192.168.56.1 zyblog secret' | openssl md5 -binary | openssl base64 | tr +/ -_ | tr -d =
EzLUxfpwyLdp7bDv0m0l0Q

直接访问,可以正确获得访问结果。

curl 'http://192.168.56.88:8034/securelink1/?md5=EzLUxfpwyLdp7bDv0m0l0Q'

日志的内容如下。

secure_link_expires=-, secure_link=1

安全链接测试(二)secure_link_secret

第二种,secure_link_secret 的使用方法,还是先来准备测试代码吧。

location /securelink2/ {access_log logs/34.securelink.log securelink;alias html/;secure_link_secret zyblog.com.cn;if ($secure_link = "") {return 200 nosecure;}rewrite ^ /$secure_link;
}
location / {root html;
}

这段代码中,我们指定签名的 Key 是 zyblog.com.cn 。如果匹配不成功,就返回 nosecure 的内容,如果成功了,$secure_link 会变成签名内容之后的 URI 地址。也就是上面配置解释中 link 的部分。接着就通过 rewrite 重写到 link 地址。

先来看看直接访问的效果。

curl 'http://192.168.56.88:8034/securelink2/aaa'
nosecure

不出意外的返回 nosecure ,因为我们的验证没有通过,$secure_link 的值是空的,先做一个加密密钥过来吧,根据规则,直接拼接 aaa 和 zyblog.com.cn ,然后 md5 就可以了,这里不需要再 base64 了。

[root@localhost article.http.d]# echo -n 'aaazyblog.com.cn' | openssl md5 -hex
(stdin)= e09475846aa906796ef997b684eced07

获得密钥之后,加到 location 和 aaa 中间。

curl 'http://192.168.56.88:8034/securelink2/e09475846aa906796ef997b684eced07/aaa'

是不是可以正常访问啦,看看日志内容。

// 34.securelink.log
secure_link_expires=-, secure_link=aaa

secure_link 确实变成了密码后面的 URI 内容了。对于指定的文件也需要加密。

[root@localhost article.http.d]# echo -n 'tf2/2.htmlzyblog.com.cn' | openssl md5 -hex
(stdin)= 2fef203746d3684862e8d2607bfebc86

现在需要访问的是 tf2 目录下的 2.html 文件。

curl 'http://192.168.56.88:8034/securelink2/2fef203746d3684862e8d2607bfebc86/tf2/2.html'

也是可以正常访问的。这里需要注意的是,它仅能对非根的的路径进行安全连接保护。比如下面这样就不行。

curl 'http://192.168.56.88:8034/securelink2/xxxx/'

即使你是 "zyblog.com.cn" 或 “/zyblog.com.cn” 这样加密都不行,但要想直接访问可以直接指定文件名。

[root@localhost article.http.d]# echo -n 'index.htmlzyblog.com.cn' | openssl md5 -hex
(stdin)= 2a19ca1a01c0121c7bb6b4ecb8d109dc

这样就可以访问根目录下的 index.html 了。

curl 'http://192.168.56.88:8034/securelink2/2a19ca1a01c0121c7bb6b4ecb8d109dc/index.html'

范围分片

这里的范围分片,其实就是范围请求的意思,也就是 HTTP 中的那个 Range 请求头和响应头的作用。不过这里的配置不是针对客户端的,而是针对代理服务器的。它的命名是 ngx_http_slice_module 模块(1.9.8),是一个过滤器,用于将请求拆分为子请求,每个子请求返回一定范围的响应。过滤器提供更有效的大响应缓存。

它只有一个配置指令,并且不是包含在 Nginx 核心源码中的,需要通过 --with-http_slice_module 编译。

slice

设置切片的大小。

slice size;

默认 0 表示禁用将响应拆分为切片。请注意,过低的值可能会导致内存使用过多并打开大量文件。

为了让子请求返回所需的范围,应将 $slice_range 变量作为 Range 请求标头字段传递给代理服务器。如果启用了缓存,则应将 $slice_range 添加到缓存键中,并应启用具有 206 状态代码的响应的缓存。

变量

  • $slice_range HTTP字节范围格式的当前切片范围,例如bytes=0-1048575。

范围分片测试

这个测试需要借助反向代理,因为它主要是针对代理的子请求的嘛。所以我们添加如下配置。

# http
proxy_cache_path slicecache levels=1:2 keys_zone=slicecache:10m;server{………………location ~ /slice(.*) {slice             100;proxy_cache       slicecache;proxy_cache_key   $uri$is_args$args$slice_range;proxy_set_header  Range $slice_range;proxy_cache_valid 200 206 10m;proxy_pass        http://127.0.0.1/$1?$args;}
}

代理相关的配置就不多说了,主要就是做了个代理缓存。然后添加了 slice 指令,设置为 100 个字符。然后需要设置代理请求头的 Range 头,值直接就放 $slice_range 就好了。另外就是有效缓存响应码要把 206 加上。这些配置都是我们之前在学习代理时讲过的。

然后准备一个 PHP 文件,没什么特别的内容,就是获取 Range 请求头的内容,然后返回响应时响应为 206 状态码,并且添加 Content-Range 响应头。最后循环随机输出数据。

// vim /usr/local/nginx/html/fastcgi1/slice/1.php
if (isset ( $_SERVER ['HTTP_RANGE'] )) {if (preg_match ( '/bytes=\h*(\d+)-(\d*)[\D.*]?/i', $_SERVER ['HTTP_RANGE'], $matches )) {$begin = intval ( $matches [1] );if (! empty ( $matches [2] )) {$end = intval ( $matches [2] );}}
}header ( 'HTTP/1.1 206 Partial Content' );header ( "Content-Range: bytes $begin-$end/10000" );
foreach(range(0, 99) as $v){echo rand(1, 9);
}

请求之后,我们去看 Proxy 缓存目录,会发现生成了很多缓存。这就是因为我们每次都只是请求 100 字节范围内的数据,所以每次请求的响应就只有 100 字节,总共会响应 1000 个字节,大概有 10 次子请求。这里只有 8 个目录,但是还有二级目录,总共生成的缓存文件应该是 10 个。

[root@localhost article.http.d]# ll /usr/local/nginx/slicecache/
total 0
drwx------ 3 www www 16 Sep 20 09:58 0
drwx------ 3 www www 16 Sep 20 09:58 1
drwx------ 4 www www 26 Sep 20 09:58 3
drwx------ 3 www www 16 Sep 20 09:58 4
drwx------ 3 www www 16 Sep 20 09:58 5
drwx------ 3 www www 16 Sep 20 09:58 a
drwx------ 4 www www 26 Sep 20 09:58 c
drwx------ 3 www www 16 Sep 20 09:58 f

随便查看一个目录下面的缓存文件,内容就是 100 个字符。

[root@localhost article.http.d]# cat /usr/local/nginx/slicecache/3/25/2c87b23befe050b716282f3280b5c253
��)c��������-)cR
KEY: /slice/fastcgi1/slice/1.phpbytes=800-899
HTTP/1.1 206 Partial Content
Server: nginx/1.23.0
Date: Tue, 20 Sep 2022 01:58:05 GMT
Content-Type: text/html; charset=UTF-8
Connection: close
X-Powered-By: PHP/7.2.24
Content-Range: bytes 800-899/10002687293144586783221846674348597775216172183988478888753581981981732616122451579567834463585161967919

这 100 个字符在最终整体返回的数据中肯定是存在的,是整体响应内容的连续一部分。

2a6fcf69926551f175422e1eed634c86.png

请求分流

最后我们再来看到的是请求分流的功能。它还是比较有意思的,能够根据一个变量内容,进行 Hash 分配到指定的内容,有点类似于之前学习过的 Redis 的分槽的效果。这个模块的全名是 ngx_http_split_clients_module 模块,用于创建适用于 A/B 测试的变量,也称为拆分测试。它直接包含在 Nginx 核心源码中,直接就可以使用,也只有一个配置指令。

split_clients

为 A/B 测试创建一个变量。

split_clients string $variable { ... }

只能在 http 模块下进行配置。使用 MurmurHash2 对原始字符串的值进行散列。和 Redis Cluster 中的 槽solt 类似,从 0 到 4294967295 的范围内,根据配置的结果,会让散列值落在一定的范围内。后面我们看例子再详细说明。

请求分流测试

上面的内容要是没看懂,我们就直接测试效果。

# http
split_clients "${arg_a}zyblog" $variant {50%               aaa.html;20%               a.txt;*                 index.html;
}server {# ………………location /splitclient/ {alias html/;index $variant;}
}

在 split_clients 配置中,我们定义了 $arg_a 拼接 zyblog 字符串做为 Hash 值,也就说,根据我们传递过来的 GET 参数 a 的不同,就会有不同的哈希结果。上面配置的意思是,50% 代表散列结果为 0-2147483647 范围内的结果,就设置 $variant 为 aaa.html ;20% 代表散列值在 2147483648-3006477107 范围内的结果,$variant 为 a.txt ;剩下如果落在 3006477108 - 4294967295 范围内,则将变量的值设置为 index.html 。

这一块真的和 Redis Cluster 中相关的概念非常类似,如果不记得了,可以回到 Redis进阶:分布式部署RedisCluster(一) 这篇文章中,看一下 槽Slot 相关的说明。接下来就是测试了,不停地修改 a 参数的值就可以看到效果啦。

➜  ~ curl 'http://192.168.56.88:8034//splitclient/'
111222333444<h1>aaa</h1>➜  ~ curl 'http://192.168.56.88:8034//splitclient/?a=1'
this is a.txt. 111➜  ~ curl 'http://192.168.56.88:8034//splitclient/?a=2'
111222333444<h1>aaa</h1>➜  ~ curl 'http://192.168.56.88:8034//splitclient/?a=3'
this is a.txt. 111➜  ~ curl 'http://192.168.56.88:8034//splitclient/?a=4'
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!123123</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p><p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p><p><em>Thank you for using nginx.</em></p>
</body>
</html>

总结

安全链接这个,是不是感觉有点意思啊,虽说大部分情况下我们会在动态语言中做接口签名,但静态资源有需要的时候完全也可以通过 Nginx 来实现嘛。这样不管动态还是静态资源,都是有请求限制的啦。

范围分片可能我们平常用得不多,大多数情况下可能是对一些下载文件做断点续传时会用到。

请求分流这个,其实可以实现更多的功能。因为我们可以设置变量,就可以将这个变量应用到 location、if、rewrite 等等各种配置中去,甚至分开记录日志都可以。非常强大,也非常灵活,期待各路高手大佬的开发咯,有好的案例也欢迎留言分享哦。

参考文档:

http://nginx.org/en/docs/http/ngx_http_secure_link_module.html

http://nginx.org/en/docs/http/ngx_http_slice_module.html

http://nginx.org/en/docs/http/ngx_http_split_clients_module.html

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端react入门day01-了解react和JSX基础

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 React介绍 React是什么 React的优势 React的市场情况 开发环境搭建 使用create-react-app快速搭建…

Qt窗体设计的布局

本文介绍Qt窗体的布局。 Qt窗体的布局分为手动布局和自动布局&#xff0c;手动布局即靠手工排布各控件的位置。而自动布局则是根据选择的布局类型自动按此类型排布各控件的位置&#xff0c;使用起来比较方便&#xff0c;本文主要介绍Qt的自动布局。 1.垂直布局 垂直布局就是…

看微功耗遥测终端机如何轻松应对野外环境挑战?

在野外&#xff0c;数据的实时监测和传输是至关重要的。无论是环境温度、湿度&#xff0c;还是水位、流量&#xff0c;都需要精准把控。然而&#xff0c;传统的监测方法往往受限于电源供应问题&#xff0c;而无法充分发挥其功能。这时候&#xff0c;一款微功耗遥测终端机&#…

Zabbix“专家坐诊”第207期问答汇总

问题一 Q&#xff1a;不小心把host表删除了&#xff0c;怎么处理&#xff1f;现在使用的zabbix 4.0.3的server&#xff0c;agent是4.2.1&#xff0c;能不能不动agent的情况下升级server版本&#xff0c;重新部署&#xff1f; A&#xff1a;数据库有备份话恢复即可&#xff0c;…

在线零售多用户多门店连锁商城系统

在线零售多用户商城系统和多门店连锁商城系统的核心都是线上线下相结合的&#xff0c;线上和线下结合&#xff0c;一体化是在线新零售多用户商城系统发展的趋势&#xff0c;现在移动互联网时代&#xff0c;越来越多的传统企业&#xff0c;如&#xff1a;连锁店铺&#xff0c;连…

SpringBoot中的日志使用

SpringBoot的默认使用 观察SpringBoot的Maven依赖图 可以看出来&#xff0c;SpringBoot默认使用的日志系统是使用Slf4j作为门户&#xff0c;logback作为日志实现 编写一个测试代码看是否是这样 SpringBootTest class SpringbootLogDemoApplicationTests {//使用Slf4j来创建LOG…

Android音视频开发之基础知识

一、视频文件 1、视频格式 常见格式&#xff1a;mp4、mkv、flv 封装的数据&#xff1a;音频码流、视频码流 常用工具&#xff1a; [FFmpeg下载]:https://ffmpeg.org/download.html 下载、安装并配置环境变量 ffmpeg.exe 视频编解码 ffplay.exe 播放器库 ffprobe.exe 音视频分…

17-spring aop调用过程概述

文章目录 1.源码2. debug过程 1.源码 public class TestAop {public static void main(String[] args) throws Exception {saveGeneratedCGlibProxyFiles(System.getProperty("user.dir") "/proxy");ApplicationContext ac new ClassPathXmlApplication…

【TES605】基于Virtex-7 FPGA的高性能实时信号处理平台

板卡概述 TES605是一款基于Virtex-7 FPGA的高性能实时信号处理平台&#xff0c;该平台采用1片TI的KeyStone系列多核DSP TMS320C6678作为主处理单元&#xff0c;采用1片Xilinx的Virtex-7系列FPGA XC7VX690T作为协处理单元&#xff0c;具有2个FMC子卡接口&#xff0c;各个处理节…

【PyTorch】深度学习实践 02 线性模型

深度学习的准备过程 准备数据集选择模型模型训练进行推理预测 问题 对某种产品花费 x 个工时&#xff0c;即可得到 y 收益&#xff0c;现有 x 和 y 的对应表格如下&#xff1a; x &#xff08;hours&#xff09; y&#xff08;points&#xff09;12243648 求花费4个工时可得…

Power BI 傻瓜入门 5. 准备数据源

本章内容将介绍&#xff1a; 定义Power BI支持的数据源类型探索如何在Power BI中连接和配置数据源了解选择数据源的最佳做法 现代组织有很多数据。因此&#xff0c;不用说&#xff0c;微软等企业软件供应商已经构建了数据源连接器&#xff0c;以帮助组织将数据导入Power BI等…

Microsoft Edge浏览器中使用免费的ChatGPT

一、双击打开浏览器 找到&#xff1a;扩展&#xff0c;打开 二、打开Microsoft Edge加载项 三、Move tab新标签 获取免费ChatGPT 四、启用Move tab。启用ChatGPT。 扩展 管理扩展 启用 五、新建标签页&#xff0c;使用GPT 六、使用举例 提问 GPT回复

asp.net网球馆计费管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net网球馆计费管理系统是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语 言开发 aspnet网球馆计费管理系统1 二、…

零售创新:社交媒体如何改变跨境电商游戏规则?

在当今数字化的时代&#xff0c;社交媒体已经成为了我们日常生活中不可或缺的一部分。Facebook、Instagram、Twitter、WeChat等平台不仅让我们与朋友家人保持联系&#xff0c;还成为了一个新的商业战场。特别是在跨境电商领域&#xff0c;社交媒体的崛起正在彻底改变游戏规则。…

选择实验室超声波清洗机具有哪些作用?

实验室超声波清洗机之所以一经面世就能迅速赢得众多消费者的心&#xff0c;这是因为实验室超声波清洗机设备厂家所提供的高性能超声波清洗机具有非常好的清洗效果。清洗效果的高低一直是各实验室关注的焦点问题&#xff0c;现在就选择实验室超声波清洗机具有哪些作用作简要阐述…

掌握测评补单技术对Shopee、Lazada店铺有什么好处?

虾皮(Shopee)、lazada作为东南亚地区最大的电商平台之一&#xff0c;吸引了众多卖家加入其平台&#xff0c;竞争激烈。在如此庞大的市场中&#xff0c;如何优化你的shopee、lazada店铺商品再结合自养号测评&#xff0c;提高曝光率和销售能力成为关键。本文将分享一些有效的方法…

数学预备知识

函数篇&#xff1a; 一次函数、反比例函数、二次函数、指数函数、对数函数、幂函数、三角函数、反三角函数、极点坐标等等 初中数学 【a&#xff0c;b】&#xff1a;开区间 &#xff08;a&#xff0c;b&#xff09;&#xff1a;闭区间 ∞ &#xff1a;无穷大 ∞&#xff1…

UE4/5:通过Blender制作BlendShape导入【UE4/5曲线、变形目标,blender形态键】

UE4/5里面&#xff0c;我们经常可以在一些骨骼模型上面看到相关的曲线&#xff0c;如Metahuman里面就是通过这个曲线来改变人物的脸部表情。 而这里笔者将教导如何去制作这种曲线。 这种曲线都是存在于骨骼模型上的&#xff0c;所以我们要么直接制作骨骼模型导入ue&#xff0…

【Spring篇】数据源对象管理加载properties文件

&#x1f38a;专栏【Spring】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【如愿】 &#x1f970;欢迎并且感谢大家指出小吉的问题 文章目录 &#x1f33a;数据源对象管理&#x1f6f8;基础版⭐在pom.xml文件中加入下面的代码&…

HIMA F3236 F7553 面向制造业的可视化人工智能

HIMA F3236 F7553 面向制造业的可视化人工智能 近年来&#xff0c;出现了一种分析高触摸制造的新解决方案:基于图像传感器数据的人工智能驱动分析。与时间和运动研究或Gemba Walks不同&#xff0c;分析从不停止&#xff0c;系统更不容易出现人为错误和偏差。 直到最近&#…