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

Nginx Web服务器管理、均衡负载、访问控制与跨域问题

Nginx Web 服务器的均衡负载、访问控制与跨域问题


Nginx 的配置

1. 安装Nginx

首先安装Nginx

apt install nginx -y
cacc@purgatory-v:~$ sudo apt install nginx
[sudo] password for cacc:
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:iproute2 libatm1 libbpf0 libcap2-bin libdeflate0 libelf1 libgd3 libjbig0 libmaxminddb0 libmnl0 libnginx-mod-http-geoip2libnginx-mod-http-image-filter libnginx-mod-http-xslt-filter libnginx-mod-mail libnginx-mod-streamlibnginx-mod-stream-geoip2 libpam-cap libpam-runtime libtiff5 libwebp7 libx11-6 libx11-data libxau6 libxcb1 libxdmcp6libxpm4 libxslt1.1 libxtables12 nginx-common nginx-core
Suggested packages:iproute2-doc libgd-tools mmdb-bin fcgiwrap nginx-doc ssl-cert
The following NEW packages will be installed:iproute2 libatm1 libbpf0 libcap2-bin libdeflate0 libelf1 libgd3 libjbig0 libmaxminddb0 libmnl0 libnginx-mod-http-geoip2libnginx-mod-http-image-filter libnginx-mod-http-xslt-filter libnginx-mod-mail libnginx-mod-streamlibnginx-mod-stream-geoip2 libpam-cap libpam-runtime libtiff5 libwebp7 libx11-6 libx11-data libxau6 libxcb1 libxdmcp6libxpm4 libxslt1.1 libxtables12 nginx nginx-common nginx-core
0 upgraded, 31 newly installed, 0 to remove and 1 not upgraded.
Need to get 3,800 kB of archives.
After this operation, 12.3 MB of additional disk space will be used.

尝试启动Nginx服务

sudo systemctl start nginx
sudo systemctl status nginx
cacc@purgatory-v:~$ sudo systemctl status nginx
○ nginx.service - A high performance web server and a reverse proxy serverLoaded: loaded (/lib/systemd/system/nginx.service; disabled; vendor preset: enabled)Active: inactive (dead)Docs: man:nginx(8)
cacc@purgatory-v:~$ sudo systemctl start nginx
Job for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xeu nginx.service" for details.
cacc@purgatory-v:~$ systemctl status nginx
× nginx.service - A high performance web server and a reverse proxy serverLoaded: loaded (/lib/systemd/system/nginx.service; disabled; vendor preset: enabled)Active: failed (Result: exit-code) since Mon 2024-12-02 21:48:37 CST; 10s agoDocs: man:nginx(8)Process: 3330 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)Process: 3331 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=1/FAILURE)CPU: 51msDec 02 21:48:35 purgatory-v nginx[3331]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Unknown error)
Dec 02 21:48:35 purgatory-v nginx[3331]: nginx: [emerg] bind() to [::]:80 failed (98: Unknown error)
Dec 02 21:48:36 purgatory-v nginx[3331]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Unknown error)
Dec 02 21:48:36 purgatory-v nginx[3331]: nginx: [emerg] bind() to [::]:80 failed (98: Unknown error)
Dec 02 21:48:36 purgatory-v nginx[3331]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Unknown error)
Dec 02 21:48:36 purgatory-v nginx[3331]: nginx: [emerg] bind() to [::]:80 failed (98: Unknown error)
Dec 02 21:48:37 purgatory-v nginx[3331]: nginx: [emerg] still could not bind()
Dec 02 21:48:37 purgatory-v systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Dec 02 21:48:37 purgatory-v systemd[1]: nginx.service: Failed with result 'exit-code'.
Dec 02 21:48:37 purgatory-v systemd[1]: Failed to start A high performance web server and a reverse proxy server.

发现无法启动,后来想起来我在这个服务器上的SpringBoot测试项目占用了80端口,关闭后尝试重启发现启动成功。

cacc@purgatory-v:~$ sudo systemctl stop demo
cacc@purgatory-v:~$ sudo systemctl restart nginx
cacc@purgatory-v:~$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy serverLoaded: loaded (/lib/systemd/system/nginx.service; disabled; vendor preset: enabled)Active: active (running) since Mon 2024-12-02 21:50:44 CST; 3s agoDocs: man:nginx(8)Process: 4117 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)Process: 4118 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)Main PID: 4119 (nginx)Tasks: 5 (limit: 9261)Memory: 4.8MCPU: 28msCGroup: /system.slice/nginx.service├─4119 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"├─4120 "nginx: worker process" "" "" "" "" "" "" "" "" "" "" "" "" >├─4121 "nginx: worker process" "" "" "" "" "" "" "" "" "" "" "" "" >├─4122 "nginx: worker process" "" "" "" "" "" "" "" "" "" "" "" "" >└─4123 "nginx: worker process" "" "" "" "" "" "" "" "" "" "" "" "" >Dec 02 21:50:44 purgatory-v systemd[1]: Starting A high performance web server and a reverse proxy server...
Dec 02 21:50:44 purgatory-v systemd[1]: Started A high performance web server and a reverse proxy server.
cacc@purgatory-v:~$

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


2. 使用启用其他端口

更改nginx的网站设置,在\etc\nginx\sites-avialable

sudo cp default default-8080
sudo vim default-8080
server {listen 8080 default_server;listen [::]:8080 default_server;root /var/www/html;index index.html index.htm index.nginx-debian.html;server_name _;location / {try_files $uri $uri/ =404;}
}

设置好后,创建快捷方式到上级目录的启用文件夹的sites-enbales,这里是启用的配置文件,然后测试以下nginx配置文件语法是否正确。

sudo ln -s /etc/nginx/sites-available/default-8080 /etc/nginx/sites-enabled/
sudo nginx -t
cacc@purgatory-v:/etc/nginx $ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

随后重启Nginx服务,随即访问相应连接,测试成功。

sudo systemctl restart nginx

在这里插入图片描述

在这里插入图片描述


3. 均衡负载

通过Nginx实现均衡负载,首先需要两个作为网站服务器的主机,以及一个代理服务器。代理服务器作为与客户端的窗口,处理客户端的请求。首先客户端发送请求给代理,代理再根据相关算法,将请求接给后端服务器,例如轮询和最小连接数算法,将服务器的压力分散,实现均衡负载

在这里插入图片描述

首先在另一台设备中安装nginx并开启服务

在这里插入图片描述

在这里,192.168.0.115是另一台服务器。将本服务器设置好后无需再设置其他。回到192.168.0.190这个服务器,设置Nginx反向代理,实现均衡负载。

sudo vim sites-available/balance
sudo ln -s /etc/nginx/sites-available/balance /etc/nginx/sites-enabled/

在这里,首先设置后端服务器的列表,这里有两个后端服务器,一个是本身服务器,这里可以填写localhost,另一个则是刚刚建立的192.168.0.115。这里设置了域名分别,也就是通过域名iot.arorms.cn访问机器时(域名解析已经设置成192.168.0.190),就会访问到这个虚拟主机的服务端,并根据这个代理实现均衡负载访问服务器,而IP直接访问则是直接访问。

upstream backend {server localhost;server 192.168.0.115;
}server {listen 80;server_name iot.arorms.cn;location / {proxy_pass http://backend;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}
}
sudo nginx -t
sudo systemctl restart nginx
cacc@purgatory-v:nginx/sites-enabled $ systemctl restart nginx
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ====
Authentication is required to restart 'nginx.service'.
Authenticating as: Cacciatore (cacc)
Password:
==== AUTHENTICATION COMPLETE ====

在这里插入图片描述

访问代理设置的域名,即为iot.arorms.cn,访问成功。这里可以直接确定实现了均衡负载,因为在这个设置中,没有写网站的根目录,而代理直接转发给了之前设置的默认配置的网站,说明已经实现了转发。

在这里插入图片描述

还可以查看日志,验证是否成功

sudo tail -f /var/log/nginx/access.log
cacc@purgatory-v:nginx/sites-enabled $ sudo tail -f /var/log/nginx/access.log192.168.0.158 - - [03/Dec/2024:15:11:59 +0800] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
192.168.0.190 - - [03/Dec/2024:15:11:59 +0800] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
192.168.0.158 - - [03/Dec/2024:15:11:59 +0800] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
192.168.0.190 - - [03/Dec/2024:15:11:59 +0800] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
192.168.0.158 - - [03/Dec/2024:15:11:59 +0800] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
192.168.0.190 - - [03/Dec/2024:15:11:59 +0800] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
192.168.0.158 - - [03/Dec/2024:15:11:59 +0800] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
192.168.0.158 - - [03/Dec/2024:15:11:59 +0800] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
192.168.0.190 - - [03/Dec/2024:15:11:59 +0800] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
192.168.0.158 - - [03/Dec/2024:15:11:59 +0800] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"

这里日志显示交替两个IP返回客户端请求,说明这里Nginx使用的是默认的轮询方法,做到均衡负载。

在这里有可能会出现两个错误,需要注意。

  1. 413 Request Header or Cookie too large

    这个可能是因为Nginx默认设置的请求头和Cookie限制,前往/etc/nginx/nginx.conf修改即可,在http块中添加如下两行。

    http {client_max_body_size 50M;			   	# 调整请求体大小(默认1M)large_client_header_buffers 4 16k;		# 调整请求头缓冲区大小...
    }
    
  2. 500 Internal Server Error

    这可能是因为设置的后端服务器列表中的服务器无法访问导致错误,需要查看是否可以连接。

    curl -I http://192.168.0.190
    curl -I http://192.168.0.115
    

    必须返回以下头部才说明服务器可访问。

    HTTP/1.1 200 OK
    Server: nginx/1.18.0 (Ubuntu)
    Date: Tue, 03 Dec 2024 07:03:58 GMT
    Content-Type: text/html
    Content-Length: 612
    Last-Modified: Tue, 15 Oct 2024 01:14:07 GMT
    Connection: keep-alive
    ETag: "670dc1df-264"
    Accept-Ranges: bytesHTTP/1.1 200 OK
    Server: nginx/1.22.1
    Date: Tue, 03 Dec 2024 07:03:59 GMT
    Content-Type: text/html
    Content-Length: 615
    Last-Modified: Tue, 03 Dec 2024 01:39:40 GMT
    Connection: keep-alive
    ETag: "674e615c-267"
    Accept-Ranges: bytes
    

    在第四个实验中,为了减少不必要的麻烦,暂时关闭代理。删除sites-enabled下的balance,这里只是删除了它的快捷方式,配置文件仍然在sites-available中,不过因为没有在enabled文件夹中创建快捷方式,所以这个设置没有被启动。

    cacc@purgatory-v:nginx/sites-enabled $ sudo rm balance
    cacc@purgatory-v:nginx/sites-enabled $ sudo systemctl restart nginx
    

基于DNS解析的均衡负载

在这里不难看出,即使已经将所有的业务分散给后端服务器,但是仍然需要通过访问代理服务器来进行访问。这个方案中,仍然需要利用代理服务器来确定连接,而且所有流量都会通过这个代理服务器。还有一种均衡负载的方法,就是通过DNS解析轮询不同服务器的IP,将所有业务均衡负载给这些服务器群,使其能够实现均衡负载。

在这里,已经设置域名解析的DNS记录,abc.arorms.cn设置了三个IP,查看DNS是否生效。下面这段Java代码使用网络地址方法InetAddress.getAllByName(),对域名获取所有解析出来的地址。

package Network;import java.io.*;
import java.net.*;/*** This program demonstrates the InetAddress class. Supply a host name as command-line* argument, or run without command-line arguments to see the address of the local host.* @version 1.02 2012-06-05* @author Cay Horstmann*/
public class InetAddressTest
{public static void main(String[] args) throws IOException{if (args.length > 0){String host = args[0];InetAddress[] addresses = InetAddress.getAllByName(host);for (InetAddress a : addresses)System.out.println(a);}else{InetAddress localHostAddress = InetAddress.getLocalHost();System.out.println(localHostAddress);}}
}

执行后发现成功实现将同一域名访问分散到不同服务器以实现均衡负载。

D:\Environment\jdk-21\bin\java.exe "-javaagent:D:\Development\IntelliJ IDEA 2024.1.4\lib\idea_rt.jar=36143:D:\Development\IntelliJ IDEA 2024.1.4\bin" -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath E:\LearningProjects\Java\out\production\CoreJavaVolume;C:\Users\Holme\.m2\repository\junit\junit\4.13.1\junit-4.13.1.jar;C:\Users\Holme\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar Network.InetAddressTest abc.arorms.cn
abc.arorms.cn/192.168.0.4
abc.arorms.cn/192.168.0.2
abc.arorms.cn/192.168.0.3Process finished with exit code 0
cacc@purgatory-v:~ $ dig abc.arorms.cn	# 利用dig命令验证; <<>> DiG 9.18.28-0ubuntu0.22.04.1-Ubuntu <<>> abc.arorms.cn
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45124
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 6, ADDITIONAL: 12;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;abc.arorms.cn.                 IN      A;; ANSWER SECTION:
abc.arorms.cn.          600     IN      A       192.168.0.3
abc.arorms.cn.          600     IN      A       192.168.0.4
abc.arorms.cn.          600     IN      A       192.168.0.2;; AUTHORITY SECTION:
cn.                     44639   IN      NS      c.dns.cn.
cn.                     44639   IN      NS      a.dns.cn.
cn.                     44639   IN      NS      e.dns.cn.
cn.                     44639   IN      NS      d.dns.cn.
cn.                     44639   IN      NS      b.dns.cn.
cn.                     44639   IN      NS      ns.cernet.net.;; ADDITIONAL SECTION:
a.dns.cn.               44639   IN      A       203.119.25.1
b.dns.cn.               44639   IN      A       203.119.26.1
c.dns.cn.               44639   IN      A       203.119.27.1
d.dns.cn.               44639   IN      A       203.119.28.1
e.dns.cn.               44639   IN      A       203.119.29.1
ns.cernet.net.          44639   IN      A       202.112.0.44
a.dns.cn.               44639   IN      AAAA    2001:dc7::1
b.dns.cn.               44639   IN      AAAA    2001:dc7:1::1
c.dns.cn.               44639   IN      AAAA    2001:dc7:2::1
d.dns.cn.               44639   IN      AAAA    2001:dc7:1000::1
e.dns.cn.               44639   IN      AAAA    2001:dc7:3::1;; Query time: 96 msec
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
;; WHEN: Tue Dec 03 20:28:46 CST 2024
;; MSG SIZE  rcvd: 437

4. 访问控制

在服务器开启Nginx的访问控制,有很多方案。

  • 基于IP地址的访问控制,用于限制从其他网络连接,比如限制外部IP,放行192.168.0.0/24
  • 基于User-Agent的访问控制,是请求头的一个属性,标识了用户身份,比如运行正常用户通过浏览器访问网站,但是不允许爬虫直接访问爬取网站资源。
  • 基于Referer的访问控制,这个用来允许或者拒绝某些来源的请求。最简单的比如只允许站内跳转到本页面。
  • 基于请求方法的控制,例如只允许GETPOST方法访问。
  • 基于HTTP身份验证的访问控制,为网站设置用户名和密码
  • 基于时间、地理位置的访问控制。
  • . . . . . .
HTTP身份验证

首先安装apache2-utils工具,用于创建和管理用户密码文件。

sudo apt-get update
sudo apt-get install apache2-utils

然后创建密码文件,利用htpasswd命令创建一个包含用户密码的文件。新建一个密码文件,并设置用户名为cacc

sudo htpasswd -c /etc/nginx/.htpasswd cacc
cacc@purgatory-v:nginx/sites-enabled $ sudo htpasswd -c /etc/nginx/.htpasswd cacc
New password:
Re-type new password:
Adding password for user cacc

可以查看密码,可以看出已经被单向算法加密

cacc@purgatory-v:nginx/sites-enabled $ cat /etc/nginx/.htpasswd
cacc:$apr1$oyMbSbhj$arjSai4uK4lEwUxibxSZ/.

创建完密码文件后,返回默认配置文件/etc/nginx/sites-enabled/default,进行更改。

sudo vim /etc/nginx/sites-enabled/default
server {listen 80 default_server;listen [::]:80 default_server;root /var/www/html;index index.html index.nginx-debian.html;server_name iot.arorms.cn;location / {auth_basic "Restricted Access";					# 提示信息auth_basic_user_file /etc/nginx/.htpasswd;		# 密码文件try_files $uri $uri/ =404;}
}

验证Nginx设置语法正确性然后重新启动Nginx服务,重新访问网站,就可以发现需要输入用户名密码才可以访问网站资源。

在这里插入图片描述

输入密码后访问成功

在这里插入图片描述

IP访问控制

注释掉刚刚身份验证控制的设置,并更换为如下设置。

server {listen 80 default_server;listen [::]:80 default_server;root /var/www/html;index index.html index.nginx-debian.html;server_name iot.arorms.cn;location / {allow 192.168.0.158;	# 允许192.168.0.158访问deny all;				# 拒绝其他所有连接#auth_basic "Restricted Access";#auth_basic_user_file /etc/nginx/.htpasswd;try_files $uri $uri/ =404;}
}

利用两台不同的机器测试,由于服务器没有安装图形化界面,直接通过curl调用接口的命令访问服务器。

192.168.0.158 Windows的访问结果,由于本IP被设置在白名单上,因此可以访问。

Invoke-WebRequest iot.arorms.cn -UseBasicParsing | Select-Object -ExpandProperty Content

返回网站页面

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>body {width: 35em;margin: 0 auto;font-family: Tahoma, Verdana, Arial, sans-serif;}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p><p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p><p><em>Thank you for using nginx.</em></p>
</body>
</html>

192.168.0.190 Ubuntu访问结果,不在白名单上,无法访问。

curl iot.arorms.cn

返回结果可以看到错误403 Forbidden无法访问。

<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.18.0 (Ubuntu)</center>
</body>
</html>

跨域问题的解决

在B/S 的应用中,什么是跨域问题?一般跨域问题的解决思路有哪些?在Nginx 中能否解决跨域问题?如何能,如何配置实现?并实验验证它。

URL结构

在跨域问题中,首先需要明确URL结构,一个URL通常如下,例如一个显示新闻的页面可能是这样的。

http://iot.arorms.cn:8080/news?id=21#title
  • http 协议
  • iot.arorms.cn 服务器域名
  • 8080 端口
  • news 资源路径
  • id=21 参数,这里是id为21
  • #title 锚点,用于定位网页位置

当访问web内容时,需要通过URL进行定位,通常会返回一个资源对象,当不同对象的协议,主机(域名),端口相同时,则称它们有共同的源。

跨域问题

如果不同源,会限制以下内容:

  • DOM 操作:不同源无法访问彼此的 DOM。

  • AJAX 请求:浏览器会阻止跨源的异步请求。

  • Cookie、LocalStorage 和 SessionStorage:限制不同源访问存储数据。

浏览器的同源策略是一个重要的安全策略,它用于限制一个源的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能够帮助阻隔恶意文档,避免跨网站脚本攻击,例如攻击者通过注入恶意脚本,窃取用户的Cookie或者敏感数据,限制注入的脚本与目标节点交互,可以减少攻击媒介。其次攻击者伪装成受信用户向服务器发送而已请求,同源策略能够限制第三方站点直接操作用户的敏感数据。

在我之前的项目中,用户需要注册登录网站。在此时会生成一份PHPSESSION,作为身份验证。而通过XSS注入,可以通过脚本将用户的PHPSESSION发送到攻击者的服务器中记录。而攻击者的服务器肯定与被攻击者的网站不同源,因此限制同源访问可以解决一些攻击手段。不过同源策略无法低于明显的跳转式SESSION劫持。

在前后端不分离时,通常不存在跨域问题,因为资源基本上都在同一个服务器。而前后端分离后,由于前端需要调用后端API,由于前后端分离,服务器不同,会导致跨域问题。

Nginx解决方案

设置反向代理

在Nginx的设置文件中如下

server {listen 80;server_name iot.arorms.cn;location /api/ {proxy_pass http://api.arorms.cn; # 目标跨域服务proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;}
}

客户端访问http://iot.arorms.cn/api时,通过反向代理调用http://api.arorms.cn服务器的api,而客户端仍然认为时iot.arorms.cn返回的资源。

验证

首先先看一下以下典型场景是否会引发跨域问题。

  1. 重定向,不会引发跨域问题

    • html标签href跳转,如下连接将用户页面重定向到主页,可以访问

      <href a="http://iot.arorms.cn">访问主页</href>
      
      • Spring方法redirect重定向网页,不会出现跨域问题
  2. 跨域获取资源

    • JavaScript的fetchXMLHttpRequestAJAX方法获取资源

      在这里跨域获取资源是不被允许的

在前面的实验中,出现了SpringBoot占用80端口导致Nginx无法启动的失误。在服务器上我利用Java SpringBoot写了一些后端API可以调用,可以用SpringBoot项目中的API做验证。

首先,后端的调用接口如下,此处是获取镇江(city=321100)天气的接口。

http://api.arorms.cn/weather/getByCity?city=321100

利用SpringBoot框架所创建的天气查询功能中,所对应的Controller类代码如下

package cn.arorms.demo.controller;import cn.arorms.demo.entity.WeatherInfo;
import cn.arorms.demo.service.WeatherService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.List;/*** WeatherController* @version 1.0 2024-11-06* @author Cacc*/
@RestController
@RequestMapping("/weather")
public class WeatherController {@AutowiredWeatherService weatherService;@GetMapping("/getByCity")public List<WeatherInfo> getByCity(@RequestParam("city") String city) {return weatherService.getWeatherForcastsByCity(city);}
}

首先,通过直接调用端口API,可以发现能够直接获取数据

curl http://api.arorms.cn/weather/getByCity\?city\=321100

返回数据,返回了天气信息对象,这里已经将json数据美化。

[{"city": "镇江市","date": "2024-12-03","weekNumber": "2","dayTemp": "15","nightTemp": "6","dayWeather": "多云","nightWeather": "阴"},// 还有还有后面三天预测省略
]

在另一台服务器上,启动前端页面,前端代码如下

<!DOCTYPE html>
<html lang="cn">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>天气预报</title><link href="/css/bootstrap.min.css" rel="stylesheet"><!-- 此处省略css代码 -->
</head>
<body>
<div class="container"><div class="row justify-content-center"><div class="col-md-5"><div class="weather-container"><h2>镇江天气预报</h2><div id="forecastContainer"></div><button class="btn btn-primary mt-4" onclick="fetchWeather()">获取天气</button><div id="errorMessage" class="error-message" style="display: none;"></div></div></div></div>
</div><script src="/js/bootstrap.bundle.min.js"></script>
<script>function fetchWeather() {const cityId = '321100';const apiUrl = `http://api.arorms.cn/weather/getByCity?city=${cityId}`;document.getElementById('errorMessage').style.display = 'none';fetch(apiUrl).then(response => response.json()).then(data => {if (data && Array.isArray(data)) {const forecastContainer = document.getElementById('forecastContainer');forecastContainer.innerHTML = '';data.forEach(weather => {const forecastDay = document.createElement('div');forecastDay.classList.add('forecast-day');const date = weather.date;const dayTemp = `${weather.dayTemp}°C`;const nightTemp = `${weather.nightTemp}°C`;const dayWeather = `白天: ${weather.dayWeather}`;const nightWeather = `夜间: ${weather.nightWeather}`;forecastDay.innerHTML = `<h4>${formatDate(weather.date)}</h4><div>${dayWeather} | ${dayTemp}</div><div>${nightWeather} | ${nightTemp}</div>`;forecastContainer.appendChild(forecastDay);});} else {showError('无法获取天气数据,请稍后再试');}}).catch(error => {console.error('获取天气数据时发生错误:', error);showError('发生错误,请检查网络连接');});}function formatDate(dateString) {const date = new Date(dateString);const month = date.getMonth() + 1;const day = date.getDate();return `${month}${day}`;}function showError(message) {const errorMessageDiv = document.getElementById('errorMessage');errorMessageDiv.style.display = 'block';errorMessageDiv.innerText = message;}window.onload = function() {fetchWeather();};
</script>
</body>
</html>

这里利用JavaScript的fetch,将调用api获取的对象显示到前端。而此处发现无法直接访问,因为这里触发了同源策略中主机不同的问题,导致无法执行脚本返回数据。也就是直接调用后端API会导致无法获取资源。

const apiUrl = `http://api.arorms.cn/weather/getByCity?city=${cityId}`;

直接访问http://iot.arorms.cn,发现无法调用接口。

在这里插入图片描述

这时,在服务器iot.arorms.cn上设置Nginx反向代理,解决跨域问题。

server {listen 80;server_name iot.arorms.cn;location / {root /var/www/demo;index index.html;}location /api/ {proxy_pass http://api.arorms.cn/weather/;proxy_set_header Host api.arorms.cn;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}
}

在这里插入图片描述

通过这样的设置,可以看出,由于数据是根据服务器的反向代理获取的,因此解决了不同源的问题,使得数据可以返回到前端显示给用户。

完成设置后测试Nginx语法并重启Nginx。将weather.html放入demo文件夹根目录后,访问iot.arorms.cn直接进入天气查询页面。在天气查询的代码中,更改apiUrl为代理的url。

const apiUrl = `http://iot.arorms.cn/api/getByCity?city=${cityId}`;

重新访问http://iot.arorms.cn并查询天气,查询成功,也验证了Nginx反向代理方法可以解决跨域问题。

在这里插入图片描述

相关文章:

Nginx Web服务器管理、均衡负载、访问控制与跨域问题

Nginx Web 服务器的均衡负载、访问控制与跨域问题 Nginx 的配置 1. 安装Nginx 首先安装Nginx apt install nginx -ycaccpurgatory-v:~$ sudo apt install nginx [sudo] password for cacc: Reading package lists... Done Building dependency tree... Done Reading state i…...

排序学习整理(2)

上集回顾 排序学习整理&#xff08;1&#xff09;-CSDN博客 2.3 交换排序 交换排序的基本思想是&#xff1a;根据序列中两个记录键值的比较结果&#xff0c;交换这两个记录在序列中的位置。 特点&#xff1a; 通过比较和交换操作&#xff0c;将键值较大的记录逐步移动到序列…...

【前端】将vue的方法挂载到window上供全局使用,也方便跟原生js做交互

【前端】将vue的方法挂载到window上供全局使用&#xff0c;也方便跟原生js做交互 <template><div><el-button click"start">调用方法</el-button></div> </template> <script> // import { JScallbackProc } from ./JScal…...

单片机的中断系统

作者简介 彭煜轩&#xff0c;男&#xff0c;银川科技学院计算机与人工智能学院&#xff0c;2022级计算机与科学技术8班本科生&#xff0c;单片机原理及应用课程第3组。 指导老师&#xff1a;王兴泽 电子邮件&#xff1a;1696409709qq.com 前言 本篇文章是参考《单片机原理…...

Java基础面向对象(接口高级)

高版本的接口 JDK8.0 普通的公开非抽象方法(默认方法) [public] default 返回值类型 方法名(形参列表){//操作语句 } default: 在此位置身份为非抽象标识 接口中的非抽象方法实现类不需要进行重写且通常不会进行重写 当父类与接口的方法体出现冲突时, 优先执行父类内容 (类优…...

OpenCV圆形标定板检测算法findCirclesGrid原理详解

OpenCV的findCirclesGrid函数检测圆形标定板的流程如下:   findCirclesGrid函数源码: //_image,输入图像 //patternSize,pattern的宽高 //_centers,blobs中心点的位置 //flags,pattern是否对称 //blobDetector,这里使用的是SimpleBlobDetector bool cv::findCirclesGrid(…...

Linux 网卡收包流程如下

Linux 网卡收包流程如下 网卡收到数据包将数据包从网卡硬件缓存移动到服务器内存中(DMA方式&#xff0c;不经过CPU)通过硬中断通知CPU处理CPU通过软中断通知内核处理经过TCP/IP协议栈处理应用程序通过read()从socket buffer读取数据 网卡丢包 我们先看下ifconfig的输出&#…...

普中51单片机——LED流水灯模块

1、GPIO概念 GPIO&#xff08;general purpose intput output&#xff09;是通用输入输出端口的简称&#xff0c;可以通过软件来控制其输入和输出。51 单片机芯片的 GPIO 引脚与外部设备连接起来&#xff0c;从而实现与外部通讯、 控制以及数据采集的功能。 1.1、GPIO分类 &a…...

Linux 各个目录作用

刚毕业的时候学习Linux基础知识&#xff0c;发现了一份特别好的文档快乐的 Linux 命令行&#xff0c;翻译者是happypeter&#xff0c;作者当年也在慕课录制了react等前端相关的视频&#xff0c;通俗易懂&#xff0c;十分推荐 关于Linux的目录&#xff0c;多数博客已有详细介绍…...

【包教包会】CocosCreator3.x——重写Sprite,圆角、3D翻转、纹理循环、可合批调色板、不影响子节点的位移旋转缩放透明度

一、效果演示 重写Sprite组件&#xff0c;做了以下优化&#xff1a; 1、新增自变换&#xff0c;在不影响子节点的前提下位移、旋转、缩放、改变透明度 新增可合批调色板&#xff0c;支持色相、明暗调节 新增圆角矩形、3D透视旋转、纹理循环 所有功能均支持合批、原生平台&…...

腾讯阅文集团Java后端开发面试题及参考答案

Java 的基本数据类型有哪些?Byte 的数值范围是多少? Java 的基本数据类型共有 8 种,可分为 4 类: 整数类型:包括 byte、short、int 和 long。byte 占 1 个字节,其数值范围是 - 128 到 127,用于表示较小范围的整数,节省内存空间,在处理一些底层的字节流数据或对内存要求…...

Kafka如何保证消息可靠?

大家好&#xff0c;我是锋哥。今天分享关于【Kafka如何保证消息可靠&#xff1f;】面试题。希望对大家有帮助&#xff1b; Kafka如何保证消息可靠&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Kafka通过多种机制来确保消息的可靠性&#xff0c;主要包…...

【layui】tabs 控件内通过 iframe 加载url 方式渲染tab页面

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>tabs 内部使用 iframe 嵌套 url 页面</title><link rel"stylesheet" href"../../../libs/layui/layui-2.4.5/dist/css/layui.css"><scr…...

EtherCAT转DeviceNe台达MH2与欧姆龙CJ1W-DRM21通讯案例

一.案例背景 台达MH2设备通常采用EtherCAT通信协议&#xff0c;这种协议在高速实时通信方面表现出色&#xff0c;适合设备之间的快速数据交换和精准控制。而欧姆龙CJ1W-DRM21 模块基于DeviceNet通信协议&#xff0c;DeviceNet在工业现场总线领域应用广泛&#xff0c;侧重于设备…...

清华、智谱团队:「6000亿合成交错语音文本」预训练,问答性能提升近3倍

与基于文本的大语言模型&#xff08;LLM&#xff09;相比&#xff0c;语音语言模型&#xff08;SpeechLM&#xff09;接受语音输入并生成语音输出&#xff0c;能够实现更自然的人机交互。然而&#xff0c;传统的 SpeechLM 因缺乏无监督语音数据和并行语音-文本数据&#xff0c;…...

Python办公——openpyxl处理Excel每个sheet每行 修改为软雅黑9号剧中+边框线

目录 专栏导读背景1、库的介绍①&#xff1a;openpyxl 2、库的安装3、核心代码4、完整代码5、最快的方法(50万行44秒)——表头其余单元格都修改样式总结 专栏导读 &#x1f338; 欢迎来到Python办公自动化专栏—Python处理办公问题&#xff0c;解放您的双手 &#x1f3f3;️‍…...

遇到问题:hive中的数据库和sparksql 操作的数据库不是同一个。

遇到的问题&#xff1a; 1、hive中的数据库和sparksql 操作的数据库不同步。 观察上面的数据库看是否同步 &#xff01;&#xff01;&#xff01; 2、查询服务器中MySQL中hive的数据库&#xff0c;发现创建的位置没有在hdfs上&#xff0c;而是在本地。 这个错误产生的原因是&…...

《网络攻防实践》实践五报告

1.实践内容 防火墙 &#xff08;1&#xff09;基本概念 所谓“防火墙”是指一种将内部网和公众访问网&#xff08;如Internet&#xff09;分开的方法&#xff0c;它实际上是一种建立在现代通信网络技术和信息安全技术基础上的应用性安全技术&#xff0c;隔离技术。越来…...

深入傅里叶级数与傅里叶变换:从基础到应用

傅里叶分析是数学、物理和工程领域的一项基础工具&#xff0c;其核心思想是将复杂的信号或函数分解为一系列简单的正弦和余弦函数的叠加。本文将带你从傅里叶级数入门&#xff0c;逐步深入傅里叶变换的概念及其应用场景。 一、傅里叶级数&#xff1a;周期信号的分解 1. 什么是傅…...

C++入门一

一、命名空间 #include <stdio.h> int rand 0; int main() {printf("hello world\n");printf("%d\n", rand); } 这样是可以运行的&#xff0c;可是当我们加入一个头文件的时候 #include <stdio.h> #include <stdlib.h> int rand 0;…...

Spring Boot 项目集成camunda流程引擎

Spring Boot 项目集成camunda流程引擎 camunda地址 camunda中文地址 使用camunda开源工作流引擎有&#xff1a;通过docker运行、使用springboot集成、部署camunda发行包、基于源代码编译运行等多种方式。 文本重点介绍如何在Spring Boot应用程序中如何集成Camunda Platform开…...

Ubuntu20.04编译安装Carla全过程

前言 Carla的安装是我现阶段解决的第一个问题&#xff0c;现记录一下我安装Carla的过程以及我在安装过程中遇到的一些问题。 一、安装前准备 1、硬件环境 carla是一款基于UE4开发的模拟仿真软件&#xff0c;本身对硬件的要求比较高。 我是windows与ubuntu双系统&#xff0…...

typecho 自动订阅 RSS

昨天学习了一下 RSS 订阅知识之后&#xff0c;经过一番百度搜索&#xff0c;终于在自己的博客上实现了 RSS 订阅功能&#xff0c;但苦于技术有限&#xff0c;不能对 Feed 文件进行定时缓存&#xff0c;每次打开链接都会比较延迟。今天继续对这个功能进行了学习&#xff0c;突然…...

MFC图形函数学习13——在图形界面输出文字

本篇是图形函数学习的最后一篇&#xff0c;相关内容暂告一段落。 在图形界面输出文字&#xff0c;涉及文字字体、大小、颜色、背景、显示等问题&#xff0c;完成这些需要系列函数的支持。下面做简要介绍。 一、输出文本函数 原型&#xff1a;virtual BOOL te…...

11.25.2024刷华为OD

文章目录 HJ76 尼科彻斯定理&#xff08;观察题&#xff0c;不难&#xff09;HJ77 火车进站&#xff08;DFS&#xff09;HJ91 走格子方法&#xff0c;&#xff08;动态规划&#xff0c;递归&#xff0c;有代表性&#xff09;HJ93 数组分组&#xff08;递归&#xff09;语法知识…...

Python练习55

Python日常练习 题目&#xff1a; 补充函数getLastDay(y,m)&#xff0c;其功能是计算y年m月共有多少天。 --------------------------------------------------------- 注意&#xff1a; 部分源程序给出如下。请勿改动主函数main和其它函数中的 任何内容&#xff0c;…...

DDR5和DDR4之区别(The Difference between DDR5 and DDR4)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 DDR是什么意思? DDR5和D…...

分层架构 IM 系统之 Router 架构分析

通过前面文章的分析&#xff0c;我们已经明确&#xff0c;Router 的核心职责是作为中央存储记录在线客户端的连接状态&#xff0c;Router 在本质上是一个内存数据库。 内存是一种易失性的存储&#xff0c;既如此&#xff0c;Router 的可用性如何保障呢&#xff1f; 副本是分布…...

用函数实现模块化程序设计(七)--数组作为函数参数(排序算法)

调用有参函数时&#xff0c;需要实参&#xff0c;实参可以是常量&#xff0c;变量&#xff0c;表达式&#xff0c;数组元素的作用与变量相当&#xff0c;凡是变量出现的地方都可用数组代替&#xff0c;数组元素可以用作函数实参&#xff0c;数组名可以作实参和形参&#xff0c;…...

M31系列LoRa分布式IO模块功能简介

M31系列LoRa 分布式 IO 模块简介 M31系列LoRa分布式IO主机模块是一款强大的无线远程控制与采集设备&#xff0c;该设备采用 LoRa 无线技术&#xff08;内置了无线模块&#xff09;&#xff0c;可通过串口或远程 LoRa 组网设备发送 Modbus RTU 指令进行控制&#xff0c;可搭配E…...

Dockerfile 安装echarts插件给java提供服务

java调用echarts插件&#xff0c;生成图片保存到磁盘然后插入到pptx中报表。 Dockerfile文件内容&#xff1a; #基础镜像&#xff0c;如果本地仓库没有&#xff0c;会从远程仓库拉取 openjdk:8 FROM docker.io/centos:centos7 #暴露端口 EXPOSE 9311 # 避免centos 日志输出 …...

学习threejs,使用VideoTexture实现视频Video更新纹理

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️VideoTexture 视频纹理 二、…...

【二分查找】Leetcode例题

【1】69. x 的平方根 - 力扣&#xff08;LeetCode&#xff09; &#x1f361;解题思路&#xff1a;首先想到的是暴力查找&#xff0c;从1开始依次比较x与num*num的大小&#xff0c;然后找出满足num*num<x且(num1)*(num1)>x的num值&#xff1b;再来看看能不能优化一下&…...

稳定运行的以MySQL数据库为数据源和目标的ETL性能变差时提高性能方法和步骤

在ETL&#xff08;Extract, Transform, Load&#xff09;过程中&#xff0c;数据源和目标都为MySQL数据库时&#xff0c;性能变差可能由多种原因引起。提高以MySQL为数据源和目标的ETL性能需要综合考虑数据库性能、ETL任务的处理方式、硬件资源和工具的选择。通过批量处理、并行…...

Springboot(四十九)SpringBoot3整合jetcache缓存

上文中我们学习了springboot中缓存的基本使用。缓存分为本地caffeine缓存和远程redis缓存。现在有一个小小的问题,我想使用本地caffeine缓存和远程redis缓存组成二级缓存。还想保证他们的一致性,这个事情该怎么办呢? Jetcache框架为我们解决了这个问题。 ‌JetCache‌是一个…...

JVM 参数前缀 -XX: 含义 详解

在 Java 虚拟机&#xff08;JVM&#xff09;中&#xff0c;参数前缀 -XX: 表示的是 JVM 的非标准&#xff08;实验性&#xff09;选项。这些参数用于调整和优化 JVM 的性能、垃圾回收行为、内存分配策略等。 1. 参数分类 -XX: 参数大致分为三类&#xff0c;根据其格式区分&…...

【Mac】安装Gradle

1、说明 Gradle 运行依赖 JVM&#xff0c;需要先安装JDK&#xff0c;Gradle 与 JDK的版本对应参见&#xff1a;Java Compatibility IDEA的版本也是有要求Gradle版本的&#xff0c;二者版本对应关系参见&#xff1a;Third-Party Software and Licenses 本次 Gradle 安装版本为…...

证明切平面过定点的曲面是锥面

目录 证明&#xff1a;切平面过定点的曲面是锥面. 证明&#xff1a;切平面过定点的曲面是锥面. 证明&#xff1a; 方法一&#xff1a; 设曲面 S : r r ( u , v ) S:\mathbf{r}\mathbf{r}(u,v) S:rr(u,v)的切平面过定点 P 0 P_0 P0​,其位置向量为 p 0 . \mathbf{p}_0. p0​…...

【WPS】【EXCEL】将单元格中字符按照分隔符拆分按行填充到其他单元格

问题&#xff1a;实现如下图的效果 解答&#xff1a; 一、函数 IFERROR(TRIM(MID(SUBSTITUTE($A$2,",",REPT(" ",LEN($A$2))),(ROW(A1)-1)*LEN($A$2)1,LEN($A$2))),"") 二、在单元格C2中填写如下函数 三、全选要填充的单元格并且按CTRLD 函数…...

工作:三菱PLC防止程序存储器爆满方法

工作&#xff1a;三菱PLC防止程序存储器爆满方法 一、防止程序存储器爆满方法1、编程时&#xff0c;添加行注释时&#xff0c;记得要选“外围”&#xff0c;这样不会占用PLC程序存储器内存&#xff1b;2、选择“外围”的注释&#xff0c;前面会有个*星号&#xff0c;方便检查 二…...

【计算机组成原理】1位预测机制与2位预测机制详解

1位预测机制与2位预测机制详解 在计算机体系结构中&#xff0c;分支预测是为了提高流水线效率而对分支指令执行结果进行预测的技术。1位预测机制和2位预测机制是两种常见的分支预测策略&#xff0c;它们通过预测分支是否发生来决定是否跳转。 一、1位预测机制 1位预测机制是…...

基于SpringBoot+Vue的靓车汽车销售网站-无偿分享 (附源码+LW+调试)

目录 1. 项目技术 2. 功能菜单 3. 部分功能截图 4. 研究背景 5. 研究目的 6. 可行性分析 6.1 技术可行性 6.2 经济可行性 6.3 操作可行性 7. 系统设计 7.1 概述 7.2 系统流程和逻辑 7.3 系统结构 8. 数据库设计 8.1 数据库ER图 &#xff08;1&#xff09;材料分…...

ESP32-S3模组上跑通ES8388(13)

接前一篇文章&#xff1a;ESP32-S3模组上跑通ES8388&#xff08;12&#xff09; 二、利用ESP-ADF操作ES8388 2. 详细解析 上一回解析了es8388_init函数中的第6段代码&#xff0c;本回继续往下解析。为了便于理解和回顾&#xff0c;再次贴出es8388_init函数源码&#xff0c;在…...

洛谷 P1651 塔(DP)

题目传送门https://www.luogu.com.cn/problem/P1651 解题思路 设 表示前 个积木&#xff0c;两塔高度差为 &#xff08;第一个比第二个高多少&#xff09;&#xff0c;的最大高度。 易得&#xff1a; 首先&#xff0c;不选当前的积木&#xff1a; 其次&#xff0c;选当前…...

去哪儿Java开发面试题及参考答案

怎么设置缓存能更快让用户收到数据? 要设置缓存以更快让用户收到数据,可从以下几方面着手。首先,选择合适的缓存位置很关键。将缓存放置在离用户近的地方,如 CDN 缓存,能极大缩短数据传输距离与时间。对于动态内容,可在应用服务器本地设置内存缓存,像使用 Ehcache 等库,…...

DDOS分布式拒绝服务攻击

DDOS分布式拒绝服务攻击 简单来说 传统的DOS就是一台或者多台服务对一个受害目标&#xff08;服务器&#xff0c;路由&#xff0c;ip&#xff0c;国家&#xff09;进行攻击&#xff0c;当范围过大时就是DDOS。目的就是通过大规模的网络流量使得正常流量不能访问受害目标&…...

AI后端工程师面试题的内容

AI后端工程师面试题主要包括以下几个方面的内容‌&#xff1a; ‌一、技术基础和项目经验‌&#xff1a; ‌1. 微服务架构的理解和应用‌&#xff1a;请描述你对微服务架构的理解&#xff0c;并举例说明一个你参与过的微服务项目&#xff0c;阐述你在该项目中扮演的角色和所承…...

使用go语言写一个脚本 实现WebSockt连接 用户发送a 得到返回b

在Go语言中实现一个简单的WebSocket服务器&#xff0c;该服务器能够接收客户端发送的“a”并返回“b”&#xff0c;可以按照以下步骤进行。首先&#xff0c;确保你的环境中已经安装了Go语言环境。接下来&#xff0c;你需要安装一个WebSocket库来处理WebSocket连接。这里我们使用…...

浏览器中输入一个URL后,按下回车后发生了什么

URL &#xff0c;统一资源定位符&#xff0c; 简单点就是网址 ip 或域名 端口号 资源位置 参数 锚点 大致流程 URL 解析DNS 查询TCP 连接处理请求接受响应渲染页面 1 &#xff0e;输入一个网址之后&#xff0c;首先浏览器通过查询 DNS &#xff0c;查找这个 URL 的 IP …...

ISO26262-(Timing Monitoring)在多核MCU的TPU上功能安全ASILB与ASILD有什么区别

在多核微控制器(MCU)的时间保护方面,针对功能安全ASIL B与ASILD等级的设计和实施存在显著差异,这些差异主要体现在系统对时间关键性操作的保障程度、故障检测能力、以及系统响应的严格性上。 ASIL B 级别: 时间关键性:在ASIL B等级,系统设计注重于识别并处理大部分可能…...