Java web应用性能分析服务端慢之Nginx慢

        一般Nginx作为整个应用的入口,即做静态服务器,也做负载均衡、反向代理;同时也因为位置靠前,还可以通过Nginx对于访问的IP、并发数进行相应的限制。在Java web应用性能分析中,Nginx是重要环节,Nginx的性能也影响整个应用。

Nginx原理

        下面我们看一下Nginx的整体架构

        Nginx 里有一个 master 进程和多个 worker 进程。master 进程并不处理网络请求,主要负责调度工作进程:加载配置、启动工作进程及非停升级。worker 进程负责处理网络请求与响应。

        master进程主要用来管理worker进程,具体包括如下4个主要功能:

  1. 接收来自外界的信号。
  2. 向各worker进程发送信号。
  3. 监控woker进程的运行状态。
  4. 当woker进程退出后(异常情况下),会自动重新启动新的woker进程。

woker进程主要用来处理基本的网络事件:

  1. 多个worker进程之间是对等且相互独立的,他们同等竞争来自客户端的请求。
  2. 一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。
  3. worker进程的个数是可以设置的,一般我们会设置与机器cpu核数一致。同时,nginx为了更好的利用多核特性,具有cpu绑定选项,我们可以将某一个进程绑定在某一个核上,这样就不会因为进程的切换带来cache的失效。

Ngnix 是如何实现高性能的?

1.事件驱动模型

        基于异步及非阻塞的事件驱动模型,可以说是 Nginx 得以获得高并发、高性能的关键因素。这一点上和 Netty 类似,底层都是使用的 BSD kqueue、Linux epoll 及 Solaris event ports。

2.多进程机制

        使用多进程的好处有两点:

  1. 进程之间不共享资源,不需要加锁,减少了使用锁对性能造成的影响,同时降低编程的复杂度,降低开发成本。
  2. 采用独立的进程,可以让进程互相之间不会影响,如果一个进程发生异常退出时,其它进程正常工作,master 进程则很快启动新的 worker 进程,确保服务不会中断,从而将风险降到最低。
3.内存池

        为了避免出现内存碎片,减少向操作系统申请内存的次数、降低各个模块的开发复杂度,Nginx 设计了简单的内存池,它的作用主要是把多次向系统申请内存的操作整合成一次,这大大减少了 CPU 资源的消耗,同时减少了内存碎片。

4.模块化设计

        高度模块化的设计是 Nginx 的架构基础。Openresty 就是在 Nginx 上引入了 lua 等第三方模块,使得扩展更加方便了。

Nginx调优

        在这里我们Nginx调优主要包括:性能调优、安全调优、以及资源管理。

        请求响应模型过程中的TCP网络消耗

1.worker工作进程调整:绑定CPU

        查看CPU核心数

user  nginx nginx;                 # 启动Nginx⼯作进程的⽤⼾和组
worker_processes  [number | auto]; # 启动Nginx⼯作进程的数量
worker_cpu_affinity 00000001 00000010 00000100 00001000;
# 将Nginx⼯作进程绑定到指定的CPU核⼼,默认Nginx是不进⾏进程绑定的,
# 绑定并不是意味着当前nginx进程独 占以⼀核⼼CPU,但是可以保证此进程不会运⾏在其他核⼼上,
# 这就极⼤减少了nginx的⼯作进程在不同的cpu核 ⼼上的来回跳转,减少了CPU对进程的资源分配与回收以及内存管理等,
#因此可以有效的提升nginx服务器的性 能。 此处CPU有四颗核心。也可写成:
#worker_cpu_affinity 0001 0010 0100 1000;

#cpu的亲和能偶使nginx对于不同的work工作进程绑定到不同的cpu上面去。就能够减少在work间不#断切换cpu,把进程通常不会在处理器之间频繁迁移,进程迁移的频率小,来减少性能损耗。
#每个 worker 的线程可以把一个 cpu 的性能发挥到极致。所以 worker 数和服务器的 cpu 数相#等是最为适宜的。设少了会浪费 cpu,设多了会造成 cpu 频繁切换上下文带来的损耗
  1. 一个master Process管理多个worker process,也就是说Nginx采用的是多进程结构,而不是多线程结构
  2. 当client发出请求(任务)时,master Process会通知管理的worker process
  3. worker process开始争抢任务,争抢到的worker process会开启连接,完成任务
  4. 每个worker都是一个独立的进程,每个进程里只有一个主线程
  5. Nginx采用了IO多路复用机制(需要在Linux环境),使用IO多路复用机制,是Nginx在使用为数不多的worker process就可以实现高并发的关键

2.事件处理模型和worker工作进程数

work_connections表示每个worker(子进程)可以创建多少个连接,
默认:work_connections:1024
最大:work_connections:65535
同时要根据系统的最大打开文件数来调整

系统的最大打开文件数>= worker_connections*worker_process
根据系统的最大打开文件数来调整,worker_connections 进程连接数量要小于等于系统的最大打开文件数
worker_connections 进程连接数量真实数量= worker_connections * worker_process

查看系统的最大打开文件数:

ulimit -a | grep "open files"

其他系统内核调整

# 配置文件/etc/sysctl.conf
sysctl -w net.ipv4.tcp_syncookies=1 # 防止一个套接字在有过多试图连接到时引起过载
sysctl -w net.core.somaxconn=1024 # 默认128,连接队列
sysctl -w net.ipv4.tcp_fin_timeout=10 # timewait 的超时时间
sysctl -w net.ipv4.tcp_tw_reuse=1 # os 直接使用 timewait的连接
sysctl -w net.ipv4.tcp_tw_recycle=0 # 回收禁用

# /etc/security/limits.conf
*               hard    nofile            204800
*               soft    nofile             204800
*               soft    core             unlimited
*               soft    stack             204800
events {
    worker_connections  1024; # 每个工作进程的最大连接数,默认值512
    multi_accept on;  # 尽可能多地接受新的连接
    use epoll;        # 选择合适的事件模型,例如epoll或kqueue
}


Nginx 事件模型对比
Nginx 的事件模型主要有两种:select、poll、epoll、kqueue、devpoll、eventport。

select:select 模型是最早期的,它在大多数操作系统上都有相同的表现。它的主要缺点是,每次调用 select 时,都需要传递所有的文件描述符集合,这使得 select 的系统调用在大量并发连接的情况下效率非常低。

poll:poll 模型在实现上是比 select 更先进的模型,它没有文件描述符的数量限制。但是,它的性能仍然不如 epoll。

epoll:epoll 是 Linux 下的一个高效的事件通知模型,它只有在有事件通知时才会唤醒进程,而且它是边缘触发,而 select 和 poll 是水平触发。

kqueue:kqueue 是 BSD 系统(包括 macOS)下的一个高效事件通知模型,它也是边缘触发。

devpoll:devpoll 是 Solaris 下的一个事件通知模型。

eventport:eventport 是 Solaris 和部分其他操作系统下的一个事件通知模型,它是边缘触发,而且是线程安全的。

在 Nginx 中,可以通过 --with-select_module、--without-select_module、--with-poll_module、--without-poll_module、--with-epoll_module、--with-kqueue_module、--with-devpoll_module 和 --with-eventport_module 这些编译参数来启用或禁用对应的事件模型。

例如,如果你想要在 Nginx 中使用 epoll 事件模型,你可以在编译 Nginx 时添加 --with-epoll_module 参数。

./configure --with-epoll_module
make
make install
在实际的生产环境中,通常会根据操作系统的不同选择不同的事件模型。例如,在 Linux 系统上,通常会选择 epoll,而在 Solaris 系统上,则会选择 devpoll 或 eventport。

注意:在 Nginx 中,默认情况下会自动选择最适合当前操作系统的事件模型。
3.开启gzip压缩

        启用Nginx的gzip模块可以压缩响应内容,减少网络传输数据量,提高性能。可以使用gzip on指令启用压缩功能。


gzip on;
gzip_min_length 1k;
gzip_comp_level 9;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";

释义如下:
这是用来配置 gzip 压缩的。gzip 是一种用于压缩文件的压缩程序,在 Web 开发中被广泛应用,主要用于压缩 Web 应用的静态资源以减少传输流量,提高网页的加载速度。
gzip on;:启用 gzip 压缩。
gzip_min_length 1k;:指定压缩文件的最小长度,只有文件大小超过 1KB 时才启用压缩。
gzip_comp_level 9;:指定压缩级别。级别越高,压缩效率越高,但会占用更多的 CPU 资源和时间。一般建议将级别设置为 6-9 之间。(这里根据你的服务器来定)
gzip_types:指定需要压缩的文件类型。在这里,配置文件将 text、application 和 image 类型的文件压缩。一般来说,压缩的文件类型应该是纯文本格式或可压缩的二进制文件。
gzip_vary on;:使用 Vary 头来指示代理服务器或浏览器缓存已压缩的版本。这样,更高效的压缩格式可以分别缓存,并在请求时正确地使用。
gzip_disable "MSIE [1-6].";:禁用 gzip 压缩的浏览器,例如早期版本的 Internet Explorer。这些浏览器对于压缩格式的支持很差,因此禁用压缩可以避免出现问题。(这一步避免版本低浏览器访问网页出现问题)

4.配置静态文件缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires 30d;
}
5.限制连接速率
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;
server {
    ...
    location / {
        limit_req zone=mylimit;
        ...
    }
}
6.保持连接时间

keepalive_timeout 65;

        keepalive就是建立一下长连接,这个timeout就是,当浏览器建立一个连接之后,这个连接最长能存在多少事件不给他关闭,这个65也不是说建立65s连接后就直接关闭,而是一个活跃事件,就是第一次请求和下一次请求都会刷新这个65s,再65s内没有再请求数据才会真的关闭这个连接,所以这个事件也不应该太长,60左右也差不多了。
 

7.配置超时时间

client_body_timeout 12;
send_timeout 10;

- keepalived_timeout :客户端连接保持会话超时时间,超过这个时间,服务器断开这个链接。
- tcp_nodelay:也是防止网络阻塞,不过要包涵在keepalived参数才有效。
- client_header_buffer_size 4k:客户端请求头部的缓冲区大小,这个可以根据你的系统分页大小来设置,一般一个请求头的大小不会超过 1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。分页大小可以用命令getconf PAGESIZE取得。
- open_file_cache max=102400 inactive=20s :这个将为打开文件指定缓存,默认是没有启用的,max指定缓存数量,建议和打开文件数一致,inactive 是指经过多长时间文件没被请求后删除缓存。
- open_file_cache_valid 30s:这个是指多长时间检查一次缓存的有效信息。
- open_file_cache_min_uses 1 :open_file_cache指令中的inactive 参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个文件在inactive 时间内一次没被使用,它将被移除。
- client_header_timeout :设置请求头的超时时间。我们也可以把这个设置低些,如果超过这个时间没有发送任何数据,nginx将返回request time out的错误。
- client_body_timeout设置请求体的超时时间。我们也可以把这个设置低些,超过这个时间没有发送任何数据,和上面一样的错误提示。
- reset_timeout_connection :告诉nginx关闭不响应的客户端连接。这将会释放那个客户端所占有的内存空间。
- send_timeout :响应客户端超时时间,这个超时时间仅限于两个活动之间的时间,如果超过这个时间,客户端没有任何活动,nginx关闭连接。
- server_tokens :并不会让nginx执行的速度更快,但它可以关闭在错误页面中的nginx版本数字,这样对于安全性是有好处的。
- client_max_body_size:上传文件大小限制。

proxy_connect_timeout 90; #后端服务器连接的超时时间,发起握手等候响应超时时间
proxy_send_timeout 90;  #后端服务器数据回传时间,就是在规定时间内后端服务器必须传完所有的数据
proxy_read_timeout 90;  #连接成功后,等候后端服务器响应时间,其实已经进入后端的排队之中等候处理(也可以说是后端服务器处理请求的时间,页面等待服务器响应时间)
proxy_buffers 4 32k;  #4是数量 32k是大小 该指令设置缓存区的大小和数量,从被代理的后端服务器取得的第一部分响应内容,会放置到这里,默认情况下,一个缓存区的大小等于内存页面大小,可能是4k也可能是8k取决于平台
proxy_busy_buffers_size 64k; #nginx在收到服务器数据后,会分配一部分缓冲区来用于向客户端发送数据,这个缓存区大小由proxy_busy_buffers_size决定的。大小通常是proxy_buffers单位大小的两倍,官网默认是8k/16k。



keepalive_timeout 60;
keepalive_requests 100;
tcp_nodelay on;
client_header_buffer_size 4k;
open_file_cache max=102400 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 1;
client_header_timeout 15;
client_body_timeout 15;
reset_timedout_connection on;
send_timeout 15;
server_tokens off;
client_max_body_size 10m;

这两个配置参数是用来设置服务器的 keepalive 功能的。
keepalive_timeout: 这个参数指定了一个已经建立的连接在没有活动(无数据传输)时保持的时间长度。对于每个连接,如果超过 keepalive_timeout 时间没有数据传输,则服务器会关闭该连接。默认值通常为 75 秒。较小的值可以确保连接及时释放,但会增加连接关闭和重新建立的频率;较大的值可以减少连接关闭和重新建立的频率,但可能会导致长时间的闲置连接占用服务器资源。
keepalive_requests: 这个参数定义了一个 keepalive 连接上最多能够处理的请求次数。当一个 keepalive 连接处理了 keepalive_requests 次请求之后,服务器会关闭该连接。默认值通常为 100。较大的值可以减少连接的关闭和重新建立,但在某些情况下可能会占用过多的服务器资源。
8.启用TCP缓冲

        通过调整tcp_nodelay和tcp_nopush指令可以启用TCP缓冲,从而提高性能。这些指令可以确保Nginx等待足够的数据量再发送给客户端,从而减少TCP连接的数量,提高传输效率。

9.配置缓存

        启用Nginx的缓存可以显著提高性能。可以使用proxy_cache_path指令在Nginx中配置缓存目录。启用缓存后,Nginx会在第一次请求时将响应存储在缓存中,以便在后续请求中快速提供响应。

        往nginx.conf 的 http内容段落中加入

proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m;

释义如下:

/path/to/cache 是指定的缓存存储路径。

levels=1:2 指定了文件系统中缓存目录的层级结构,这里是一级目录和两级子目录。

keys_zone=my_cache:10m 定义了一个名为 my_cache 的缓存区域,大小为 10 兆字节。

max_size=10g 指定了缓存最大可使用的空间大小为 10 GB。

inactive=60m 表示缓存文件在60m时间内没有被访问时,会被视为不活动,并有可能被清理掉。

10.开启高效传输模式
http {
  include mime.types;
  default_type application/octet-stream;
  ……

  sendfile on;
  tcp_nopush on;
  ……
}
- Include mime.types :媒体类型,include 只是一个在当前文件中包含另一个文件内容的指令。
- default_type application/octet-stream :默认媒体类型足够。
- sendfile on:开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。
- tcp_nopush on:必须在sendfile开启模式才有效,防止网路阻塞,积极的减少网络报文段的数量(将响应头和正文的开始部分一起发送,而不一个接一个的发送。)

11.启用HTTPS

        启用Nginx的HTTP2模块可以提高性能,因为HTTP2使用多路复用技术,可以同时发送多个请求和响应,从而提高网络传输效率。可以使用http2 on指令启用HTTP2。

12.调整缓冲区

        可以通过调整Nginx的缓冲区大小来提高性能。可以使用client_body_buffer_size、client_header_buffer_size和large_client_header_buffers等指令调整缓冲区大小。

        总的来说,Nginx性能调优需要结合服务器的硬件配置、网络环境和预期的并发连接数等因素进行综合考虑。

13.设置完整的日志格式和路径

        在后期问题排查过程中,配置完整的日志,可以快速协助定位问题。

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;
error_log /var/log/nginx/error.log warn;

14.设置Nginx监控

        Nginx 提供了一个状态页面,可以用来监控 Nginx 的运行状态。为了使用这个状态页面,你需要在 Nginx 配置中启用 stub_status 模块。

        stub_status模块参数可以用来查看Nginx的一些状态信息如连接数、请求数统计等,需要安装好相应的模块stub_status才支持配置,安装时需要指定–with-http_stub_status_module,

        比如:./configure --prefix=/usr/local/nginx  --with-http_stub_status_module
 

        以下是一个配置示例,它在 server 块中添加了一个 location 用于 Nginx 状态页面:

server {
    listen 80;
    server_name localhost;
 
    location /nginx_status {
        stub_status on;          # 开启状态页面
        access_log   off;       # 不记录访问nginx状态的日志
        allow 127.0.0.1;       # 只允许本地访问
        deny all;              # 拒绝其他IP访问
    }
}

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

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

相关文章

Flink Job提交分析

1.概述 Flink 应用程序的提交方式为:打成jar包,通过 flink 命令来进行提交。 flink 命令脚本的底层是通过 java 命令启动:CliFrontend 类 来启动 JVM 进程,执行任务的构造和提交。 flink run xxx.jar class arg1 arg2flink.sh 脚…

Springboot+Vue项目-基于Java+MySQL的影城管理系统(附源码+演示视频+LW)

大家好!我是程序猿老A,感谢您阅读本文,欢迎一键三连哦。 💞当前专栏:Java毕业设计 精彩专栏推荐👇🏻👇🏻👇🏻 🎀 Python毕业设计 &…

Unity 新版输入系统(Input System)

前言 官方教程 注意 新的输入法系统需要 Unity 2019.4 和 .NET 4 运行时。它不适用于 .NET 3.5 的项目。 教程版本:Unity 2021.3.26 1. 安装 1.1 打开 Package Manager 导航栏 -> Window -> Package Manager 1.2 安装 Input System 选择 Unity Registry 在…

【WEB前端2024】开源元宇宙:乔布斯3D纪念馆-第8课-新增摆件

【WEB前端2024】开源元宇宙:乔布斯3D纪念馆-第8课-新增摆件 使用dtns.network德塔世界(开源的智体世界引擎),策划和设计《乔布斯超大型的开源3D纪念馆》的系列教程。dtns.network是一款主要由JavaScript编写的智体世界引擎&#…

mysql基础20——数据备份

数据备份 数据备份有2种 一种是物理备份 一种是逻辑备份 物理备份 物理备份 通过把数据文件复制出来 达到备份的目的 用得比较少 逻辑备份 逻辑备份 把描述数据库结构和内容的信息保存起来 达到备份的目的 是免费的 数据备份工具 mysqldump (3种模式&#x…

C++笔试强训day4

目录 1.游游的you 2.腐烂的苹果 3.孩子们的游戏 1.游游的you 链接: 分析题意之后,发现就是一道简单的贪心,当然也可以把他看作纯数学题。 因为you和oo里面都有o,但是you可以得两分,所以贪心策略尽可能的去凑更多的…

【嵌入式】keil5安装(同时兼容C51和STM32)

最近在开发STM32的时候,安装Keil5,遇到STM32和C51的共存的问题,在网上找了很多方法,又遇到一些bug,最终还是弄好了。因此将处理的过程记录下来,希望对遇到相同问题的朋友一些启发。 1、下载安装包 Keil P…

vue-Router 路由(常量路由)

1、安装 pnpm i vue-router 2、新建文件:src/routes.ts import { RouteRecordRaw } from vue-routerexport const constantRoute: RouteRecordRaw[] [{//path: /,redirect: /login,},{//path: /login,component: () > import(/views/Login/index.vue),name…

mysql基础6——多表查询

外键 把分散在多个不同表里面的数据查询出来的操作,就是多表查询 把两个表连接:使用外键(foreign key)和连接(join) 外键在表创建的阶段定义也可以通过修改表定义,连接在查询字段把相同意义的字段连接起来 外键就是从表中用来引用主表中数…

【MATLAB源码-第190期】基于matlab的32QAM系统相位偏移估计EOS算法仿真,对比补偿前后的星座图误码率。

操作环境: MATLAB 2022a 1、算法描述 1. 引言 M-QAM调制技术的重要性 现代通信系统追求的是更高的数据传输速率和更有效的频谱利用率。M-QAM调制技术,作为一种高效的调制方案,能够通过在相同的带宽条件下传输更多的数据位来满足这一需求…

舍得酒业陷入瓶颈期:业绩增速再放缓,股价低迷,市场信心缺失?

撰稿|行星 来源|贝多财经 被誉为“川酒六朵金花”之一的舍得酒业,混的不算好。 近日,舍得酒业股份有限公司(SH:600702,下称“舍得酒业”)披露2023年年度报告。在白酒行业活性整体趋弱的大环境下,舍得酒业…

加入新团队时,为什么你需要一个“WTF 笔记本”

原文:Nat Bennett - 2021.09.04 我有一个子弹日记。我并不是你在 Pinterest 上看到的那种用精美排版的人——大部分只使用黑色墨水,标准设置,偶尔会有自定义的集合。 每当我加入新的团队,都会翻到下一页,然后在那一页…

引用静态方法

import java.util.Arrays; import java.util.Comparator;public class demo1 {//引用public static void main(String[] args) {Integer []arr{1,2,4,3,8,6};//匿名内部类Arrays.sort(arr, new Comparator<Integer>() {Overridepublic int compare(Integer o1, Integer o…

docker 报错 error adding seccomp filter rule for syscall clone3

网上有一些说法&#xff0c;例如重新安装docker 但是我自己尝试&#xff0c;用 –security-opt seccompunconfined 就可以&#xff0c;但是需要把这个命令放到紧挨着run的位置&#xff0c;如果放到偏后的位置&#xff0c;可能不起作用。 以下命令是其他网友启动是的命令&…

是用computed获取vuex数据后,修改数据页面不响应的问题

问题描述&#xff1a; 代码里使用computed获取mapGetters的数据后&#xff0c;直接在页面使用&#xff0c;在methods中更新数据后&#xff0c;控制台打印数据已经更改&#xff0c;但是页面上的数据没有同步更改和响应。 分析&#xff1a; 1.computed是计算属性&#xff0c;所有…

匿名函数与gorm中的Transaction事务方法

整理下go中的匿名函数&#xff0c;项目中很多地方都在用。 1、函数类型的变量 Go中&#xff0c;函数也是一种数据类型。定义一个函数&#xff0c;把这个函数赋值给一个变量&#xff0c;这个变量就是函数类型的变量&#xff0c;用这个变量等价于直接调函数&#xff1a; packa…

AD高速板设计--HDMI(笔记)

HDMI的布线要求&#xff1a; 差分线对内误差为5以内&#xff0c;所有的差分线误差在10以内&#xff1a; 进行阻抗匹配需要调整线宽&#xff0c;间距和板层。 四对差分线&#xff0c;控制阻抗为100欧姆&#xff1b;四对单端信号线&#xff0c;控制阻抗为50欧姆。 \] HDMI识别过…

Redis底层数据结构之quicklist

目录 一、概述二、quicklist结构三、quicklistNode结构四、优缺点 上一篇 redis底层数据结构之ziplist 一、概述 QuickList是由多个 ziplist 组成的双向链表&#xff0c;每个 ziplist 存储一定数量的元素。优点:结合了 ziplist 和双向链表的优点&#xff0c;既节省空间&#x…

【数据结构】栈和队列(链表模拟队列)

学习本章节必须具备 单链表的前置知识&#xff0c; 建议提前学习&#xff1a;点击链接学习&#xff1a;单链表各种功能函数 细节 详解 本章节是学习用 单链表模拟队列 1. 单链表实现队列 思路如下 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数…

查询服务器上所有SQL SERVER数据库中是否包含某个字段,且该字段是否包含某个值

公司有一堆相同类别的客户&#xff0c;每个客户都部署了相同的一套系统&#xff0c;每套系统对应一个相同结构的数据库&#xff0c;昨天老板让查一下手机号码177xxxxx248是属于哪个客户的客户。 我要查的这个号码来自于oa_member表中的phone字段&#xff0c;我需要对所有的数据…
最新文章