代码地址:https://github.com/AJ-Spade/cloud2020/tree/master
服务注册中心集群和服务提供者集群
Eureka(停更),Zookeeper,Consul,Nacos
涉及到的module:
- cloud-consumer-order80
- cloud-eureka-server7001
- cloud-eureka-server7002
- cloud-provider-payment8001
- cloud-provider-payment8002
版本说明
- cloud Hoxton.SR1
- boot 2.2.2RELEASE
- cloud alibaba 2.1.0 RELEASE
- java java8
- Maven 3.5以上
- Mysql 5.7以上
Eureka
-
什么是服务治理?
-
Spring Cloud封装了Netflix公司开发的Eureka模块来实现服务治理。
-
在传统rpc远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,所以需要使用服务治理。可以实现服务调用,负载均衡,容错等,实现服务发现与注册。
-
-
Eureka采用了CS的设计架构,Eureka Server作为服务注册功能的服务器,即服务注册中心。而系统中的其他微服务,使用Eureka的客户端连接到Eureka Server,并维持心跳连接 ,并通过Eureka Server来监控系统中各个微服务是否正常运行。
-
流程:
- step1:启动eureka服务注册中心;
- step2:启动服务提供者payment支付服务
- step3:支付服务启动后,会把自身信息(如服务地址)以别名方式注册进eureka;
- step4:消费者order服务在需要调用接口时,使用服务别名取注册中心获取实际的RPC远程调用地址;
- step5:消费者获得调用地址后,底层实际时用HttpClient技术实现远程调用;
- step6:消费者获得服务地址后,会缓存在本地jvm内存中,默认每间隔30s更新一次服务调用地址;
-
配置服务注册中心集群步骤:
-
step1:创建两个服务注册中心module,分别为cloud-eureka-server7001和cloud-eureka-server7002;
-
step2:修改pom文件,两个模块一致;
-
step3:修改映射配置,找到C:\Windows\System32\driver\etc\hosts,修改映射配置,注释掉原先的127.0.0.1,添加127.0.0.1 eureka7001.com 127.0.0.1 eureka7002.com
-
step4:改写两个module的YML文件。
-
step5:写主启动;
-
step6:测试http://eureka7001.com:7001/;和http://eureka7002.com:7002/
-
step7:之后要在注册中心注册的服务,其默认域如下:
#下面这是集群Eureka的地址 defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
两个module的YML文件:
server: port: 7001 eureka: instance: hostname: eureka7001.com #eureka服务端的实例名称 client: # false表示不向注册中心注册自己 register-with-eureka: false # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要检索服务 fetch-registry: false service-url: # 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址 # 单机 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ # 相互注册 defaultZone: http://eureka7002.com:7002/eureka/ #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #defaultZone: http://eureka7001.com:7001/eureka/
server: port: 7002 eureka: instance: hostname: eureka7002.com #eureka服务端的实例名称 client: # false表示不向注册中心注册自己 register-with-eureka: false # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要检索服务 fetch-registry: false service-url: # 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址 # 单机 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ # 相互注册 defaultZone: http://eureka7001.com:7001/eureka/ #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #defaultZone: http://eureka7001.com:7001/eureka/
-
-
配置一种服务的多个集群步骤:
-
step1:创建两个提供一致功能的服务module;cloud-provider-payment8001和cloud-provider-payment-8002;
-
step2:在Controller中,添加如下代码,用于获取调用该服务的具体端口(即该种服务下的具体某个服务);
@Value("${server.port}") private String serverPort;
-
step3:将调用该种服务的消费者(cloud-consumer-order80)中的controller中的服务地址不要写死,而是写该种服务的别名。
//下面是单机服务,写死的服务地址 //public static final String PAYMENT_URL = "http://localhost:8001"; //下面是集群服务,填写服务的别名,通过轮询算法,访问真正的服务提供者(服务器和端口) public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";
-
step4:在配置类中,使用@LoadBalanced注解,赋予RestTemplate负载均衡的能力,这样调用某种服务时,才能通过算法(轮询),去调用某种服务的具体服务。
通过上面的配置,使得能够达到负载均衡的效果,8001和8002端口交替出现。
Ribbon和Eureka整合后Consumer可以直接调用服务,而不用再关心地址和端口号,且服务还具有负载均衡的功能了。
-
- Eureka包含两个组件:Eureka Server和Eureka Client。
- Eureka Server提供服务注册服务:各个服务节点通过配置启动后,会在EurekaServer进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点信息可以在界面中直接观察到。
- Eureka Client(即多个微服务存在的地方,而非消费者的位置):是一个Java客户端,用于简化与EurekaServer的交互,同时客户端中具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,会向EurekaServer发送心跳,若多个周期都没受到心跳,则EurekaServer会从服务注册表将这个服务节点移除。
需熟练掌握
知识点
-
微服务RPC远程服务调用最核心的是?
高可用。因此需要搭建Eureka注册中心集群,实现负载均衡+故障容错。
-
微服务背后,应该是多个微服务提供者集群。
-
Spring Boot Actuator:健康检查、审计、统计和监控。
你可以增加spring-boot-actuator模块到一个已经存在的应用,通过使用下面的依赖。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies>
Actuator创建了所谓的endpoint来暴露HTTP或者JMX来监控和管理应用。
举个例子,有一个叫/health的endpoint,提供了关于应用健康的基础信息。/metricsendpoints展示了几个有用的度量信息,比如JVM内存使用情况、系统CPU使用情况、打开的文件等等。/loggersendpoint展示了应用的日志和可以让你在运行时改变日志等级。
每一给actuator endpoint可以被显式的打开和关闭。此外,这些endpoints也需要通过HTTP或者JMX暴露出来,使得它们能被远程进入。
打开http://localhost:8080/actuator/health,则会显示如下内容: {"status":"UP"} 状态将是UP只要应用是健康的。如果应用不健康将会显示DOWN,比如与仪表盘的连接异常或者缺水磁盘空间等。 默认,只有health和info通过HTTP暴露了出来。
-
Eureka的自我保护模式。
- 保护模式主要用于一组客户端和Eureka Server之间存在网络分区场景下的保护。
- 一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,即不会注销任何微服务。即不会立即从服务注册表中清理不可用的微服务。
- 属于分布式思想中CAP中的AP。
- 在一般默认情况下,如果EurekaServer在一定事件内没有接收到某个微服务实例的心跳,持久90秒后,将注销该实例。
- 如果EurekaServer节点在短时间(90s)内丢失过多的客户端时,该节点进入自我保护阶段。
tips
-
实际开发过程中,一般是通过几号机器、几号端口、微服务名称,来描述服务。在module中的application.yml的eureka部分,可以通过instance修改某种服务下,具体服务的名字,以及显示IP地址:
eureka: client: #表示是否将自己注册进EurekaServer默认为true register-with-eureka: true #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true,才能配合ribbon使用负载均衡 fetch-registry: true service-url: #下面这个是单机Eureka的地址 #defaultZone: http://localhost:7001/eureka #下面这是集群Eureka的地址 defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka instance: instance-id: payment8002 prefer-ip-address: true #访问路径可以显示IP地址
-
如何暴露给外界,自身所具有的服务?
对于注册进eureka里面的微服务,可以通过服务发现来获得这些微服务的信息。这里的服务可以是项目中80端接口的消费者(cloud-consumer-order80),可以通过微服务(例如cloud-provider-payment8001)对外暴露一个接口地址(如下面的/payment/discovery),然后由消费者调用,即可获得该微服务的一些信息。
具体实现步骤:
-
step1:修改cloud-provider-payment8001的Controller,添加的主要内容如下:
@RestController @Slf4j public class PaymentController { //。。。。。。。。。。。。。 @Resource private DiscoveryClient discoveryClient; @GetMapping(value="/payment/discovery") public Object discovery() { List<String> services = discoveryClient.getServices(); for(String element: services){ log.info("********element:"+element); } List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE"); for(ServiceInstance instance:instances){ log.info(instance.getServiceId() + "\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri()); } return this.discoveryClient; } }
-
Step2:在8001主启动类上,添加@EnableDiscoveryClient注解。
@SpringBootApplication @EnableEurekaClient @EnableDiscoveryClient public class PaymentMain8001 { public static void main(String args[]){ SpringApplication.run(PaymentMain8001.class,args); } }
-
-
如何禁用eureka的自我保护模式
-
step1:首先在eureka注册服务中心,yml配置文件中设置禁用自我保护模式,然后可以再设置一下时间间隔;
server: 。。。。。 eureka: 。。。。。 server: enable-self-preservation: false #禁用自我保护模式,默认是true eviction-interval-timer-in-ms: 2000 #清理无效节点的时间间隔
-
step2:微服务(8001),的yml配置文件中,设置客户端向服务器发送心跳的时间间隔,以及最长等待时间
eureka: 。。。。。。 instance: instance-id: payment8001 prefer-ip-address: true #访问路径可以显示IP地址 #Eureka客户端向服务器发送心跳的时间间隔,单位为秒(默认时30s) lease-renewal-interval-in-seconds: 1 #Eureka服务端在收到最后一次心跳后,等待的时间上限,单位为秒(默认为90s),超时将剔除服务 lease-expiration-duration-in-seconds: 2
-
我的理解:服务端的eviction-…设置的2000ms,是服务器每2000ms要从注册表中清理一次无效节点;而客户端的lease-…设置的2秒,是如果等待心跳时间超过2s,则该服务将被视为无效的服务。那么该服务会在下一次服务器清理注册表的时候,被清理。
-