Day59-Nginx反向代理与负载均衡算法精讲及会话保持精讲

Day59-Nginx反向代理与负载均衡算法精讲及会话保持精讲

  • 7.nginx负载均衡调度算法
    • 7.1 什么是nginx负载均衡调度算法
    • 7.2 nginx负载均衡调度算法有哪些。
  • 8.负载均衡后端的会话保持
    • 8.1 nginx负载均衡会话(session)保持
    • 8.2 负载均衡集群会话保持
    • 8.3 实践共享会话保持

7.nginx负载均衡调度算法

7.1 什么是nginx负载均衡调度算法

集群节点有多个,怎么分发请求到不同的节点。

7.2 nginx负载均衡调度算法有哪些。

调度算法一般分为两类:
第一类为静态调度算法,
即负载均衡器根据自身设定的规则进行分配,不需要考虑后端节点服务器情况,
例如:rr、wrr、ip_hash都属于静态调度算法。

第二类为动态调度算法,
即负载均衡器会根据后端节点的当前状态来决定是否分发请求,
例如:连接数少的优先获得请求,响应时间短的优先获得请求。
例如:least_conn、fair等都属于动态调度算法。

3个静态调度算法:
rr:轮询调度,根据请求,均匀分配给资源池各个应用节点
作用:平均分配每个请求到不同节点,特点用于配置相同的服务器。

wrr:加权轮询,根据节点的权重比来调度
作用:解决对配置不同的服务器可以获得不同的调度比例。

ip_hash:根据hash算法计算出最合适的一台A节点处理请求,后续该IP再次请求,还是对应的A节点处理。
hash(客户端IP)/3=0,1,2 当客户端IP不变的时候,请求都会被调度到同一个节点。
实践:当增加节点后,哪怕是down的设置,都会改变请求的服务器。
作用:解决集群的会话保持的问题。
弊端:会导致后端某一个应用节点压力过大,而其他节点没有流量。
问题:调度到的节点故障怎么办?
切换其他可用的节点,故障节点恢复了,则继续调度到该节点。

完美解决方案:
既想使用轮询负载算法,又想解决会话保持的问题,
又不想某个单个节点压力过大,其他空闲:
采用redis缓存,存储所有节点服务器产生的session会话信息。

默认:

[root@web01 conf.d]# ls /var/lib/php/session/
sess_67d11aac46ad07cdd20faf23f2f6ed16

url_hash:和ip_hash类似,这里是根据访问URL的hash结果来分配请求的,让每个URL定向到同一个后端服务器,后端服务器为缓存服务器时效果显著。
Nginx本身不支持url_hash,这种调度算法必须安装Nginx的hash模块软件包。
hash(客户端URL)/3=0,1,2 当客户端URL不变的时候,请求都会被调度到同一个节点。
作用:主要用于缓存服务集群
问题:节点宕机或增加节点,容易出现缓存数据大面积动荡。一致性hash算法。

upstream oldboy_lb {
	server squid1:3128;
	server squid2:3128;
	hash $request_uri;
	hash_method crc32;
}

consistent_hash

一致性HASH算法:一般用于代理后端业务为缓存服务(squid,memcached)的场景,通过将用户请求的URI或者指定字符串进行计算,然后调度到后端的服务器上,此后任何用户查找同一个URI或者指定字符串都会被调度到这一台服务器上,
因此后端的每个节点缓存的内容都是不同的,一致性HASH算法可以解决后端某个或几个节点宕机后,
缓存的数据动荡的最小
具体算法,将每个server虚拟成n个节点,均匀分布到hash环上,每次请求,根据配置的参数计算出一个hash值,在hash环
上查找离这个hash最近的虚拟节点,对应的server作为该次请求的后端机器。
该模块可以根据配置参数采取不同的方式将请求均匀映射到后端机器,比如:

consistent_hash $remote_addr# 可以根据客户端ip映射
consistent_hash $request_uri# 根据客户端请求的uri映射
consistent_hash $args# 根据客户端携带的参数进行映射

虽然Nginx本身不支持一致性HASH算法,但Nginx的分支tengine支持。详细可见
链接: http://tengine.taobao.org/document_cn/http_upstream_consistent_hash_cn.html

http {
    upstream test {
        consistent_hash $request_uri;
        server 127.0.0.1:9001 id=1001 weight=3;
        server 127.0.0.1:9002 id=1002 weight=10;
        server 127.0.0.1:9003 id=1003 weight=20;
   }
}

3.consistent hashing算法的原理
Consistent hashing是一种hash算法,简单的说,在移除或添加一个cache节点时,能够尽可能小的改变已存在的key的映射关系,尽可能的满足单调性的要求。
单调性:

为什么要讲?
least_conn(动态调度算法)
least_conn算法会根据后端节点的连接数来决定分配情况,哪个机器连接数少就分发。
除了上面介绍的这些算法外,还有一些第三方的调度算法,例如:url_hash、一致性

fair(动态调度算法)
此算法会根据后端节点服务器的响应时间来分配请求,响应时间短的优先分配。这是更加智能的调度算法。此种算法可以依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx本身是不支持fair调度算法的,如果需要使用这种调度算法,必须下载Nginx的相关模块

8.负载均衡后端的会话保持

8.1 nginx负载均衡会话(session)保持

会话技术
1)什么是会话?
Http协议是无状态的协议,在网络传输中的每次连接断开后,需要重新再去连接,因此服务器端是无法判断此次连接的客户端是谁。如果每次数据传输都需要进行连接和断开,那造成的开销是很巨大的。并且网站有会员和非会员区别,同时,有浏览网站和登录账户购物等需求,因此就需要一种方法区别不同访问的用户是谁,于是会话就应运而生。会话实现有cookie和session。

2)什么是cookie?
为了解决网络访问的用户是谁的问题,因此cookie应运而生,当用户登陆成功后,服务器会在返回响应数据的同时也携带着cookie信息给到客户端浏览器,之后客户端每次发起请求只要携带着这个cookie信息,服务端就会验证这个cookie信息,进而判断用户是谁,用户则会处于登录的状态,无需再登录,同时也改善了网络传输效率。
但是由于cookie是保存在客户端浏览器的数据,因此也很容易被获取,存在安全方面隐患。

3)什么是session?
session本质是通过以cookie的方式向客户端发送随机字符串,每次客户端发起请求时只要携带
该随机字符串便可被服务端获取进而验证用户登录的身份。session的实现依赖于cookie。
session信息是保存在服务端的数据。

用户请求整个session过程的基本原理。

  1. 用户发出登录请求。
  2. 服务端判断用户账户密码是否正确
  3. 如正确,则返回数据并在cookie中写随机字符串(session ID),并且在服务端以{随机字符串:{‘k’:‘v’}}的形式存储用户相关数据。
  4. 客户端接收服务端在cookie中写随机字符串(session ID),并且保留在浏览器本地。
  5. 下次同一个客户发送请求,携带cookie(包含session ID)信息在请求报文里。
  6. 服务端会判断客户端提交的cookie信息是否包含session ID,如有再去服务器中查询该session ID 是否有对应的session数据,如果有则说明是登录过的用户,返回请求的数据。

4)cookie和session区别?

会话cookiesession
存放位置客户端浏览器里服务器端(文件、数据库、Redis)
作用可存放服务器端下发的信息,用户、密码、session id信息等存放用户登录信息,用户、密码、session id、购物车信息等
安全性不安全,容易被伪造,出现过很多安全的问题安全,不容易被伪造
生产应用其他信息可以放在cookie中登录信息等重要信息存放为session
客户端解决会话保持问题服务端解决会话保持问题

8.2 负载均衡集群会话保持

1)什么是会话保持
会话保持是运行负载均衡集群时需要的一种机制,在负载均衡的同时还保证一系列相关连的访问请求都会分配到同一台机器上。一句话说明就是在一次会话过程中发起的多个请求都会落到同一台机器上。

2)为什么需要会话保持
负载均衡集群后面有多个节点,如果一个用户的多次请求被分配到多个不同节点,就会导致用户登录了网站后(假如分配到A节点),然后在点击进入其它页面后,就会出现未登录状态的问题,这显然是不行的。

3)会话保持的实现方法
1.基于原地址实现:
即使用nginx ip_hash的调度算法,将同一用户的请求始终分配至同一服务器上。
优点:实现简单。缺点:导致负载失衡(特别是NAT上网的情况下)。

2.基于连接超时实现:
负载均衡器会为每一个处于保持状态中的会话设定一个时间值。若一个会话从上一次完成到下次再来之间的间隔时间小于超时值时,负载均衡器将会将新的连接进行会话保持;但如果这个间隔大于该超时值,负载均衡器会将新来的连接认为是新的会话然后进行负载平衡。lvs -p功能
优点:实现简单。缺点:也会导致负载有一定的失衡,仅LVS等少数软件支持。

3.利用session复制:
即采用复制的方法,当产生session时,同步复制到所有集群节点,tomcat集群功能。

4.把session共享(重要普遍):
即采用将session集中存储到某一固定地点:
a.文件中存放(PHP服务默认)。b.数据库中存放即采用将session存储至MySQL数据库中(例如:discuz论坛)c.内存数据库(memcache,redis)中存放(推荐)
即采用统一的内存数据库存储方式,将session存储到redis,memcached中。中小企业推荐使用内存数据库实现。

优点:速度快。缺点:需要配置内存数据库,并且要配置动态服务配置文件。
在这里插入图片描述

链接: https://blog.51cto.com/oldboy/1331316

5.cookie插入方式实现
在基于cookie模式下负载均衡器负责插入cookie,后端服务器无需作出任何修改。当客户端进行第一次请求时,客户端的HTTP request(不带cookie)进入负载均衡器, CLB根据负载平衡算法策略选择后端一台服务器,并将请求发送至该服务器;后端服务器的HTTP response(不带cookie)被发回给负载均衡器。接下来负载均衡器将向该后端服务器插入cookie并将HTTP response返回到客户端。

当客户请求再次发生时,客户HTTP request(带有上次负载均衡器插入的cookie)进入CLB,然后CLB读出cookie里的会话保持数值,将HTTP request(带有与上面同样的cookie)发到指定的服务器,然后后端服务器进行请求回复;由于服务器并不写入cookie,HTTP response将不带cookie,该HTTP response再次经过进入CLB时,CLB将写入更新后的会话保持cookie。腾讯云CLB的7层会话保持能力,就是基于这样的cookie插入的方式实现的。Haproxy也支持cookie插入的方式,但是Nginx默认不支持此种方式。

优点:不需要后端服务和程序支持,只在负载均衡器配置即可(需要负载均衡器支持)。缺点:消耗负载均衡资源

8.3 实践共享会话保持

1)环境准备:

负载均衡:  10.0.0.5
web集群:   10.0.0.7/10.0.0.8
Redis:    10.0.0.51
项目:      phpmyadmin
部署顺序:
1. 部署多个节点
2. 接入负载均衡

2)搭建环境(Nginx+php):

3)运行phpmyadmin项目作为测试环境(MySQL数据库的web管理界面,通过web页面的方式管理数据库):

1)部署web01及安装phpmyadmin
笔记已发

[root@web01 ~]# cat /etc/nginx/conf.d/phpmyadmin.etiantian.org.conf 
server {
    listen 80;
    server_name phpmyadmin.etiantian.org;
    root /data/phpmyadmin;
    index index.php index.html;
    
    location ~ \.php$ {
    root /data/phpmyadmin;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params;
}
 #用户名密码验证
    #auth_basic "oldboyedu Auth access";
    #auth_basic_user_file /etc/nginx/auth_pass;
    #来源IP限制
    #allow 172.16.1.0/24;        #允许指定的地址或地址段
    #deny all;                 #拒绝所有的地址
    }

2)部署web02:
web01:

scp phpmyadmin.etiantian.org.conf 172.16.1.8:/etc/nginx/conf.d
scp -r /data/phpmyadmin 172.16.1.8:/data

web02:

chown -R www.www /data/phpmyadmin/
chown -R www.www /var/opt/remi/php74/lib/php/session #浏览器打开phpmyadmin前可能没有
#htpasswd -cb /etc/nginx/auth_pass oldboy 123456

windows配置host解析
10.0.0.8 phpmyadmin.etiantian.org
浏览器浏览phpmyadmin.etiantian.org

3)部署lb01
phpmyadmin.etiantian.org虚拟主机反向代理lb01配置

[root@lb01 conf.d]# cat /etc/nginx/conf.d/01_test.etiantian.org.conf 
upstream backend {
    #server backend1.example.com       weight=5;
    #server backend2.example.com:8080;
    #server unix:/tmp/backend3;
    server 172.16.1.7       weight=1 ; #默认80端口 
    server 172.16.1.8       weight=1; #默认80端口
    #server 8080.etiantian.org:8080 down;
    #server 8080.etiantian.org:8080   backup; #热备
    #server backup2.example.com:8080   backup; #热备
}
server {
	listen 80;
	server_name test.etiantian.org;
	location / {
		proxy_pass http://backend;
		#proxy_pass http://a.etiantian.org:80;
                proxy_set_header Host $http_host;
	}
}
server {
        listen 80;
        server_name phpmyadmin.etiantian.org;
        location / {
                proxy_pass http://backend;
                proxy_set_header Host $http_host;
        }
}

4)测试浏览器打开phpmyadmin.etiantian.org
登录到数据库,然后刷新感受请求到不同节点后,出现未登录状态。
可以通过谷歌f12查看请求报文和响应报文。

5)登录172.16.1.51部署redis缓存
采用Redis共享方式来实现会话保持:
0.查看php redis访问支持

[root@web01 ~]# rpm -qa|grep redis
php71w-pecl-redis-3.1.6-1.w7.x86_64

1.安装配置redis 10.0.0.51

[root@db01 ~]# yum install redis -y
[root@db01 ~]# sed -i '/^bind/c bind 127.0.0.1 172.16.1.51' /etc/redis.conf
[root@db01 ~]# grep "^bind" /etc/redis.conf
bind 127.0.0.1 172.16.1.51
[root@db01 ~]# systemctl start redis
[root@db01 ~]# systemctl enable redis
[root@db01 ~]# netstat -lntup|grep redis
tcp        0      0 172.16.1.51:6379        0.0.0.0:*               LISTEN      2055/redis-server 1 
tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      2055/redis-server 1 

#查看redis中的数据:
[root@db01 ~]# redis-cli 
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> 

2.分别将web01,web02的php应用服务器的session信息、修改存储至Redis中(/etc/php.ini)

[root@web01 ~]# vim /etc/php.ini
session.save_handler = redis
session.save_path = "tcp://172.16.1.51:6379?weight=1&timeout=2.5"


#Redis有密码的配置方法
session.save_path = "tcp://172.16.1.51:6379?auth=oldboy123"	

#使用;注释如下两行,
[root@web01 ~]# vim /etc/php-fpm.d/www.conf
;php_value[session.save_handler] = files
;php_value[session.save_path]    = /var/lib/php/session

重启php-fpm
[root@web01 ~]# systemctl restart php-fpm

注意;web02的特殊,大家可以自己跟web01一样配置

老师的web02安装的是php74,注意路径:
采用方法2:子配置的方法

[root@web02 ~]# cat /etc/opt/remi/php74/php.d/50-redis.ini 
session.save_handler = redis
session.save_path = "tcp://db01.etiantian.org:6379?weight=1"

#使用;注释如下两行,
vim /etc/opt/remi/php74/php.ini
session.save_handler = file
session.save_path = "/tmp"


#使用;注释如下两行,
[root@web01 ~]# vim  /etc/opt/remi/php74/php-fpm.d/www.conf
;php_value[session.save_handler] = files
;php_value[session.save_path]    = /var/lib/php/session

systemctl restart php74-php-fpm.service

3.测试访问
将lb01负载均衡调度修改为默认轮询的方式测试。
检查是不是登录后依然是登录状态。
采用谷歌f12查看本地cookie,同时查看请求报文和响应报文,
看和讲解的session工作原理流程是否一致。
同时,查看redis中是否有session数据。

127.0.0.1:6379> keys *
1) "PHPREDIS_SESSION:5908fd411a39c1149a9db18332830cee"
2) "PHPREDIS_SESSION:be6bb9c370f83cdd5f7c41ac11b96404"
3) "PHPREDIS_SESSION:77bfa030697cc2660fb9000f3553ee85"
127.0.0.1:6379> keys *
1) "PHPREDIS_SESSION:5908fd411a39c1149a9db18332830cee"
2) "PHPREDIS_SESSION:be6bb9c370f83cdd5f7c41ac11b96404"
3) "PHPREDIS_SESSION:77bfa030697cc2660fb9000f3553ee85"
127.0.0.1:6379> keys *
1) "PHPREDIS_SESSION:fa5a092ae9b53f071c5942e18f81d83a"
2) "PHPREDIS_SESSION:be6bb9c370f83cdd5f7c41ac11b96404"
3) "PHPREDIS_SESSION:77bfa030697cc2660fb9000f3553ee85"
127.0.0.1:6379> keys *
1) "PHPREDIS_SESSION:7eff395a4c057891e3bbb03d5ca1ffc9"
2) "PHPREDIS_SESSION:be6bb9c370f83cdd5f7c41ac11b96404"
3) "PHPREDIS_SESSION:77bfa030697cc2660fb9000f3553ee85"
127.0.0.1:6379> 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《Mahjong Bump》

Mahjong Bump 类型:Tile 三消 视角:2d 乐趣点:清空杂乱快感,轻松的三合一休闲 平台:GP 时间:2021 个人职责: 所有程序部分开发 上架 GooglePlay 相关工做 针对游戏数据做出分析,讨论…

并发编程之的HashSet和HashMap的详细解析

HashSet不安全 HashSet也是线程不安全的,底层没有进行任何线程同步处理。 在hashset的源码中,底层是用hashmap实现的: 每次add的时候,把值放在了map对象中的key,而map对象的value则全部统一放一个常量: 在下…

【前端学习——js篇】6.事件模型

具体见:https://github.com/febobo/web-interview 6.事件模型 ①事件与事件流 事件(Events) 事件是指页面中发生的交互行为,比如用户点击按钮、键盘输入、鼠标移动等。在js中,可以通过事件来触发相应的操作,例如执行函数、改变…

STM32H743驱动SSD1309(3)

接前一篇文章:STM32H743驱动SSD1309(2) 三、命令说明 1. 设置命令锁定(FDh) 此双字节命令用于锁定OLED驱动器IC,不接受除其自身之外的任何命令。在输入FDh 16h(A[2]=1b)…

C语言文件操作详解

文件是什么 在我们日常使用的电脑上我们在电脑磁盘上会看到许许多多的文件夹,那里面的东西其实就是文件,为什么我们要使用文件?那是因为我们的电脑肯定会要用来存储东西的,如果没有文件,那么我们的东西都全部存放在内…

应急响应小结

应急响应的整体思路 应急响应的整体思路,就是上层有指导性原则和思想,下层有技能、知识点与工具,共同推进和保障应急响应流程的全生命周期。 原则和指导性思路 3W1H原则:3W即Who、What、Why,1H即How,做应…

Vastbase编程利器:PL/pgSQL原理简介

PL/pgSQL是Vastbase提供的一种过程语言,在普通SQL语句的使用上增加了编程语言的特点,可以用于创建函数、存储过程、触发器过程以及创建匿名块等。 本文介绍Vastbase中PL/pgSQL的执行流程,包括PL/pgSQL的编译与运行。 1、编译 PL/pgSQL的编译…

Windows入侵排查

目录 0x00 前言 0x01 入侵排查思路 1.1 检查系统账号安全 1.2 检查异常端口、进程 1.3 检查启动项、计划任务、服务 0x00 前言 当企业发生黑客入侵、系统崩溃或其它影响业务正常运行的安全事件时,急需第一时间进行处理,使企业的网络信息系统在最短时…

CQ 社区版2.10.0 | 新增 SQL 审核、全新英文版上线…

三月中旬,我们预告了 CloudQuery 社区版即将上线的「SQL 审核」功能。现在,它来了! 本次社区版 v2.10.0,除了 SQL 审核功能,我们还在手动授权、连接分组等模块做了新功能和优化。 新增功能 新增 SQL 审核功能 支持…

政安晨:【深度学习神经网络基础】(二)—— 神经元与层

政安晨的个人主页:政安晨 欢迎 👍点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益,如有不足之处,欢迎在评论区提出指正! 神经元是深度学习神经网络中的基本单元,模拟了…

从零开始为香橙派orangepi zero 3移植主线linux——1.uboot

从零开始为香橙派orangepi zero 3移植主线linux——1.uboot 0.前言一、准备二、制作引导文件1.BL312.SCP firmware (Crust)3.uboot 三、烧录四、运行 0.前言 之前买了块香橙派zero3,CPU是全志H618,四核cortex-A53,烧录了官方的ubuntu系统后就…

nodejs中使用WebScoket的简单示例

前言 WebScoket可以用来实现即时通信,一般用于通信聊天工具或者是需要实时接受数据等功能 在浏览器环境中,WebScoket是一个构造函数,需要new创建连接的实例; 在nodejs环境中,则需要使用ws模块来完成服务的创建。 示例 下面是可以直接使用的代码,不需要修改 node创建服务端…

Avalonia笔记4-Rider如何添加xaml支持

在Linux Rider中,File Type中是有XAML文件的,但是新增xaml文件并不能正确的添加到项目中,而且就算是新增文件,直接命名为“XXX.xaml”,也是没有智能提示的。 在引用Style文件的时候,需要新建一个axaml的文…

STM32H743驱动SSD1309(2)

接前一篇文章:STM32H743驱动SSD1309(1) 二、芯片详解 1. 概览 上一回已提到,SSD1309是一个单片CMOS OLED/PLED驱动芯片可以驱动有机/聚合发光二极管点阵图形显示系统。由128个segments和64个commons组成。该芯片专为共阴极OLED…

机器学习——聚类算法-KMeans聚类

机器学习——聚类算法-KMeans聚类 在机器学习中,聚类是一种无监督学习方法,用于将数据集中的样本划分为若干个簇,使得同一簇内的样本相似度高,不同簇之间的样本相似度低。KMeans聚类是一种常用的聚类算法之一,本文将介…

【设计经验】0Ω电阻在电路中有什么作用

电路设计与调试过程中,我们很多时候要用到0Ω电阻(如下图),那么0Ω电阻到底在这过程中充当了什么样的角色呢? 0R电阻在电路中有什么作用? #创作灵感#:脑海存留的如下几点疑惑需要解开。 1、电路初次设计使用串接电阻为什么是0R电阻; 2、单板调试时为什么有时候会用到0R…

VMware Live Recovery 9.0 发布 - 多云实时恢复

VMware Live Recovery 9.0 - 多云实时恢复 VMware Live Cyber Recovery VMware Live Site Recovery 请访问原文链接:https://sysin.org/blog/vmware-live-recovery/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.or…

Unity学习笔记 9.2D射线

下载源码 UnityPackage 1.Ray2D 让小球向右发射射线: Ray2D ray;void Start() {// Ray2D(起点,终点)ray new Ray2D(this.transform.position, Vector2.right);// Debug.DrawLine(起点,终点,颜色,显示时间)Debug.DrawL…

[实战]Springboot与GB28181摄像头对接。摄像头注册上线(一)

与支持国标摄像头对接 前言:不想看教程?1、准备阶段1.1、我们会学到什么?1.2、创建项目1.3、pom中用到的依赖1.4 打开摄像头的网址(了解配置方式) 2、代码编写2.1、增加项目配置2.2、在config目录下创建SipConfig2.3、在service目录下创建Sip…

如何在Windows 10中打开屏幕键盘?这里有详细步骤

本文解释了在Windows 10中打开或关闭屏幕键盘的不同方法,还解释了如何将屏幕键盘固定到开始菜单。 使用屏幕键盘的快捷键 如果你喜欢快捷方式,你会喜欢这个:按物理键盘上的Win+CTRL+O。这将立即显示屏幕键盘,而无需通过轻松使用。 ​提示:使用运行窗口也可以打开键盘。…