当前位置: 首页 > news >正文

网站备案的规划方案做网站编辑怎么样

网站备案的规划方案,做网站编辑怎么样,40个常见的html标签及含义,淘宝联盟怎么自己做网站推广10-Ansible 角色管理 文章目录10-Ansible 角色管理实验环境准备Ansible 角色角色介绍:为什么需要角色?角色结构:标准化的目录布局角色存放位置:Ansible 去哪里找角色?创建角色:实战示例(部署 Ap…

10-Ansible 角色管理

文章目录

    • 10-Ansible 角色管理
      • 实验环境准备
      • Ansible 角色
        • 角色介绍:为什么需要角色?
        • 角色结构:标准化的目录布局
        • 角色存放位置:Ansible 去哪里找角色?
        • 创建角色:实战示例(部署 Apache 服务)
        • 调用角色:在 Playbook 中使用角色
        • 角色依赖:一个角色依赖另一个角色
        • 任务执行顺序:pre_tasks、roles、tasks、post_tasks
        • Handlers 执行顺序:何时触发处理程序?
        • include_role 和 import_role:在任务中动态调用角色
      • Ansible 角色优势与开发最佳实践
        • 优势
        • 开发最佳实践
      • 使用系统角色(以 RHEL 为例)
        • 系统角色介绍
        • 安装与查看
        • 案例 1:用 timesync 角色配置时间同步
        • 案例 2:用 selinux 角色配置 SELinux
      • 使用 Ansible Galaxy 获取公共角色
        • 常用`ansible-galaxy`命令
        • 实战:用 Galaxy 角色部署 Web 集群

实验环境准备

操作流程

  1. 创建工作目录并进入
  2. 配置 Ansible 全局设置(ansible.cfg
  3. 定义主机清单(inventory
# 创建名为web的工作目录并进入
[bq@controller ~]$ mkdir web && cd web# 创建Ansible配置文件ansible.cfg,定义默认参数
[bq@controller web]$ cat > ansible.cfg <<'EOF'
[defaults]
remote_user = bq               # 默认远程登录用户为bq
inventory = ./inventory        # 指定inventory文件路径为当前目录下的inventory[privilege_escalation]
become = True                  # 允许提权(切换到root)
become_user = root             # 提权目标用户为root
become_method = sudo           # 提权方式为sudo
become_ask_pass = False        # 提权时不询问密码(需提前配置sudo免密)
EOF# 创建主机清单文件,定义需要管理的主机
[bq@controller web]$ cat > inventory <<'EOF'
controller  # 控制节点
node1       # 被控节点1
node2       # 被控节点2
node3       # 被控节点3
node4       # 被控节点4
EOF

Ansible 角色

角色介绍:为什么需要角色?

在实际工作中,我们编写的 Playbook 会越来越复杂:可能包含几十甚至上百个任务,还会引用各种文件、模板和变量。如果每次部署类似服务(比如 Web 服务器、数据库)都重新写一遍 Playbook,不仅效率低,还容易出错。

Ansible 角色就是为解决这个问题而生的:它把部署一个服务所需的所有任务、变量、文件、模板等资源,按标准化的目录结构打包。这样一来,我们可以把角色复制到不同项目中,直接调用即可,大大提高了代码的复用性和可维护性。

角色结构:标准化的目录布局

Ansible 角色有固定的目录结构,通过ansible-galaxy init命令可以自动创建。我们先看一个示例:

# 初始化一个名为bq的角色(自动创建标准目录结构)
[bq@controller web]$ ansible-galaxy init bq
- bq was created successfully# 查看角色的目录结构
[bq@controller web]$ tree bq
bq
├── defaults          # 角色默认变量(优先级低,可被覆盖)
│   └── main.yml
├── files             # 静态文件(如配置文件、脚本等,可被任务直接引用)
├── handlers          # 处理程序(如服务重启等,由任务触发)
│   └── main.yml
├── meta              # 角色元信息(作者、依赖、支持的平台等)
│   └── main.yml
├── README.md         # 角色说明文档(用途、用法、依赖等)
├── tasks             # 核心任务(角色的主要操作,如安装、配置等)
│   └── main.yml
├── templates         # Jinja2模板文件(动态生成配置文件,带变量)
├── tests             # 测试相关(测试用的inventory和Playbook)
│   ├── inventory
│   └── test.yml
└── vars              # 角色内部变量(优先级高,不建议在Playbook中修改)└── main.yml8 directories, 8 files

各目录作用详解

  • defaults/main.yml:默认变量,几乎所有其他变量(如清单变量、Playbook 中的 vars)都能覆盖它。适合作为 “可自定义的参数”,比如 Web 服务的默认端口。
  • files:存放静态文件(如固定内容的配置文件),任务中引用时无需写路径,Ansible 会自动在这里查找。
  • handlers/main.yml:处理程序,比如 “重启 Apache”“重载 Nginx” 等操作,由任务通过notify触发。
  • meta/main.yml:元信息,包括作者、支持的操作系统(如 CentOS、Ubuntu)、角色依赖(如部署 Web 服务前需要先部署防火墙)等。
  • tasks/main.yml:核心任务集合,定义角色要执行的操作(如安装软件、启动服务、复制文件等)。
  • templates:存放 Jinja2 模板(文件名通常以.j2结尾),可通过变量动态生成配置文件(如根据主机名生成不同的虚拟主机配置)。
  • vars/main.yml:角色内部变量,优先级较高(仅低于事实变量、注册变量等),用于角色内部逻辑,不建议在外部修改。
角色存放位置:Ansible 去哪里找角色?

Ansible 默认会从以下目录查找角色(优先级从高到低):

  1. ~/.ansible/roles(当前用户的角色目录)
  2. /usr/share/ansible/roles(系统级共享角色目录)
  3. /etc/ansible/roles(系统默认角色目录)

如果想自定义角色路径,可以在ansible.cfg中通过roles_path设置:

[defaults]
# 多个路径用冒号分隔,Ansible会按顺序查找
roles_path = ./roles:/etc/ansible/roles/custom
创建角色:实战示例(部署 Apache 服务)

实验流程

  1. 创建roles目录(统一存放角色)
  2. 初始化apache角色
  3. 配置角色的核心文件(任务、变量、模板、处理程序等)
  4. 编写 Playbook 调用角色
  5. 执行并验证结果

步骤细化

  1. 创建角色目录并初始化apache角色
# 创建roles目录(用于存放所有角色)
[bq@controller web]$ mkdir roles# 初始化apache角色,并指定存放路径为./roles
[bq@controller web]$ ansible-galaxy init apache --init-path=./roles
- apache was created successfully# 进入apache角色目录,准备配置文件
[bq@controller web]$ cd roles/apache/
  1. 配置tasks/main.yml(核心任务)
    任务定义了角色要执行的操作:安装 Apache、启动服务、生成配置文件等。
---
# tasks file for apache:部署Apache服务的核心任务# 安装Web服务软件(包名通过变量web_package指定)
- name: install web serveryum:name: "{{ web_package }}"  # 引用变量(默认值在defaults中定义)state: latest              # 确保安装最新版本# 启动Web服务并设置开机自启
- name: start and enable web serviceservice:name: "{{ web_service }}"  # 服务名通过变量web_service指定state: started             # 确保服务处于启动状态enabled: yes               # 开机自启# 生成/etc/motd文件(登录提示,用模板动态生成)
- name: generate motd filetemplate:src: motd.j2               # 模板文件(位于templates目录)dest: /etc/motd            # 目标路径# 生成Apache虚拟主机配置文件
- name: generate virtual host configtemplate:src: bq.conf.j2            # 虚拟主机模板dest: /etc/httpd/conf.d/bq.conf  # Apache额外配置目录notify:                      # 配置文件变化时,触发处理程序- restart_web              # 重启Web服务(在handlers中定义)# 创建网站根目录(路径包含当前主机名,确保每个主机独立)
- name: create document rootfile:path: "/var/www/html/{{ ansible_hostname }}"  # ansible_hostname是facts变量(主机名)state: directory           # 确保目录存在mode: '0755'               # 权限设置# 生成网站首页(动态显示主机名)
- name: generate index.htmltemplate:src: index.html.j2         # 首页模板dest: "/var/www/html/{{ ansible_hostname }}/index.html"
  1. 配置defaults/main.yml(默认变量)
    定义可自定义的变量,比如 Web 服务的包名和服务名(默认是httpd,如需部署 Nginx 可在此修改)。
---
# defaults file for apache:可自定义的默认变量
web_package: httpd  # Web服务软件包名(如httpd、nginx)
web_service: httpd  # Web服务名(需与包名对应)
  1. 配置templates目录下的模板文件
    模板文件用于动态生成配置,这里以 3 个关键模板为例:
  • templates/motd.j2(登录提示模板):
hello guys!
Welcome to {{ ansible_fqdn }}!  # ansible_fqdn是facts变量(主机全名)
  • templates/bq.conf.j2(Apache 虚拟主机模板):
# {{ ansible_managed }}  # 标记此文件由Ansible管理
<VirtualHost *:80>ServerAdmin bq@{{ ansible_fqdn }}  # 管理员邮箱(包含主机名)ServerName {{ ansible_fqdn }}      # 虚拟主机域名ErrorLog logs/{{ ansible_hostname }}-error.log  # 错误日志路径(含主机名)CustomLog logs/{{ ansible_hostname }}-common.log common  # 访问日志路径DocumentRoot /var/www/html/{{ ansible_hostname }}/  # 网站根目录<Directory /var/www/html/{{ ansible_hostname }}/>Options +Indexes +FollowSymlinks +Includes  # 目录选项Order allow,denyAllow from all  # 允许所有IP访问</Directory>
</VirtualHost>
  • templates/index.html.j2(网站首页模板):
Welcome to {{ ansible_fqdn }} !  # 显示主机全名
  1. 配置handlers/main.yml(处理程序)
    定义需要被任务触发的操作(如配置文件更新后重启服务)。
---
# handlers file for apache:处理程序(由任务notify触发)
- name: restart_web  # 处理程序名称(需与tasks中的notify对应)service:name: "{{ web_service }}"  # 服务名(引用变量)state: restarted           # 重启服务
  1. 配置meta/main.yml(元信息)
    说明角色的作者、支持的平台、标签等(方便其他人理解和使用)。
---
galaxy_info:author: bq                    # 作者description: Deploy Apache web server  # 角色描述company: bq world             # 公司/组织license: GPLv2                # 许可证min_ansible_version: 2.4      # 最低支持的Ansible版本platforms:                    # 支持的操作系统- name: Fedoraversions:- all- 25galaxy_tags: [apache, web]    # 标签(方便搜索)
dependencies: []                # 角色依赖(暂时为空)
调用角色:在 Playbook 中使用角色

角色配置完成后,只需在 Playbook 中通过roles关键字调用即可。

示例 Playbook(deploy_apache.yml

---
- name: deploy apache web server  # Play名称hosts: node1                   # 目标主机(部署到node1)roles:- apache                     # 调用apache角色(从roles目录查找)

执行与验证

# 执行Playbook
[bq@controller web]$ ansible-playbook deploy_apache.yml# 验证1:登录node1,查看motd(登录提示)
[bq@controller web]$ ssh root@node1
# 预期输出:
hello guys!
Welcome to node1.lab.example.com!  # 显示node1的主机全名# 验证2:访问Web服务(node1的首页)
[root@node1 ~]# curl http://node1/
# 预期输出:
Welcome to node1.bq.cloud !  # 显示node1的主机全名
角色依赖:一个角色依赖另一个角色

场景:部署 Web 服务时,需要先确保防火墙放行 80 端口。这时可以让apache角色依赖firewall角色,实现自动部署防火墙并配置规则。

实验流程

  1. 修改apache角色的元信息,添加对firewall角色的依赖
  2. 创建firewall角色,配置其任务和默认变量
  3. 执行 Playbook,验证依赖是否生效(防火墙自动配置并放行 http)

步骤细化

  1. 配置apache角色的依赖(roles/apache/meta/main.yml
---
galaxy_info:# 省略其他配置...
dependencies:- role: firewall  # 依赖firewall角色service: http   # 传递变量给firewall角色(放行http服务)
  1. 创建firewall角色并配置
# 初始化firewall角色,存放于roles目录
[bq@controller web]$ ansible-galaxy init firewall --init-path=./roles
- firewall was created successfully# 进入firewall角色目录
[bq@controller web]$ cd roles/firewall/
  • 配置tasks/main.yml(防火墙任务):
---
# tasks file for firewall:配置防火墙并放行指定服务# 安装firewalld软件
- name: install firewalldyum:name: firewalldstate: latest# 启动firewalld并设置开机自启
- name: start and enable firewalldservice:name: firewalldstate: startedenabled: true# 放行指定服务(服务名通过变量service传递)
- name: allow service through firewallfirewalld:state: enabled       # 永久生效immediate: true      # 立即生效(无需重启服务)permanent: true      # 永久配置(重启后不失效)service: "{{ service }}"  # 服务名(从依赖传递的变量)
  • 配置defaults/main.yml(防火墙默认变量):
---
# defaults file for firewall:默认放行ssh服务(如未传递变量则使用此值)
service: ssh
  1. 验证依赖效果
    再次执行部署apache角色的 Playbook,Ansible 会先自动执行firewall角色,再执行apache角色:
# 执行Playbook
[bq@controller web]$ ansible-playbook deploy_apache.yml# 验证:查看node1的防火墙规则,确认http服务已放行
[bq@controller web]$ ansible node1 -m shell -a "firewall-cmd --list-services"
# 预期输出包含http
任务执行顺序:pre_tasks、roles、tasks、post_tasks

Ansible 中,任务的执行顺序是固定的,与 Playbook 中编写的顺序无关:

  1. pre_tasks:在角色执行前运行的任务
  2. roles:角色中的任务
  3. tasks:Playbook 中直接定义的任务
  4. post_tasks:在所有任务和角色执行后运行的任务

实验验证

  1. 创建测试角色test_task_exec_order
# 初始化角色
[bq@controller web]$ ansible-galaxy init test_task_exec_order --init-path=roles# 配置角色任务(roles/test_task_exec_order/tasks/main.yml)
[bq@controller web]$ vim roles/test_task_exec_order/tasks/main.yml
---
# 角色中的任务:输出提示信息
- name: task in roleshell: echo 'task in role'
  1. 编写测试 Playbook(test_order.yml
---
- name: test task execute order  # 测试任务执行顺序hosts: node1gather_facts: false  # 关闭facts收集(简化输出)pre_tasks:- name: task in pre_tasksshell: echo 'task in pre_tasks'  # 输出pre_tasks提示roles:- test_task_exec_order  # 调用测试角色tasks:- name: task in tasksshell: echo 'task in tasks'  # 输出tasks提示post_tasks:- name: task in post_tasksshell: echo 'task in post_tasks'  # 输出post_tasks提示
  1. 执行并查看顺序
[bq@controller web]$ ansible-playbook test_order.yml
# 预期输出顺序:
# task in pre_tasks → task in role → task in tasks → task in post_tasks
Handlers 执行顺序:何时触发处理程序?

处理程序(Handlers)的执行顺序与任务阶段相关,规则如下:

  1. 执行pre_tasks → 触发pre_tasks中的 Handlers
  2. 执行roles → 执行tasks
  3. 触发rolestasks中的 Handlers
  4. 执行post_tasks → 触发post_tasks中的 Handlers

实验验证

  1. 修改测试角色,添加 Handlers(roles/test_task_exec_order/handlers/main.yml
---
# 角色中的处理程序
- name: role_handlershell: echo 'handle in role'
  1. 修改角色任务,触发 Handlers(roles/test_task_exec_order/tasks/main.yml
---
- name: task in roleshell: echo 'task in role'notify:  # 触发角色中的处理程序- role_handler
  1. 编写测试 Playbook(test_handler_order.yml
---
- name: test handler execute orderhosts: node1gather_facts: falsepre_tasks:- name: task in pre_tasksshell: echo 'task in pre_tasks'notify: iamhandler  # 触发全局Handlersroles:- test_task_exec_order  # 角色任务会触发role_handlertasks:- name: task in tasksshell: echo 'task in tasks'notify: iamhandler  # 触发全局Handlerspost_tasks:- name: task in post_tasksshell: echo 'task in post_tasks'notify: iamhandler  # 触发全局Handlershandlers:  # 全局处理程序- name: iamhandlershell: echo 'iamhandler'
  1. 执行并查看顺序
[bq@controller web]$ ansible-playbook test_handler_order.yml
# 预期输出顺序:
# 1. task in pre_tasks → 2. iamhandler(pre_tasks触发)
# 3. task in role → 4. task in tasks
# 5. role_handler(角色触发) → 6. iamhandler(tasks触发)
# 7. task in post_tasks → 8. iamhandler(post_tasks触发)
include_role 和 import_role:在任务中动态调用角色

这两个模块用于在tasks中调用角色(而非直接在roles中定义),支持when条件判断,灵活度更高。

  • import_role:在 Playbook 解析阶段加载角色(类似 “静态导入”),即使when条件为false,也会先解析角色(若角色有语法错误,会直接报错)。
  • include_role:在任务执行到此时才加载角色(类似 “动态导入”),若when条件为false,则不会解析角色。

示例

---
- hosts: node1tasks:- shell: echo 'first task'  # 第一个任务- name: use role in tasksimport_role:  # 或include_rolename: hello  # 调用hello角色when: ansible_hostname == 'node1'  # 仅在node1上执行

Ansible 角色优势与开发最佳实践

优势
  • 代码复用:一次编写,多处调用(如部署多个 Web 服务器时直接复用同一角色)。
  • 并行开发:不同管理员可分别开发不同角色(如一人写数据库角色,一人写 Web 角色)。
  • 易于维护:角色结构标准化,便于多人协作和后期修改。
开发最佳实践
  1. 不存储敏感信息:密码、SSH 密钥等敏感数据应通过变量传递(如用 Ansible Vault 加密),而非硬编码到角色中。
  2. 精简目录:用ansible-galaxy init创建角色后,删除不需要的目录(如无需测试可删除tests)。
  3. 完善文档:维护README.md(说明用法)和meta/main.yml(说明作者、依赖等)。
  4. 功能单一:一个角色专注于一件事(如 “部署 Apache” 而非 “部署 Apache+MySQL+PHP”)。
  5. 避免重复:优先重构现有角色以支持新场景,而非创建新角色。

使用系统角色(以 RHEL 为例)

系统角色介绍

RHEL 系统提供了rhel-system-roles软件包,包含标准化的 Ansible 角色(如时间同步、SELinux 配置等),可跨 RHEL 6/7/8 版本使用,无需担心不同版本的配置差异。

安装与查看
# 安装系统角色
[bq@controller ~]$ sudo yum install -y rhel-system-roles# 系统角色存放路径(Ansible默认会搜索此目录)
[bq@controller ~]$ ls -1 /usr/share/ansible/roles/# 查看角色文档(每个角色的用法和变量说明)
[bq@controller ~]$ ls /usr/share/doc/rhel-system-roles/
案例 1:用 timesync 角色配置时间同步

rhel-system-roles.timesync角色可统一配置 NTP 时间同步,支持 RHEL 各版本。

Playbook 示例

---
- name: configure time synchronizationhosts: node1vars:# 指定NTP服务器(classroom.example.com),启用快速同步(iburst: yes)timesync_ntp_servers:- hostname: classroom.example.comiburst: yestimezone: "Asia/Shanghai"  # 设置时区为上海roles:- rhel-system-roles.timesync  # 调用时间同步角色tasks:# 额外任务:设置时区- name: set timezonetimezone:name: "{{ timezone }}"
案例 2:用 selinux 角色配置 SELinux

rhel-system-roles.selinux角色可简化 SELinux 配置(如模式切换、布尔值设置等)。

Playbook 示例

---
- hosts: node1vars:selinux_state: permissive  # 设置SELinux为宽容模式(仅记录不阻止)# 启用httpd访问家目录的布尔值selinux_booleans:- name: 'httpd_enable_homedirs'state: 'on'persistent: 'yes'  # 永久生效# 设置/srv/www目录的SELinux上下文为httpd_sys_content_t(Web内容)selinux_fcontexts:- target: '/srv/www(/.*)?'setype: 'httpd_sys_content_t'state: 'present'# 对/srv/www目录执行restorecon(恢复SELinux上下文)selinux_restore_dirs:- /srv/www# 允许TCP 82端口使用http_port_t类型(支持HTTP服务)selinux_ports:- ports: '82'setype: 'http_port_t'proto: 'tcp'state: 'present'roles:- rhel-system-roles.selinux  # 调用SELinux角色

使用 Ansible Galaxy 获取公共角色

Ansible Galaxy(galaxy.ansible.com)是社区维护的角色仓库,提供大量现成角色(如部署 Docker、Nginx 等),可直接下载使用。

常用ansible-galaxy命令
命令作用
ansible-galaxy list查看本地已安装的角色
ansible-galaxy search 关键词搜索 Galaxy 仓库中的角色
ansible-galaxy info 角色名查看角色详情(作者、用法等)
ansible-galaxy install 角色名安装角色到本地
实战:用 Galaxy 角色部署 Web 集群

需求

  • node3 作为负载均衡器(haproxy)
  • node1 和 node2 作为 Web 服务器(apache)

实验流程

  1. 配置主机清单,区分负载均衡器和 Web 服务器
  2. 从 Galaxy 下载geerlingguy.haproxy(负载均衡)和geerlingguy.apache(Web 服务)角色
  3. 编写 Playbook,分别部署负载均衡器和 Web 服务器
  4. 执行并验证集群效果

步骤细化

  1. 配置主机清单(inventory
[loadbalancers]
loadbalancer ansible_host=node3  # node3作为负载均衡器[webservers]
node1  # Web服务器1
node2  # Web服务器2
  1. 安装 Galaxy 角色
# 安装haproxy角色(用于负载均衡)
[bq@controller web]$ ansible-galaxy install geerlingguy.haproxy# 安装apache角色(用于Web服务)
[bq@controller web]$ ansible-galaxy install geerlingguy.apache
  1. 编写部署 Playbook(deploy_web_cluster.yml
---
# 第一个Play:部署负载均衡器(haproxy)
- name: deploy load balancerhosts: loadbalancersvars:# 配置haproxy后端服务器(指向node1和node2的80端口)haproxy_backend_servers:- name: node1address: 10.1.8.11:80  # node1的IP和端口- name: node2address: 10.1.8.12:80  # node2的IP和端口roles:- geerlingguy.haproxy  # 调用haproxy角色# 第二个Play:部署Web服务器(apache)
- name: deploy web servershosts: webserversroles:- geerlingguy.apache  # 调用apache角色tasks:# 生成Web首页(显示当前主机名)- name: create index.htmlcopy:content: "Welcome to {{ ansible_fqdn }}.\n"  # 动态内容dest: /var/www/html/index.html  # Apache默认首页路径
  1. 执行并验证
# 执行Playbook
[bq@controller web]$ ansible-playbook deploy_web_cluster.yaml# 测试负载均衡效果(多次访问node3,会交替显示node1和node2的页面)
[bq@controller web]$ curl http://node3/
Welcome to node1.bq.cloud.  # 第一次输出[bq@controller web]$ curl http://node3/
Welcome to node2.bq.cloud.  # 第二次输出(负载均衡生效)

如涉及版权问题,请联系作者处理!!!!!!

http://www.dtcms.com/a/497590.html

相关文章:

  • 投资公司网站模板重庆知名设计公司有哪些
  • 建站之星怎么用网站建设验收合同模板
  • 青岛网站建设多少钱济宁网站建设只要500元
  • wap自助建站济南百度推广
  • 求网站资源懂的2021佛山seo优化
  • 哪个在家做兼职网站比较好网站搜索页面设计
  • 在家做网站主任说到学校新网站的建设工作
  • 做视频网站要什么软件有哪些wordpress主题页脚添加联系信息
  • 自己做的网站如何引流怎么让百度快速收录网站
  • 专业模板建站软件首饰设计网站大全
  • 网站建设需注意的公司网站背景图片
  • 周浦做网站运营怎么做
  • 如何建一个购物网站苏州网站制作哪家好
  • 知乎免费阅读网站手机访问wordpress
  • 电商网站设计公司排名怎样做网站卖手机号
  • 微信制作网站wordpress数据库怎么添加积分
  • 网站优化升级深圳建网站培训学校
  • 建设中的网站备案期间做什沈阳网站制作公司排名
  • 如何不用域名也可以做网站源服务器发生5xx错误
  • 宁波建网站哪家好用点做虚假彩票网站判几年
  • wordpress 阅读全文seo排名优化方法
  • 南阳做网站优化公司微信商城小程序怎么做
  • 建筑工程网站搭建购物网站导航素材代码
  • 如何自己开一个网站深圳 公司网站设计
  • asp.net 大型网站开发中国建筑在线网
  • DPO数学原理
  • 门户网站样式高级软件开发培训班
  • 网站建设开票名称怎么写广告创意设计视频
  • 购物网站二级店铺mvc网络改造实施方案
  • 网站开发的发展历史及趋势货源网