Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务发现功能。
1. Eureka组件
Eureka包含两个组件:Eureka Server和Eureka Client。
1.1 Eureka Server
Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样Eureka Server中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
Eureka Server本身也是一个服务,默认情况下会自动注册到Eureka注册中心。
如果搭建单机版的Eureka Server注册中心,则需要配置取消Eureka Server的自动注册逻辑。
Eureka Server通过Register、Get、Renew等接口提供服务的注册、发现和心跳检测等服务。
1.2 Eureka Client
Eureka Client是一个java客户端,用于简化与Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。
在应用启动后,将会向Eureka Server发送心跳,默认周期为30秒,如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)。
2. Eureka角色
Eureka Client分为两个角色,分别是:Application Service(Service Provider)和Application Client(Service Consumer)
2.1 Application Service
服务提供方,是注册到Eureka Server中的服务。
2.2 Application Client
服务消费方,通过Eureka Server发现服务,并消费。
在这里,Application Service和Application Client不是绝对上的定义,因为Provider在提供服务的同时,也可以消费其他Provider提供的服务;Consumer在消费服务的同时,也可以提供对外服务。
3. Eureka常用配置介绍
Register(服务注册):把自己的IP和端口注册给Eureka。
Renew(服务续约):发送心跳包,每30秒发送一次。告诉Eureka自己还活着。
Cancel(服务下线):当provider关闭时会向Eureka发送消息,把自己从服务列表中删除。防止consumer调用到不存在的服务。
Get Registry(获取服务注册列表):获取其他服务列表。
Replicate(集群中数据同步):eureka集群中的数据复制与同步。
Make Remote Call(远程调用):完成服务的远程调用。
Zuul 服务网关。Zuul相当于是app应用端和PC端调用服务端时提供方之间的防护门。作为前端服务(Edge Service也称边缘服务,前端服务的作用是对后端服务做必要的聚合和裁剪后暴露给外部不同的设备,如PC,Pad或者Phone),Zuul旨在实现动态路由,监控,弹性和安全性。它具备根据需求将请求路由到多个AWS自动弹性伸缩组的能力。
1.1 Zuul 功能
权限控制和安全性--为每个请求提供身份认证,并拒绝不满足条件的请求。
预警和监控--跟踪前端有意义的请求和统计数据,以便我们准确了解生产环境运行状况
动态路由--根据需求将请求动态地路由到不同的后端集群。
压力测试--逐渐增大到集群的流量,以便进行性能评估。
负载均衡--为每种类型的请求分配容量并丢弃超过限额的请求。
静态资源处理--直接在Zuul处理静态资源并响应,而并非转发这些请求到内部集群中
多区域弹性--实现跨AWS区域请求路由,扩大了ELB的使用范围,并使前端服务更接近我们的成员
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。因为微服务间的调用,API网关的请求转发等内容,实际上都是通过Ribbon来实现的,包括后续我们将要介绍的Feign,它也是基于Ribbon实现的工具。
微服务之间相互调用。Eureka注册中心的微服务之间可以通过Feign注解相互访问。使用了动态代理。动态代理根据在接口上注解的@RequestMapping等注解,来动态构造出需要请求的服务地址
1. 新建maven项目huaun-euzl
2. 新建eureka模块
新建eureka模块后,查看eureka模块的pom.xml的配置文件:
4.0.0 org.springframework.boot spring-boot-starter-parent 2.3.7.RELEASE com.huaun eureka 0.0.1-SNAPSHOT eureka eureka 1.8 Hoxton.SR9 org.springframework.cloud spring-cloud-starter-netflix-eureka-server org.springframework.boot spring-boot-starter-test test org.junit.vintage junit-vintage-engine org.springframework.cloud spring-cloud-dependencies ${spring-cloud.version} pom import org.springframework.boot spring-boot-maven-plugin
将eureka模块中的application.properties文件改成application.yml文件,并进行如下配置
server: port: 8000 #端口号 spring: application: name: eureka-service #服务名称,注册中心的serverId eureka: server: peer-node-connect-timeout-ms: 300 instance: hostname: localhost client: fetch-registry: false #不获取服务中心的服务 register-with-eureka: false #不注册自己到注册中心去 service-url: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
@EnableEurekaServer注解eureka块中的EurekaApplication启动类
package com.huaun.eureka; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class, args); } }
启动Eureka服务,浏览器输入http://localhost:8000/.可以得到如下图结果
3. 新建微服务userapi模块(不含 Feign)
新建userapi模块后,查看userapi模块的pom.xml的配置文件:
4.0.0 org.springframework.boot spring-boot-starter-parent 2.3.7.RELEASE com.huaun userapi 0.0.1-SNAPSHOT userapi userapi 1.8 Hoxton.SR9 org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-starter-netflix-eureka-client org.springframework.boot spring-boot-starter-test test org.junit.vintage junit-vintage-engine org.springframework.cloud spring-cloud-dependencies ${spring-cloud.version} pom import org.springframework.boot spring-boot-maven-plugin
将userapi模块中的application.properties文件改成application.yml文件,并进行如下配置
server: port: 7001 servlet: context-path: /userapi #context-path不能省略,用于统一userapi中restful接口的访问的前缀 spring: application: name: user-service eureka: instance: prefer-ip-address: true client: register-with-eureka: true #将自己注册到eureka注册中心中去 fetch-registry: true #从eureka注册中心拉取服务 service-url: defaultZone: http://localhost:8000/eureka
@EnableDiscoveryClient注解userapi块中的UserapiApplication启动类
package com.huaun.userapi; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class UserapiApplication { public static void main(String[] args) { SpringApplication.run(UserapiApplication.class, args); } }
在userapi模块中创建restful接口
package com.huaun.userapi.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @GetMapping("getUserInfo") public String getUserInfo(){ return "name: lucy00"; } }
刷新Eureka服务,浏览器输入http://localhost:8000/.可以得到如下图结果:
浏览器输入http://localhost:7001,可以得到如下图结果:
3. 新建微服务模块:userapi01,userapi02
创建方式、resultful接口,以及配置 均和userapi一样。
配置不同的地方是:userapi01中application.yml中的server.port =7002
userapi02中application.yml中的server.port=7003
userapi01中的controller中的name:lucy00改为name:lucy01
userapi02中的controller中的name:lucy00改为name:lucy02
4. 新建微服务模块systemapi (包含fegin,用于调用userapi,userapi01,userapi02模块中的接口)
systemapi模块的pom.xml的配置文件:
4.0.0 org.springframework.boot spring-boot-starter-parent 2.3.7.RELEASE com.hauun systemapi 0.0.1-SNAPSHOT systemapi systemapi 1.8 Hoxton.SR9 org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-starter-openfeign org.springframework.cloud spring-cloud-starter-netflix-eureka-client org.springframework.boot spring-boot-starter-test test org.junit.vintage junit-vintage-engine org.springframework.cloud spring-cloud-dependencies ${spring-cloud.version} pom import org.springframework.boot spring-boot-maven-plugin
将systemapi模块中的application.properties文件改成application.yml文件,并进行如下配置
server: port: 7004 servlet: context-path: /systemapi #context-path不能省略,用于统一restful接口前缀 spring: application: name: system-service eureka: instance: prefer-ip-address: true client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://localhost:8000/eureka feign: #将systemapi伪装成消费端,调用userapi中的restful接口 client: config: default: connectTimeout: 5000 readTimeout: 5000 loggerLevel: basic okhttp: enabled: true hystrix: enabled: true
@EnableDiscoveryClient @EnableFeignClients注解systemapi块中的SystemapiApplication启动类
package com.hauun.systemapi; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class SystemapiApplication { public static void main(String[] args) { SpringApplication.run(SystemapiApplication.class, args); } }
创建controller类和Feign客户端类
package com.hauun.systemapi.feign; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; @FeignClient(name = "user-service") #name的值必须与被调用的微服务所在的模块在注册中心的serviceId一致 public interface UserFeignClient { @GetMapping("userapi/getUserInfo") #userapi是被调用的微服务所在模块配置的content-path的值,getUserInfo是被调用微服务的注解的值 public String getUserInfo(); }
package com.hauun.systemapi.controller; import com.hauun.systemapi.feign.UserFeignClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class DeptController { @Autowired private UserFeignClient userFeignClient; @GetMapping("getDeptInfo") public String getDeptInfo(){ String userInfo=userFeignClient.getUserInfo(); return userInfo+",dept:人力资源部"; } }
4. 新建客户端路由模块Zuul(包含Ribbon 负载均衡)
Zuul模块的pom.xml的配置文件:
4.0.0 org.springframework.boot spring-boot-starter-parent 2.3.7.RELEASE com.huaun zuul 0.0.1-SNAPSHOT zuul zuul 1.8 Hoxton.SR9 org.springframework.cloud spring-cloud-starter-netflix-eureka-client org.springframework.cloud spring-cloud-starter-netflix-ribbon org.springframework.cloud spring-cloud-starter-netflix-zuul org.springframework.boot spring-boot-starter-test test org.junit.vintage junit-vintage-engine org.springframework.cloud spring-cloud-dependencies ${spring-cloud.version} pom import org.springframework.boot spring-boot-maven-plugin
将Zuul模块中的application.properties文件改成application.yml文件,并进行如下配置
server: port: 8080 spring: application: name: zuul-service eureka: instance: prefer-ip-address: true client: fetch-registry: true register-with-eureka: true service-url: defaultZone: http://localhost:8000/eureka zuul: routes: user-service-rout: path: /userapi/** service-id: user-service stripPrefix: false system-service-rout: path: /systemapi/** service-id: system-service stripPrefix: false user-service: #负载均衡配置 ribbon: listOfServers: localhost:7000, localhost:7001,localhost:7002 NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
@EnableDiscoveryClient @EnableZuulProxy注解zuul块中的ZuulApplication启动类
package com.huaun.zuul; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @SpringBootApplication @EnableDiscoveryClient @EnableZuulProxy public class ZuulApplication { public static void main(String[] args) { SpringApplication.run(ZuulApplication.class, args); } }
依次启动zuul,userapi01,userapi02,systemapi模块服务
刷新http://localhost:8000,如下图:
访问userapi01:http://localhost:7002/userapi/getUserInfo
访问userapi02:http://localhost:7003/userapi/getUserInfo
访问systemapi模块:http://localhost:7004/systemapi/getDeptInfo
通过路由的负载均衡访问userapi模块:http://localhost:8080/userapi/getUserInfo
通过路由访问systemapi模块:http://localhost:8080/systemapi/getDeptInfo