nginx应用

## Nginx教程

### 1. 为什么要使用Nginx

单体式的架构的项目:公司的项目刚刚上线的时候,并发量小,用户使用的少,所以在低并发的情况下,一个jar包应用就够了,但是慢慢的,平台用户多了起来,并发量慢慢增大了,用户群体的不断壮大,单台的服务器遇到了瓶颈,这时候一台服务器满足不了我们的需要了。

于是我们思考新的解决方案,进行了横向扩展,又增加了服务器,这个时候几个项目启动在不同的服务器上,用户要访问,就需要增加一个代理服务器了,通过代理服务器来帮我们转发和处理请求。

我们希望这个代理服务器可以帮助我们接收用户的请求,然后将用户的请求按照规则帮我们转发到不同的服务器节点之上。这个过程用户是无感知的,用户并不知道是哪个服务器返回的结果,我们还希望他可以按照服务器的性能提供不同的权重选择,保证最佳体验,所以我们使用了Nginx。



### 2. Nginx的简介

Nginx是一个高性能的HTTP和反向代理web服务器,是由伊戈尔·赛索耶夫为俄罗斯访问量第二站点开发的,因它的稳定性、丰富的功能集、简单的配置文件和低系统资源的消耗而闻名,第一个公开版本0.1.0发布于2004年10月4日。

Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件代理服务器,其特点是占有内存少,并发能力强,事实上Nginx的并发能力在同类型的网页服务器中表现较好,

中国大陆使用Nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。

Nginx是由C语言开发,专为性能优化而开发,性能是最重要的考量,实现上非常注重效率,能经受高负载的考验,官方数据测试表明能够支持高达50000个并发连接数的响应。

https://lnmp.org/nginx.html

### 3.Nginx的特征

#### 3.1Nginx具有很高的稳定性

其他Http服务器,当遇到访问的峰值,或者有人恶意发起慢速连接时,也很可能会导致服务器物理内存耗尽,频繁交换,失去响应,只能重启服务器。例如当apache一旦上到200个以上进程,web响应速度就明显非常缓慢了。而Nginx采取了分阶段资源分配技术,使得它的CPU与内存占用率非常低。Nginx官方表示保持10000个没有活动的链接,它只占2.5MB内存,所以类似DOS这样的攻击对Nignx来说基本上是毫无用处的。

#### 3.2 Nginx支持热部署

它的启动特别容易,并且几乎可以做到7*24小时不间断运行,即使运行数个月也不需要重新启动。你还能够在不间断服务的情况下,对软件版本进行升级。



### 4.Nginx的作用

#### 4.1.反向代理

正向代理:如果把局域网外的Internet想象成一个巨大的资源库,则局域网中的客户端要访问Internet,则需要通过代理服务器来访问,这种代理服务就称为正向代理。 正向代理(VPN,玩游戏使用)代理的是客户端。

![1](Nginx.assets/1.jpg)

反向代理代理的是服务器端,比如咱们在客户端浏览器里访问的百度,客户端发出请求后,由一台nginx服务器接收到请求后,从后台调取一台服务器给咱们提供接收请求,进行响应的过程。在这个过程中这个Nginx服务器就是百度众多服务器的代理。

#### 4.2.负载均衡

客户端发送多个请求到服务器,服务器处理请求,有一些可能要与数据库进行交互,服务器处理完毕后,再将结果返回给客户端。

这种架构模式对于早期的系统相对单一,并发请求相对较少的情况下是比较适合的,成本也低。但是随着信息数量的不断增长,访问量和数据量的飞速增长,以及系统业务的复杂度增加,这种架构会造成服务器响应客户端的请求日益缓慢,并发量特别大的时候,还容易造成服务器直接崩溃。很明显这是由于服务器性能的瓶颈造成的问题,那么如何解决这种情况呢?

我们首先想到的可能是升级服务器的配置,比如提高CPU的执行频率,加大内存等提高机器的物理性能来解决此问题,但是我们知道摩尔定律的日益失效,硬件的性能提升已经不能满足日益提升的需求了,最明显的一个例子,天猫双十一当天,某个热销商品的瞬时访问量是极其庞大的,那么类似上面的系统架构,将机器都增加到现有的顶级物理配置,都是不可能满足需求的,那么怎么办呢?

12306 官网    阿里

上面的分析我们去掉了增加物理服务器来解决问题的办法,也就是说纵向解决问题的办法行不通了,那么横向增加服务器的数量呢?这时候集群的概念产生了,单个服务器解决不了,我们增加服务器的数量,然后将请求分发到各个服务器上,将原先请求集中到单个服务器上的情况改为分发到多个服务器上,将负载分发到不同的服务器,这种方式也就是我们所说的负载均衡。



![2](Nginx.assets/2.jpg)

Ngix提供的负载均衡策略有2种,内置策略和扩展策略。内置策略为轮询,加权轮询,IPhash(固定的IP只能访问到固定的服务器,保证session不会丢失的一种方案。)

#### 4.3.动静分离

在我们的软件开发中,有些请求是需要后台处理的,有些请求不需要经过后台处理,比如:css,js,html,jpg等文件,这些不需要后台处理的文件叫做静态文件。让动态网站里的动态网页根据一定的规则把不变的资源和经常变的资源区分开来,动静资源做好了拆分以后,我们就可以根据静态资源的特点将其做缓存操作,提高资源响应的速度。通过使用Nginx大大提高了我们网站的响应速度,优化了用户体验,让网站的健壮性更上一层楼!

![3](Nginx.assets/3-1640519527584.jpg)

### 5.windows下安装Nginx

官网:http://nginx.org/en/download.html

下载[nginx/Windows-1.20.1](http://nginx.org/download/nginx-1.20.1.zip) 稳定版。

服务启动后,访问80端口就会被nginx拦截。



### 6.Linux下安装Nginx步骤

#### 6.1 下载nginx压缩版

官网:http://nginx.org/en/download.html

下载nginx-1.20.1.tar.gz 稳定版

#### 6.2 上传到linux服务器

上传到了usr目录下

#### 6.3 安装gcc

安装nginx需要先将官网下载的源码进行编译,编译依赖gcc环境,如果没有gcc环境,则需要安装:

~~~bash
yum install gcc-c++
~~~

#### 6.4 查看版本

~~~bash
gcc -v
~~~

#### 6.5 安装pcre-devel依赖库

pcre是一个perl库,ngix的http模块使用pcre来解析正则表达式,所以要在linux上安装pcre

pcre-devel是使用的pcre开发的一个二次开发库,nginx也需要此库,命令:

~~~bash
yum -y install pcre-devel
~~~

#### 6.6 安装openssl依赖库

openssl是一个强大的安全套接字层密码库,囊括主要的密码算法,常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的的使用。nginx不仅支持http协议,还支持https(即在ssl协议上传输http),所以需要安装openssl库,命令:

~~~bash
yum -y install openssl openssl-devel
~~~

#### 6.7 解压缩

解压目录是在 /usr/nginx-1.20.1

~~~bash
tar -zxvf nginx-1.20.1.tar.gz
~~~

#### 6.8 进入目录

~~~bash
cd nginx-1.20.1
~~~

#### 6.9 执行自动配置

~~~bash
./configure
~~~

#### 6.10 执行make命令

把文件进行编译

~~~bash
make
~~~

#### 6.11 执行make install

再执行安装

~~~bash
make install
~~~

#### 6.12 查看安装的路径(是否成功)

nginx的默认安装目录: /usr/local/nginx

~~~bash
whereis nginx
~~~

#### 6.13 进入安装目录

~~~bash
cd /usr/local/nginx
ll
cd sbin
~~~

#### 6.14 查看nginx的配置文件

~~~bash
cd ..
ll
cd conf
ll
cat nginx.conf
~~~

#### 6.15 执行nginx的启动文件

~~~shell
# 进入安装目录
cd /usr/local/nginx/sbin
#启动Nginx服务
./nginx
~~~

#### 6.16 查看nginx进程

~~~shell
ps -ef | grep nginx
~~~

#### 6.17 输入IP地址进行访问

http://101.200.174.107,如果访问不到Nginx服务,则需要在防火墙中进行端口得开放操作

#### 6.18 防火墙的设置

需要记忆:

~~~shell
#查看防火墙的启动状态
systemctl status firewalld
# 关闭防火墙
systemctl stop firewalld
#开启防火墙
systemctl start firewalld
#查看开放的端口号
firewall-cmd --list-all
#在防火墙中设置开放的端口号
firewall-cmd --zone=public --add-port=80/tcp --permanent
#开启端口后,需要重启防火墙才生效
systemctl restart firewalld | firewall-cmd --reload 
# 如果有不用的端口,则进行移除
firewall-cmd --permanent --remove-port=8081/tcp
~~~



### 7.Nginx常用命令

~~~bash
# 进入nginx的目录
cd /usr/local/nginx/sbin
# 查看Nginx的版本
./nginx -v
# 启动Nginx
./nginx  
# 停止Nginx
./nginx -s stop 
# 安全退出Nginx,同时会关闭Nginx服务
./nginx -s quit 
# 重新加载配置文件(不重新启动Nginx,也会生效)
./nginx -s reload 
# 查看Nginx的进程
ps -ef | grep nginx 
~~~



### 8.Nginx配置文件的组成

进入Nginx配置文件的位置

~~~shell
cd /usr/local/nginx
ll
cd conf
ll
~~~

就可以看到nginx.conf文件,此文件就是Nginx的配置文件,通过 `vim nginx.conf`命令,打开配置文件

> Nginx配置文件有三部分组成:

#### 8.1第一部分:全局块

从配置文件开始到events块之间的内容,主要会设置一些影响nginx服务器整体运行的配置指令,主要包含配置运行Nginx服务器的用户(组),允许生成的worker、process数,进程PID存放路径,日志存放路径和类型以及配置文件的引入等。

比如上面第一行配置的

~~~
worker_processes  16;  //8个处理器 16G内存 
~~~

前面带#号的都是注释部分。

worker_processes这是Nginx服务器并发处理服务的关键配置,worker_processes值越大,可以支持的并发处理量也越多,但是会受到硬件,软件等设备的制约

查看CPU个数:

~~~shell
cat /proc/cpuinfo | grep "cores"|uniq
~~~

##### worker_processes,工作进程数

- 1.默认:worker_processes: 1  要启动的工作进程的数量。这个参数直接影响 Nginx 的性能和资源使用情况。通常,`worker_processes` 参数应该设置为服务器 CPU 核心数量的1-2倍。如果你的服务器有4核CPU,你可以设置`worker_processes`为4或者8。
- 2.调大:worker_processes: CPU核心数,(双核4线程,可以设置为4)

#### 8.2 第二部分:events块

比如下面的配置:

~~~
events {
    worker_connections  1024;
}
~~~

参数是用来设置nginx工作进程的最大连接数

worker_connections是Nginx的另一个重要参数。它指定了单个worker进程可以处理的并发连接数。这个值也需要根据服务器硬件、网络带宽、负载类型等因素

进行调整。一般情况下,可以根据服务器的内存大小来进行设置。如果服务器的内存足够大,则可以将worker_connections设置为非常大的值,以提高Nginx的并发处理能力。

例如,如果服务器的内存大小为16GB,则可以将worker_connections设置为16,384或32,768。

这部分的配置对Nginx的性能影响较大,在实际中应该灵活配置



#### 8.3 第三部分:http块

这算是Nginx服务器配置中最频繁的部分,代理,缓存和日志定义等绝大多数功能和第三方模块的配置都在这里,需要注意的是:http块也可以包括http全局块,server块。

http全局块:

http全局块配置的指令包括文件的引入,MIME-TYPE定义,日志自定义,连接超时时间,单链接请求数上限等。

server块:

这块和虚拟主机有密切关系,虚拟主机从用户角度看和一台独立的硬件主机是完全一样的,该技术的产生是为了节省互联网服务器硬件成本。

每个http块可以包括多个server块,而每个server块就相当于一个虚拟主机

而每个server块也可分为全局server块,以及可以同时包含多个location块。

##### 8.3.1 全局server块

最常见的配置是本虚拟机主机的监听配置和本虚拟主机的名称或IP配置。

##### 8.3.2 location块

一个server块可以配置多个location块

这块的主要作用是基于Nginx服务器接收到的请求字符串,对虚拟主机名称之外的字符串进行匹配,对特定的请求进行处理。地址定向,数据缓存和应答控制等功能,还有许多第三方模块的配置也在这里进行。



**Nginx配置文件各部分组成详解**

~~~shell
# 全局块:配置影响nginx全局的指令。一般包括配置运行nginx服务器的用户组、启动进程数、配置日志文件路径等。
user  nginx;
worker_processes  1;
 
# 错误日志文件和访问日志文件的位置
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
 
events {
    # 事件块:配置影响nginx服务器或与网络连接有关的指令,如每个进程的最大连接数等。
    worker_connections  1024;
}
 
http {
    # http块:可以包含多个server块,配置代理、日志格式等
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
 
    # 日志格式定义
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
 
    # 访问日志
    access_log  /var/log/nginx/access.log  main;
 
    sendfile        on;
    #tcp_nopush     on;
 
    keepalive_timeout  65;
 
    # 包含其他的server块配置文件
    include /etc/nginx/conf.d/*.conf;
 
    # 服务器块
    server {
        listen       80;
        server_name  localhost;
 
        # 位置块:用于匹配网页位置。
        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }
 
        # 定义错误页面
        error_page  404              /404.html;
        location = /40x.html {
        }
 
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
        }
    }
}
~~~



### 9. Nginx的使用

#### 9.1 反向代理的配置1

要实现的最终效果就是:

在本地浏览器中输入:www.abc.com,访问到nginx服务器192.168.8.54:80下,然后nginx做反向代理跳转到127.0.0.1:8085的服务器上。

![11](D:/Java2304班资料/二阶段/2023-08-18 day27/01-讲义/Nginx/Nginx.assets/11.png)

##### 9.1. 1 编写spring的项目工程

配置端口为8085与8086两个项目工程,编写好代码后打成jar文件,上传到服务器并进行启动,可在配置文件中设置端口号(或启动的时候指定端口也可以)

~~~shell
java -jar xxx.jar --server.port=8085
java -jar xxx.jar --server.port=8086
~~~

##### 9.1.2 在linux防火墙中开放8085与8086端口

~~~shell
firewall-cmd --zone=public --add-port=8085/tcp --permanent
firewall-cmd --zone=public --add-port=8086/tcp --permanent
~~~



##### 9.1.3 windows的host文件进行配置

配置域名映射的IP地址,当你在浏览器中输入一个域名后,它会先从本地的host文件中看有没有相应的配置,如果有的话,根据配置好的去执行,如果没有的话,

再从网络上DNS域名解析服务器,找网络中的IP去执行。



在windows系统的host文件中进行域名和IP对应关系的配置

在C盘下,Windows文件夹中有一个System32,里面有一个drivers文件下,打开找到etc,有一个HOSTS文件,在最后一行添加:

~~~
192.168.8.54 www.abc.com
~~~

##### 9.1.4 在Nginx中做请求转发的配置	

~~~
server {
    listen  80;
    server_name localhost; 
}
~~~

把localhost改为服务器的IP地址: 192.168.8.54

~~~
location / {
    root   html;
    proxy_pass http://127.0.0.1:8085/user/hello;
    index  index.html index.htm;
}
~~~

为什么要配置为127.0.0.1,是因为项目和nginx目前同在同一个linux下。

![3](D:/Java2304班资料/二阶段/2023-08-18 day27/01-讲义/Nginx/Nginx.assets/3.png)

 



~~~
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
	
	server {
		listen  80;
		server_name localhost; 
		
		location / {
			root   /usr/share/nginx/html;
			proxy_pass http://127.0.0.1:8080/newsweb/news/getList;
			index  index.html index.htm;
		}
	}

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;
    sendfile        on;

    keepalive_timeout  65;
    #gzip  on;
    
}

~~~



#### 9.2 反向代理的配置2

要实现的最终效果就是:

使用nginx反向代理,根据访问的路径跳转到不同的端口的服务中,nginx的监听端口为9001,访问

~~~
http://192.168.8.54:9001/teacher/ 直接跳转到127.0.0.1:8085/user/hello
http://192.168.8.54:9001/student/ 直接跳转到127.0.0.1:8086/user/hello
~~~

##### 9.2.1 在linux防火墙中开放9001端口

~~~shell
firewall-cmd --zone=public --add-port=9001/tcp --permanent
~~~

##### 9.2.2 具体配置

打开 nginx.conf 文件,再添加一个server节点,写如下配置

~~~
server {
    listen  9001;
    server_name 192.168.8.54; 
    
    location   /teacher/ {
         proxy_pass http://localhost:8085/user/hello;
    }
    location   /student/ {
         proxy_pass http://localhost:8086/user/hello;
    }
}
~~~

说明:~ 符合是用的一种正则表达式的形式,意思就是说当你的访问路径中存在teacher,就转发到8005 ,但是有个前提,如果使用了~ 线,proxy_pass 代理的服务器路径后面只能存在http://loalhost:8005   只能有IP地址+端口号



##### 9.1.3 测试

在浏览器中输入

~~~
http://192.168.8.54:9001/edu/hello
http://192.168.8.54:9001/vod/hello
~~~



#### 9.3 负载均衡的配置

在http块中添加如下配置

~~~
upstream myserver {
    server  192.168.8.54:8085;
    server  192.168.8.54:8086;
}
~~~

然后在server中把server_name 的值localhost改为 101.200.174.107

~~~
server {
    listen  80;
    server_name 192.168.8.54; 
}
~~~

在location中配置  proxy_pass http://myserver;

~~~co
location / {
    root   html;
    index  index.html index.htm;
    proxy_pass http://myserver;
}
~~~

测试:

http://192.168.8.54/user/hello

#### 9.4 负载均衡的策略

负载均衡是将负载分摊到不同的服务单元,既保证服务的可用性,又保证响应足够快,给用户很好的体验。

Nginx提供了几种分配策略:

##### 9.4.1轮询(默认)

每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。

如果你买的两台服务器,配置不一致,  4核8G       1核2G

##### 9.4.2weight(权重) 

weight代表权重,默认值为1,权重越高被分配到的客户端越多

~~~
upstream myserver {
    server  192.168.8.54:8085 weight=1;
    server  192.168.8.54:8086 weight=3;
}
~~~

##### 9.4.3 ip_hash

每个请求按访问ip的hash结果分配,这样每个访客固定一个后端服务器,可以解决session的问题 

~~~
upstream myserver {
    ip_hash;
    server  101.200.174.107:8085;
    server  101.200.174.107:8086;
}
~~~

##### 9.4.4 fair (第三方)

按后端服务器的响应时间来分配请求,响应时间短的优先分配

~~~
upstream myserver {
    server  101.200.174.107:8085;
    server  101.200.174.107:8086;
    fair;
}
~~~



### 10. 动静分离的配置

#### 10.1 前端页面的请求设置

~~~vue
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
	</head>
	<body>
		<div id="app">
			<input type="button"  value="获取数据"  @click="buyGood" /><br/>
			<span >{{message}}</span>
		</div>

	</body>
	<script src="https://cdn.staticfile.net/vue/2.7.0/vue.min.js"></script>
	<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
	<script>
		axios.default.withCredentials = true
		new Vue({
			el: "#app",
			data: {
				message:""
			},
			methods: {
				buyGood() {
					axios({
						method: "get",
						url: "/ipport/hello"
					}).then(res => {
						this.message=res.data
						
					})
				}
			}
			
		})
	</script>
</html>
~~~

#### 10.2 后端Controller的设置

~~~java
@CrossOrigin
@RestController
public class IndexController {
    @RequestMapping("/index")
    public String index(){
        System.out.println("进入项目1");
        return "欢迎登录首页!";
    }
}
~~~

#### 10.3 Nginx的设置

~~~
upstream mengshujun {
    server 192.168.2.167:8085 weight=1;
    server 192.168.2.167:8086 weight=1;
}
~~~

~~~
location / {
    root /web/shop/;
    index  index.html index.htm;
}

location /ipport/ {
    proxy_pass http://mengshujun/;
}
~~~

动静分离配置:

~~~shell

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    upstream myserver{
        server 47.93.163.95:8085 weight=1;
        server 47.93.163.95:8086 weight=1;
    } 
   
    server {
        listen     80;
        server_name  47.93.163.95;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   /myweb;
            index  index.html index.htm;
        }

        location /ipport/ {
            proxy_pass http://myserver/;
        }       

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

~~~




  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值