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

ansible自动化部署考试系统前后端分离项目

1. ✅ansible编写剧本步骤

  • 1️⃣创建roles目录结构
  • 2️⃣在group_vars/all/main.yml中定义变量列表
  • 3️⃣在tasks目录下编写tasks任务
  • 4️⃣在files目录下准备部署文件
  • 5️⃣在templates目录下创建j2模板文件
  • 6️⃣在handlers目录下编写handlers
  • 7️⃣在roles目录下编写主playbook
  • 8️⃣运行主playbook
  • 9️⃣检查验证

2. 🔐部署数据库(db02)

  • 1️⃣创建roles目录结构
mkdir -p db_server/{files,templates,tasks,handlers}

  • 2️⃣在group_vars/all/main.yml中定义变量列表
db_server:ip: "172.16.1.52"basedir: /app/tools/datadir: /app/data/3306/port: 3306root_password: Lidao996user_name: examuser_password: examuser_host: "172.16.1.%"db_name: exam
  • 3️⃣在tasks目录下编写tasks任务
- name: 1.准备数据库安装目录file:path: "{{ item }}"state: directoryloop:- "{{ db_server.basedir }}"- "{{ db_server.datadir }}"- name: 2.拷贝mysql源码包copy:src: mysql-8.0.28-linux-glibc2.12-x86_64.tar.xzdest: /tmp/backup: yes- name: 3.解压mysql源码包unarchive:src: /tmp/mysql-8.0.28-linux-glibc2.12-x86_64.tar.xzdest: "{{ db_server.basedir }}"remote_src: yescreates: "{{ db_server.basedir }}mysql-8.0.28-linux-glibc2.12-x86_64/LICENSE"- name: 4.创建软链接file:path: "{{ db_server.basedir }}mysql"src: "{{ db_server.basedir }}mysql-8.0.28-linux-glibc2.12-x86_64/"state: link- name: 5.创建mysql用户user:name: mysqlshell: /sbin/nologincreate_home: nostate: present- name: 6.创建my.cnf配置文件template:src: my.cnf.j2dest: /etc/my.cnfowner: mysqlgroup: mysqlbackup: yesnotify:restart_mysqld- name: 7.修为数据库目录所有者file:path: "{{ item }}"owner: mysqlgroup: mysqlloop:- "{{ db_server.basedir }}mysql/"- "{{ db_server.datadir }}"- name: 8.配置环境变量lineinfile:path: /etc/profileline: 'export PATH=/app/tools/mysql/bin:$PATH'insertafter: EOF- name: 9.检查是否已经初始化过数据库stat:path: /tmp/init_dbregister: init_stat- name: 10.初始化数据库script: ./db_server/files/init_mysql.shwhen: not init_stat.stat.exists- name: 11.启动数据库systemd:name: mysqldenabled: yesstate: started- name: 12.安装pipyum:name:- python3-pipstate: present- name: 13.安装pymysql模块pip:name: pymysqlstate: present- name: 14.创建数据库,字符集为 utf8mb4mysql_db:name: "{{ db_server.db_name }}"encoding: utf8mb4collation: utf8mb4_unicode_cistate: presentlogin_user: rootlogin_password: ""when: not init_stat.stat.exists- name: 15.创建用户mysql_user:name: "{{ db_server.user_name }}"host: "{{ db_server.user_host }}"password: "{{ db_server.user_password }}"state: presentwhen: not init_stat.stat.exists- name: 16.授予用户权限mysql_user:name: "{{ db_server.user_name }}"host: "{{ db_server.user_host }}"priv: "{{ db_server.db_name }}.*:ALL"state: presentwhen: not init_stat.stat.exists- name: 17.上传 SQL 文件到目标主机copy:src: xzs-mysql.sqldest: /tmp/xzs-mysql.sqlwhen: not init_stat.stat.exists- name: 18.导入数据库shell: "{{ db_server.basedir }}mysql/bin/mysql -uroot exam </tmp/xzs-mysql.sql"when: not init_stat.stat.exists- name: 19.设置root密码mysql_user:name: rootpassword: "{{ db_server.root_password }}"host: localhostlogin_user: rootlogin_password: ""when: not init_stat.stat.exists- name: 20.创建标记文件表示已初始化file:path: /tmp/init_dbstate: touchmode: '0644'when: not init_stat.stat.exists
  • 4️⃣在files目录下准备部署文件
#!/bin/bash
##############################################################
# File Name:db_server/files/init_mysql.sh
# Version:V1.0
# Author:zbl
# Organization:zhubaolin.blog.csdn.net
# Desc:
##############################################################
source /etc/profile
#1.初始化数据库
mysqld --initialize-insecure --user=mysql --basedir=/app/tools/mysql/ --datadir=/app/data/3306/#2.拷贝启动管理文件到init.d
if [ -f /app/tools/mysql/support-files/mysql.server ];thencp /app/tools/mysql/support-files/mysql.server  /etc/init.d/mysqld
elseecho "file not found"exit 1
fi
#3.修改管理文件权限
chmod +x /etc/init.d/mysqld#4.修改管理文件内容
sed -i  '/^basedir=/s#basedir=#basedir=/app/tools/mysql/#g'  /etc/init.d/mysqld
sed -i  '/^datadir=/s#datadir=#datadir=/app/data/3306/#g'  /etc/init.d/mysqld#5.加载自启动服务文件
systemctl daemon-reload
  • 5️⃣在templates目录下创建j2模板文件
[mysqld]
user=mysql 
basedir={{ db_server.basedir }}mysql/
datadir={{ db_server.datadir }}
port={{ db_server.port }}
socket=/tmp/mysql.sock [client]
socket=/tmp/mysql.sock
  • 6️⃣在handlers目录下编写handlers
- name: restart_mysqldsystemd:name: mysqldstate: restarted
  • 7️⃣在roles目录下编写主playbook
- hosts: dbroles:- db_server
  • 8️⃣运行主playbook
ansible-playbook top.yml

  • 9️⃣检查验证
ansible db -m shell -a 'ps -ef | grep mysql'

3. 🚀启动jar项目(web03/web04)

  • 1️⃣创建roles目录结构
mkdir -p backend_web/{files,templates,tasks,handlers}

  • 2️⃣在group_vars/all/main.yml中定义变量列表
backend_web:ip:- "10.0.0.9"- "10.0.0.10"port: 8000site_dir: /app/code/exam/backend/host: exam
  • 3️⃣在tasks目录下编写tasks任务
- name: 1.安装jdkyum:name:- java-11-openjdk- java-11-openjdk-develstate: present- name: 2.拷贝项目文件到后端web服务器上copy:src: xzs-3.9.0.jardest: "{{ backend_web.site_dir }}"backup: yes- name: 3.拷贝配置文件到后端web服务器上template:src: application-prod.yml.j2dest: "{{ backend_web.site_dir }}application-prod.yml"backup: yes- name: 4.拷贝自启动脚本到后端web服务器上template:src: "{{ backend_web.host }}.sh.j2"dest: /server/scripts/{{ backend_web.host }}.shbackup: yes- name: 5.拷贝service服务管理文件到web服务器上template:src: "{{ backend_web.host }}.service.j2"dest: /usr/lib/systemd/system/{{ backend_web.host }}.servicebackup: yes- name: 6.重新加载systemd配置systemd:daemon_reload: yes- name: 7.启动服务,并设置下次开机启动systemd:name: "{{ backend_web.host }}"enabled: yesstate: started
  • 4️⃣在files目录下准备部署文件
xzs-3.9.0.jar
  • 5️⃣在templates目录下创建j2模板文件
  • exam.sh.j2
#!/bin/bash
##############################################################
# File Name:exam.sh
# Version:V1.0
# Author:zbl
# Organization:zhubaolin.blog.csdn.net
# Desc:
###############################################################1.vars
service=xzs-3.9.0.jar
dir={{ backend_web.site_dir }}
choose=$1
time=`date +%F_%T`
jar_file=${dir}${service}#2.function
function srv_start() {pid=`ps -ef | grep -w xzs-3.9.0 | grep -v grep | awk '{print $2}'`pidcount=`ps -ef | grep -w xzs-3.9.0 | grep -v grep | awk '{print $2}' | wc -l`if [ -f ${jar_file} ];thenif [ -z ${pid} ];thencd ${dir}nohup java -Duser.timezone=Asia/Shanghai -jar -Dspring.profiles.active=prod xzs-3.9.0.jar >/dev/null 2>&1 &fielseexitfireturn $?
}function srv_stop() {pid=`ps -ef | grep -w xzs-3.9.0 | grep -v grep | awk '{print $2}'`pidcount=`ps -ef | grep -w xzs-3.9.0 | grep -v grep | awk '{print $2}' | wc -l`if [ ${pidcount} -gt 0 ];thenkill ${pid}fireturn $?
}function srv_restart() {srv_stopsleep 1srv_start
}function srv_status() {pid=`ps -ef | grep -w xzs-3.9.0 | grep -v grep | awk '{print $2}'`pidcount=`ps -ef | grep -w xzs-3.9.0 | grep -v grep | awk '{print $2}' | wc -l`if [ ${pidcount} -ge 1 ];thenecho -e "\E[1;32mrunning pid:[${pid}] ${service}\E[0m"elseecho -e "\E[1;31mstoped ${service}\E[0m"fireturn $?
}#3.case
case "${choose}" instart) srv_start ;;stop) srv_stop ;;restart) srv_restart ;;status) srv_status ;;*) echo input error
esac
  • application-prod.yml.j2
#server后端服务的配置
server:port: {{ backend_web.port }}undertow:io-threads: 16worker-threads: 4000buffer-size: 1024direct-buffers: truecompression:enabled: truemin-response-size: 1
#日志
logging:path: {{ backend_web.site_dir }}#数据库,redis等等配置
spring:datasource:#mysql://数据库地址:端口号/库名字?url: jdbc:mysql://{{ db_server.ip }}:{{ db_server.port }}/{{ db_server.db_name }}?useSSL=false&useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowPublicKeyRetrieval=true&allowMultiQueries=trueusername: {{ db_server.user_name }}password: {{ db_server.user_password }}driver-class-name: com.mysql.cj.jdbc.Driver
  • exam.service.j2
[Unit]
Description={{ backend_web.host }}
After=network.target 
[Service]
Type=forking
#EnvironmentFile=/etc/sysconfig/tomcat
ExecStart=bash /server/scripts/{{ backend_web.host }}.sh start
ExecStop=bash /server/scripts/{{ backend_web.host }}.sh stop
[Install]
WantedBy=multi-user.target
  • 6️⃣在handlers目录下编写handlers
  • 7️⃣在roles目录下编写主playbook
- hosts: backend_webroles:- backend_web
  • 8️⃣运行主playbook
ansible-playbook top.yml

  • 9️⃣检查验证
ansible backend_web -m shell -a 'ps -ef | grep java'

4. 🍀接入4层负载均衡(lb01/lb02)

  • 1️⃣创建roles目录结构
mkdir -p backend_lb/{files,templates,tasks,handlers}

  • 2️⃣在group_vars/all/main.yml中定义变量列表
backend_lb:ip:- "10.0.0.5"- "10.0.0.6"port: 8000
  • 3️⃣在tasks目录下编写tasks任务
- name: 1.分发nginx源copy:src: nginx.repodest: /etc/yum.repos.d/backup: yes- name: 2.安装nginx软件yum:name: nginxstate: present- name: 3.分发nginx配置文件template:src: nginx.conf.j2dest: /etc/nginx/nginx.confbackup: yesnotify:reload_nginx- name: 4.启动nginx并设置下次开机启动systemd:name: nginxenabled: yesstate: started
  • 4️⃣在files目录下准备部署文件
vim backend_lb/files/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
  • 5️⃣在templates目录下创建j2模板文件
  • backend_lb/templates/nginx.conf.j2

user  nginx;
worker_processes  auto;error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;events {worker_connections  1024;
}stream {upstream exam_pools {
{% for i in backend_web.ip %}server {{ i }}:{{ backend_web.port }};
{% endfor %}hash $remote_addr consistent;}log_format basic '$remote_addr [$time_local] ''$protocol $status $bytes_sent $bytes_received ''$session_time';access_log /var/log/nginx-l4.log basic;server {listen {{ backend_lb.port }};proxy_pass exam_pools;}
}http {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;#gzip  on;include /etc/nginx/conf.d/*.conf;
}
  • 6️⃣在handlers目录下编写handlers
- name: reload_nginxsystemd:name: nginxstate: reloaded
  • 7️⃣在roles目录下编写主playbook
- hosts: lbroles:- backend_lb
  • 8️⃣运行主playbook
ansible-playbook top.yml

  • 9️⃣检查验证
ansible lb -m shell -a 'ss -lntup | grep 8000'

5. 🌏部署前端web(web01/web02)

  • 1️⃣创建roles目录结构
mkdir -p front_web/{files,templates,tasks,handlers}

  • 2️⃣在group_vars/all/main.yml中定义变量列表
front_web:ip:- "10.0.0.7"- "10.0.0.8"port: 80site_dir: /app/code/exam/front/front_host: studentbackend_host: admin
  • 3️⃣在tasks目录下编写tasks任务
- name: 1.分发nginx源copy:src: nginx.repodest: /etc/yum.repos.d/nginx.repobackup: yes- name: 2.安装nginx软件yum:name: nginxstate: present- name: 3.分发nginx配置文件template:src: exam.conf.j2dest: /etc/nginx/conf.d/exam.confbackup: yesnotify:reload_nginx- name: 4.创建站点目录file:path: "{{ front_web.site_dir }}"state: directory- name: 5.分发前端代码到前端web服务器上copy:src: exam-web.tar.gzdest: /tmp/backup: yes- name: 6.解压代码到站点目录下unarchive:src: /tmp/exam-web.tar.gzdest: "{{ front_web.site_dir }}"remote_src: yes- name: 7.启动nginx并设置开机自启动systemd:name: nginxenabled: yesstate: started
  • 4️⃣在files目录下准备部署文件
vim front_web/files/nginx.repo 
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
  • 5️⃣在templates目录下创建j2模板文件
  • front_web/templates/exam.conf.j2
server {listen {{ front_web.port }};server_name {{ front_web.front_host }}.zhubl.xyz;root  {{ front_web.site_dir }}{{ front_web.front_host }}/;location / {index index.html;}location /api/ {proxy_pass  http://{{ backend_lb.vip }}:{{ backend_lb.port }};}
}server {listen 80;server_name {{ front_web.backend_host }}.zhubl.xyz;root  {{ front_web.site_dir }}{{ front_web.backend_host }}/;location / {index index.html;}location /api/ {proxy_pass  http://{{ backend_lb.vip }}:{{ backend_lb.port }};}
}
  • 6️⃣在handlers目录下编写handlers
- name: reload_nginxsystemd:name: nginxstate: reloaded
  • 7️⃣在roles目录下编写主playbook
- hosts: front_webroles:- front_web
  • 8️⃣运行主playbook
ansible-playbook top.yml

  • 9️⃣检查验证
ansible front_web -m shell -a 'ss -lntup | grep 80'

6. 🍀接入7层负载(lb01/lb02)

  • 1️⃣创建roles目录结构
mkdir -p front_lb/{files,templates,tasks,handlers}

  • 2️⃣在group_vars/all/main.yml中定义变量列表
front_lb:ip:- "10.0.0.5"- "10.0.0.6"port: 80vip: "10.0.0.3"
  • 3️⃣在tasks目录下编写tasks任务
- name: 1.分发nginx源copy:src: nginx.repodest: /etc/yum.repos.d/backup: yes- name: 2.安装nginx软件yum:name: nginxstate: present- name: 3.分发nginx配置文件template:src: exam.conf.j2dest: /etc/nginx/conf.d/exam.confbackup: yesnotify:reload_nginx- name: 4.启动nginx并设置下次开机自启动systemd:name: nginxenabled: yesstate: started
  • 4️⃣在files目录下准备部署文件
vim front_lb/files/nginx.repo 
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
  • 5️⃣在templates目录下创建j2模板文件
  • front_lb/templates/exam.conf.j2
upstream l7_pools {
{% for i in front_web.ip %}server {{ i }}:{{ front_web.port }};
{% endfor %}hash $remote_addr consistent;
}
server {listen {{ front_lb.port }};server_name {{ front_web.front_host }}.zhubl.xyz;location / {proxy_pass http://l7_pools;proxy_set_header Host $http_host;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Real-Ip $remote_addr;}
}
server {listen {{ front_lb.port }};server_name {{ front_web.backend_host }}.zhubl.xyz;location / {proxy_pass http://l7_pools;proxy_set_header Host $http_host;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Real-Ip $remote_addr;}
}
  • 6️⃣在handlers目录下编写handlers
- name: reload_nginxsystemd:name: nginxstate: reloaded
  • 7️⃣在roles目录下编写主playbook
- hosts: lbroles:- front_lb
  • 8️⃣运行主playbook
ansible-playbook top.yml

  • 9️⃣检查验证
ansible lb -m shell -a 'ss -lntup | grep 80'

7. 🚀接入高可用(lb01/lb02)

  • 1️⃣创建roles目录结构
mkdir -p front_keepalived/{files,templates,tasks,handlers}
  • 2️⃣在group_vars/all/main.yml中定义变量列表
  • 3️⃣在tasks目录下编写tasks任务
- name: 1.安装keepalived软件yum:name: keepalivedstate: present- name: 2.获取主机名shell: hostnameregister: hostname- name: 3.分发lb01配置文件template:src: lb01.keepalived.conf.j2dest: /etc/keepalived/keepalived.confbackup: yeswhen: hostname.stdout is match("lb01")notify:restart_keepalived- name: 4.分发lb02配置文件template:src: lb02.keepalived.conf.j2dest: /etc/keepalived/keepalived.confbackup: yeswhen: hostname.stdout is match("lb02")notify:restart_keepalived- name: 5.分发监控nginx进程脚本到负载均衡copy:src: check_lb.shdest: /server/scripts/check_lb.shmode: '0755'backup: yes- name: 6.启动keepalived并设置下次开机自启动systemd:name: keepalivedenabled: yesstate: started
  • 4️⃣在files目录下准备部署文件
#!/bin/bash
##############################################################
# File Name:/server/scripts/check_lb.sh
# Version:V1.0
# Author:zbl
# Organization:zhubaolin.blog.csdn.net
# Desc:
##############################################################
#1.vars
count=`ps -ef | grep nginx | wc -l`#2.stop keepalived
if [ ${count} -eq 1 ];thensystemctl stop keepalived
fi
  • 5️⃣在templates目录下创建j2模板文件
  • front_keepalived/templates/lb01.keepalived.conf.j2
global_defs {router_id lb01
}
vrrp_script check_lb.sh {   script /server/scripts/check_lb.shinterval 2weight  1user root 
}vrrp_instance vip_3 {    state MASTER    interface ens33virtual_router_id 51 priority 100    advert_int 1        authentication {   auth_type PASSauth_pass 1111  
}
virtual_ipaddress { {{ front_lb.vip }} dev ens33 label ens33:1
}
track_script  {check_lb.sh 
}
}vrrp_instance vip_4 {state BACKUPinterface ens33virtual_router_id 52priority 50advert_int 1authentication {auth_type PASSauth_pass 1111
}
virtual_ipaddress {{{ backend_lb.vip }} dev ens33 label ens33:2
}
}
  • front_keepalived/templates/lb02.keepalived.conf.j2
global_defs {router_id lb02
}
vrrp_script check_lb.sh {script /server/scripts/check_lb.shinterval 2weight  1user root 
}vrrp_instance vip_3 {state BACKUPinterface ens33virtual_router_id 51priority 50advert_int 1authentication {auth_type PASSauth_pass 1111
}
virtual_ipaddress {{{ front_lb.vip }} dev ens33 label ens33:1
}
}vrrp_instance vip_4 {state MASTERinterface ens33virtual_router_id 52priority 100advert_int 1authentication {auth_type PASSauth_pass 1111
}
virtual_ipaddress {{{ backend_lb.vip }} dev ens33 label ens33:2
}
track_script  {check_lb.sh
}
}
  • 6️⃣在handlers目录下编写handlers
- name: restart_keepalivedsystemd:name: keepalivedstate: restarted
  • 7️⃣在roles目录下编写主playbook
- hosts: lbroles:- keepalived
  • 8️⃣运行主playbook
ansible-playbook top.yml
  • 9️⃣检查验证

8. 🌏浏览器访问

9. ✅总结

9.1. 🌟总变量

db_server:ip: "172.16.1.52"basedir: /app/tools/datadir: /app/data/3306/port: 3306root_password: Lidao996user_name: examuser_password: examuser_host: "172.16.1.%"db_name: examfront_web:ip:- "10.0.0.7"- "10.0.0.8"port: 80site_dir: /app/code/exam/front/front_host: studentbackend_host: adminbackend_web:ip:- "10.0.0.9"- "10.0.0.10"port: 8000site_dir: /app/code/exam/backend/host: exambackend_lb:ip:- "10.0.0.5"- "10.0.0.6"port: 8000vip: "10.0.0.4"front_lb:ip:- "10.0.0.5"- "10.0.0.6"port: 80vip: "10.0.0.3"

9.2. 🌟总roles

[root@m02 /server/ansible/roles]# tree -F 
.
├── ansible.cfg
├── backend_lb/
│   ├── files/
│   │   └── nginx.repo
│   ├── handlers/
│   │   └── main.yml
│   ├── tasks/
│   │   └── main.yml
│   └── templates/
│       └── nginx.conf.j2
├── backend_web/
│   ├── files/
│   │   └── xzs-3.9.0.jar
│   ├── handlers/
│   ├── tasks/
│   │   └── main.yml
│   └── templates/
│       ├── application-prod.yml.j2
│       ├── exam.service.j2
│       └── exam.sh.j2
├── db_server/
│   ├── files/
│   │   ├── init_mysql.sh*
│   │   ├── mysql-8.0.28-linux-glibc2.12-x86_64.tar.xz
│   │   └── xzs-mysql.sql
│   ├── handlers/
│   │   └── main.yml
│   ├── tasks/
│   │   └── main.yml
│   └── templates/
│       └── my.cnf.j2
├── front_lb/
│   ├── files/
│   │   └── nginx.repo
│   ├── handlers/
│   │   └── main.yml
│   ├── tasks/
│   │   └── main.yml
│   └── templates/
│       └── exam.conf.j2
├── front_web/
│   ├── files/
│   │   ├── exam-web.tar.gz
│   │   └── nginx.repo
│   ├── handlers/
│   │   └── main.yml
│   ├── tasks/
│   │   └── main.yml
│   └── templates/
│       └── exam.conf.j2
├── group_vars/
│   └── all/
│       └── main.yml
├── hosts
├── keepalived/
│   ├── files/
│   │   └── check_lb.sh
│   ├── handlers/
│   │   └── main.yml
│   ├── tasks/
│   │   └── main.yml
│   └── templates/
│       ├── lb01.keepalived.conf.j2
│       └── lb02.keepalived.conf.j2
└── top.yml32 directories, 33 files

9.3. 🌟总剧本

- hosts: dbroles:- db_server- hosts: backend_webroles:- backend_web- hosts: lbroles:- backend_lb- hosts: front_webroles:- front_web- hosts: lbroles:- front_lb- keepalived

http://www.xdnf.cn/news/15265.html

相关文章:

  • C++ 强制类型转换
  • 前端性能优化利器:懒加载技术原理与最佳实践
  • QuickUnion优化及Huffman树
  • flask校园学科竞赛管理系统-计算机毕业设计源码12876
  • 使用docker的常用命令
  • 【C++】第十五节—一文详解 | 继承
  • 接入Deepseek的AI截图全能王—截图、录屏剪辑的工具,支持AI OCR / 识图 /翻译
  • Vue3 Diff 算法片段解析:新旧节点队列之乱序比对与更新策略
  • Java使用Langchai4j接入AI大模型的简单使用(五)--流式输出的实现
  • 设计模式之单例模式:深入解析全局唯一对象的艺术
  • STM32-第五节-TIM定时器-1(定时器中断)
  • F-GNN的新型检测框架:随机森林增强图神经网络
  • Python 数据建模与分析项目实战预备 Day 4 - EDA(探索性数据分析)与可视化
  • 音视频学习(三十七):pts和dts
  • 香港理工大学实验室定时预约
  • php生成二维码
  • Java网络编程
  • ref 和 reactive
  • 详解Linux下多进程与多线程通信(一)
  • Kafka——Kafka 线上集群部署方案怎么做?
  • 解决 Python 跨目录导入模块问题
  • git实际工作流程
  • Java 大视界 -- Java 大数据在智能教育学习资源智能分类与标签优化中的应用(346)
  • [2025CVPR]DenoiseCP-Net:恶劣天气下基于LiDAR的高效集体感知模型
  • 若依框架集成阿里云OSS实现文件上传优化
  • 基于requests_html的爬虫实战
  • 「小程序开发」项目结构和页面组成
  • java: DDD using oracle 21c
  • 多级@JsonTypeInfo和@JsonSubTypes注解使用详解及场景分析
  • opencv python 基本操作