Spring Cloud 实现多服务器部署
前景摘要: 项目要求实现 ,微服务部署在多个服务器,这在分布式架构,实现RPC本来是一个十分常规的操作,但是在操作过程共还是遇到了一些问题,特此记录.
配置文件内容
####不同服务器发布####
eureka:
instance:
# ip 地址优先
prefer-ip-address: true
# 服务实例的id,就展示在Eureka的管理界面
instance_id: ${spring.cloud.client.ip-address}-${server.port}
client:
service-url:
# 对于不同服务器,就要注册到对应地址的注册中心
defaultZone: http://192.168.1.11:8001/eureka/
###同一台服务器发布##
eureka:
instance:
hostname: localhost
client:
service-url:
# 同一台服务器 注册中心就在localhost
defaultZone: http://${eureka.instance.hostname}:8001/eureka/
对于同一台服务器来讲,服务注册到Eureka注册中心,很容易实现,只要写好 eureka.instance.hostname为localhost,然后把defaultZone 指向localhost即可.
对于不同的服务器,则需要配置prdfer-ip-address的值为true,再把defaultZone指向eureka所在地址即可.
实现结果
配置完成后部署成功,如果能够在Eureka的管理界面,看到所启动服务已经注册到注册中心,表示配置成功.
有坑
文件的配置实现的很简单.但是还是不可避免的踩到了坑.
1. 安全组规则
在配置完成后,也已经观察到了.服务成功注册到注册中心,但是访问对应的接口还是不能访问到,最终发现是阿里云服务器安全组规则的坑.
笔者部署的服务器需要访问到某个端口,从而访问到数据库的数据,但是当时公司的服务器为了保证数据库安全,这些端口是不对外开放的,所以导致计算微服务配置成功可还是不能正常显示.所以如果使用的是阿里云的服务器,一定好设置好安全组.
新发现
之所以能发现是阿里云安全组的问题,其实也是一个偶然的操作.在看到服务已经成功注册到Eureka之后,经过百般尝试怎么都不行,结果扔在测试服务器给搞定了.扔在生产环境就搞不定.经过大哥提醒有可能是安全组的问题.然后去看安全组,发现新服务所在服务器使用的是测试环境的安全组,于是我尝试了第一种解决方案
- 把所有正式环境的安全组开放的端口,在测试环境也全部开放.
结果,还是不成功.于是我就萌生了.第二种想法
- 我为啥不直接用正式环境的安全组呢? 于是新服务器使用正式环境的安全组.
结果,成功了! 但是测试环境上的新服务又失效了.Emm...
要的结果是 2:1,而不是1:1;到现在为止的结论就是使用正式环境的安全组,正式环境就OK,使用测试环境的安全组,就不行.
- 然后我的另一个野鸡操作又来了, 我在正式环境的安全组把测试环境开放的端口都开了(不建议,只是当时要搞清楚问题,临时这么做.测试完就还原了).
结果又是失败.
- 突然想起一个问题.在测试环境 ,服务和数据库集群是同一个服务器,和正式生产环境是服务和数据库分别使用独立的服务器.也就是说 我得考虑正式数据库环境的安全组.
在新服务器使用测试安全组的情况下,开放正式数据库的安全组端口后.结果就成功了.
于是,结论来了.新服务器必须在使用生产环境的安全组或者 使用测试环境安全组的同时开放数据库端口,才能实现多服务器部署.而在测试服务器上部署是两个安全组都可以的.
原因是: 测试服务器的数据库的端口是开放的,而正式环境的数据库端口需要在数据库所在服务器开放.
测试服务器 也测试过了, 如果把测试服务器对应的数据库的端口关闭后,原本能成功访问的数据也获取不到了.
现在的情况是: 如果我要在正式服务器上部署,就必须开放数据库端口,这显然不是我想要的.毕竟之前就不开放,显然是为了能安全.
等等,之前不开放 ?? 那之前的数据库是怎么访问的? 还有上面 新服务器导入了生产环境的安全组,但是并没有开放数据库的端口,它怎么就又能部署成功,数据也访问成功呢?
难道说,如果说我多个服务器之间只要共用同一个安全组规则,那共用的这几个服务器就可以不受安全组的约束吗?答案是肯定的.
至于说iptables 规则如何配置,下回分解.
2. Eureka
先说结论: 同一个服务下,有多个的实例instance,不正常的实例会影响到正常的实例.
这个界面上显示的实例,有可能是已经失效的服务,但是Eureka中心 还是会显示出来;
那如何去处理掉无效的呢?
host:port/eureka/apps/{appID}/{instanceID}/status?value=DOWN
value 可以是 DOWN 也可以是UP
DOWN 就是无效的时候,让其下线,UP 就是当服务注册不上的时候 ,让其上线.
要用
PUT请求,而不是常用的GET或者POST请求
host:port/eureka/apps/{appID}/{instanceID}/
该接口要使用DELETE请求.
浏览器是不支持,
PUT或者DELETE请求的,所以需要借助类似postman的工具
实例部署还有一些需要注意的地方,摘抄自网络大佬:
- 尽量不要使用
kill -9 pid强制杀掉进程,而应该使用kill pid或者kill -15 pid关闭进程。使用kill pid或者kill -15 pid关闭进程之前,Eureka Client 会给 Eureka Server 请求删除自己,后续服务再次启动后会重新注册为 UP 状态。如果使用kill -9 pid强制杀掉进程,Eureka Client 没有办法注销自己,Eureka Server 就不知道该实例已下线,直到长时间收不到心跳才会删除该实例。如果在 Eureka Server 删除实例之前实例启动了,那么它的状态还是会保持 DOWN 状态。如果确实需要用到kill -9 pid强制杀掉进程,那么服务重启后需要再通过第一步的方式将实例状态设为 UP。- 服务启动后,需要等待并确认启动成功后,才可以开始部署下一台服务器。这里我们可以定时去请求 Spring Boot 提供的 actuator endpoint
/health接口,例如每隔 1 秒请求一次,直到接口可以正常访问,即可认为服务启动成功。