私有子网EC2实例上AngularJS与Java后端通信失败的排查与解决
问题分析与解决方案
这个问题的核心其实是浏览器端的localhost和EC2实例的localhost不是同一个概念,我来给你拆解清楚:
为什么会出现连接拒绝?
当你通过浏览器访问ELB加载前端应用后,前端代码是运行在你本地的浏览器进程里,而不是EC2服务器上。这时候代码里的http://localhost:8080/myserv/getdata,是让你的浏览器去请求你自己电脑的8080端口——但你的本地机器并没有运行Spring Boot后端服务,自然就会出现ERR_CONNECTION_REFUSED错误。
而你在EC2上执行curl命令能成功,是因为curl是在EC2本地执行的,这里的localhost指向的是EC2实例本身,所以能正常访问到8080端口的后端。
解决办法(推荐第一种,更安全)
方案1:用反向代理统一请求入口(推荐)
我们可以在EC2上配置反向代理(比如Nginx),让前端的API请求通过相对路径转发到后端,不需要暴露后端端口到公网,更安全。
步骤如下:
- 修改前端API请求路径
把$http的url改成相对路径,去掉硬编码的http://localhost:8080:$http({ method: 'GET', url: '/myserv/getdata', headers: { 'Content-Type': '*/*' } }).then(function (response) { // processing data... }, function (err) { console.log('ERROR: ' + JSON.stringify(err)); }); - 在EC2上安装并配置Nginx
- 以Amazon Linux 2为例,安装Nginx:
sudo yum install nginx -y - 编辑Nginx配置文件(可以在
/etc/nginx/conf.d/下新建app.conf):server { listen 9000; server_name localhost; # 托管Angular前端静态资源 location / { root /path/to/your/angular/app/dist; # 替换成你的Angular项目构建后的目录 try_files $uri $uri/ /index.html; # 处理单页应用路由跳转 } # 转发后端API请求到8080端口 location /myserv { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } - 重启Nginx并设置开机自启:
sudo systemctl restart nginx sudo systemctl enable nginx
- 以Amazon Linux 2为例,安装Nginx:
- 调整前端运行方式
停止原来用pm2运行的前端服务,现在由Nginx托管静态资源:pm2 stop your-angular-app-name
这样配置后,当浏览器请求/myserv/getdata时,Nginx会把请求转发到EC2本地的8080端口,前端就能正常和后端通信了。
方案2:暴露后端端口并配置CORS(不推荐,安全性低)
如果你不想用反向代理,也可以通过ELB暴露后端的8080端口,同时配置后端允许跨域请求:
- 配置ELB监听规则
在ELB控制台添加新监听:监听8080端口,转发到EC2实例的8080端口;同时确保EC2安全组允许ELB访问8080端口。 - Spring Boot后端配置CORS
在后端添加跨域配置,允许前端所在的ELB域名访问:@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://your-elb-domain") // 替换成你的ELB域名 .allowedMethods("GET", "POST", "PUT", "DELETE") .allowedHeaders("*"); } } - 修改前端API请求地址
把url改成ELB域名加8080端口:$http({ method: 'GET', url: 'http://your-elb-domain:8080/myserv/getdata', headers: { 'Content-Type': '*/*' } }).then(function (response) { // processing data... }, function (err) { console.log('ERROR: ' + JSON.stringify(err)); });
这种方案的缺点是把后端端口直接暴露到公网,增加了安全风险,所以更推荐第一种反向代理的方式。
内容的提问来源于stack exchange,提问作者Sumit
相关产品推荐
相关产品推荐

