1.什么是eureka
eureka(服务发现框架)是Netflix开源的服务发现组件,本身是一个基于rest(一种软件架构风格)的服务。它包含server和client两部分。springcloud将它集成在子项目springcloudNetflix中。
功能:微服务的注册与发现
2.eureka原理
我们可以看下eureka的架构图
其中 application service可以理解为服务提供者,application client为服务消费者,make remote call为调用restful api 的行为,而us-east-1c,us-east-1d等都是zone,都属于us-east-1这个region
有图可知,eureka包括server和client两个组件,他们的作用分别是:
eureka server:提供服务发现的能力,各个微服务启动时,会向注册中心(eureka server)注册自己的信息(例如IP,端口,微服务名称等),注册中心会存储这些信息。
eureka client:这是Java客户端,用于简化与eureka server的交互,提供微服务(服务提供者)。
微服务启动后,会周期性的(默认30秒)向eureka server 发送心跳使得自己keep alive。如果在一定时间内(默认90秒)注册中心没有接收到某个微服务的心跳,注册中心会注销该实例。这使得系统具有灵活性。
eureka client 会缓存服务注册表中的信息,这使得微服务无须每次请求都得查询eureka server,提高了效率,此外,即使eureka server 所有的节点都宕掉,client 依然可以利用缓存中的信息找到服务提供者并完成调用,保证了系统的高可用性。
3.简单的代码实现
3.1首先是编写一个eureka server(注册中心)
3.1.1pom文件引入相关的依赖(eureka依赖)
<!-- eureka依赖导入服务端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
这里最好把spring cloud 父依赖也引入进来,避免手动配置版本,出现各种奇怪的问题。
<dependencyManagement>
<!-- spring cloud 父依赖导入 版本控制 避免自己手动选择版本出错-->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
3.1.2编写启动类,重点是添加注解@EnableEurekaServer
//启动类入口需要增加注解@EnableEurekaServer
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
3.1.3在配置文件application.propercitis添加一下配置
其中两个置为false是关键,将自己声明为eureka server。配置完成后,启动即可。
#eureka服务的端口
server.port=8080
#服务名称
spring.application.name=eureka-zeron
#优先IP
eureka.instance.prefer-ip-address=true
#不要获取注册表中的信息(服务端)
eureka.client.fetch-registry=false
#防止将自己注册到注册中心去(服务端)
eureka.client.register-with-eureka=false
#eureka server地址
eureka.client.service-url.defaultZone=http://localhost:8080/eureka/
3.2 将微服务注册到eureka server上
3.2.1pom文件引入依赖
<!-- eureka相关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
3.2.1编写一个微服务,提供接口供调用。(以订单服务为例)部分代码如下:
//通过ID可以查询对应商品的信息,或者selectAll返回所有商品的信息
@RestController
@RequestMapping("/myTest")
public class goodController {
@Autowired
private GoodService goodService;
@RequestMapping(value = "/getGoodByID",method = RequestMethod.GET)
public String getGood(int goodID){
return goodService.getGoodInfo(goodID).toString();
}
@RequestMapping("/selectAll")
@ResponseBody
public List<Good> ListGood(){
return goodService.selectAll();
}
}
3.2.2在配置文件application.propercitis添加一下配置
#eureka-client
#自己的运行端口
server.port=8099
#服务名称
spring.application.name=eureka-miss
#优先IP
eureka.instance.prefer-ip-address=true
#获取注册表中的信息
eureka.client.fetch-registry=true
#注册到eureka-server
eureka.client.register-with-eureka=true
#注册地址(与前面的eureka-server地址一致)
eureka.client.service-url.defaultZone=http://localhost:8080/eureka/
这里与eureka-server不同的在于,当然也可以不写,默认为true。
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
3.2.3编写启动类,加入注解@EnableEurekaClient
@SpringBootApplication
@EnableEurekaClient
public class EurekaClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication.class, args);
}
}
值得一提的是
至此,完成了一个eureka-server(注册中心)的搭建,并将一个微服务注册在上面。
4.eureka高可用
刚前面提到,eureka-client利用缓存机制,即使在eureka-server宕机的情况下,仍然可以通过缓存中的信息找到微服务并完成调用。现在假定出现这样的情况,eureka-server宕机的同时,某些微服务也出现了不可用的情况,如果eureka-client中的缓存不被更新,就会影响到微服务之间的调用,甚至影响到整个系统的高可用性,因此,在实际生产环境中,我们需要部署一个高可用的eureka-server集群。
我们前面在编写单节点eureka-server时,在配置文件中添加了以下内容
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka server 可以通过运行多个实例并且相互注册的方式实现高可用部署,eureka server实例会彼此增量地同步信息,从而确保所有节点数据一致。实现方式非常简单,只需将上述两项置为ture(或者不写),然后注册到另外一个注册中心上去,这里的注册中心地址不再是它本身,而是另外一个注册中心的地址,它本身作为eureka client 注册到上面去。配置文件如下:
server.port=8081
#eureka
#服务名称
spring.application.name=eureka-miss
eureka.instance.prefer-ip-address=true
#另外一个注册中心的地址
eureka.client.service-url.defaultZone=http://localhost:8080/eureka/
这样就实现了将节点2注册到节点1的过程。接下来是将服务注册到eureka server 集群上。
实现也非常简单,如下所示,只需要配置多个eureka server地址即可,地址之间用,隔开。
eureka.client.service-url.defaultZone=http://localhost:8080/eureka/,http://localhost:8081/eureka/
5.feign实现微服务之间的调用
5.1feign简介
Feign是Netflix开发的声明式、模板化的HTTP客户端, Feign可以帮助我们更快捷、优雅地调用HTTP API。
在Spring Cloud中,使用Feign非常简单——创建一个接口,并在接口上添加一些注解,代码就完成了。Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。
Spring Cloud对Feign进行了增强,使Feign支持了Spring MVC注解,并整合了Ribbon和Eureka,从而让Feign的使用更加方便。
Spring Cloud Feign是基于Netflix feign实现,整合了Spring Cloud Ribbon和Spring Cloud Hystrix,除了提供这两者的强大功能外,还提供了一种声明式的Web服务客户端定义的方式。
Spring Cloud Feign帮助我们定义和实现依赖服务接口的定义。在Spring Cloud feign的实现下,只需要创建一个接口并用注解方式配置它,即可完成服务提供方的接口绑定,简化了在使用Spring Cloud Ribbon时自行封装服务调用客户端的开发量。
Spring Cloud Feign具备可插拔的注解支持,支持Feign注解、JAX-RS注解和Spring MVC的注解。
5.2feign简单实践
这里编写两个服务(用户服务和订单服务)和一个服务注册中心,两个服务注册在注册中心上并且能够相互访问,订单服务提供一个接口,该接口作用是可以通过商品ID获取商品信息(单价,种类,库存等),用户服务使用openfeign通过注册中心实现对该接口的调用。接口具体实现逻辑不再展示,主要看如何使用feign实现微服务间调用。
首先是往调用者的pom文件里引入依赖,被调用者不需要引入。
<!-- 引入openfeign依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
接着是创建一个feign接口,并且添加@FeignClient注解,如下所示
//必须加入component注解 否则在controller层无法注入,加入component 把对象创建交给spring完成
@Component
//加入这个注解 并且name值必须与被调用服务注册在注册中心上的名称一致
@FeignClient(name = "HONGSHEN-WEAVING")
public interface GoodService {
//这个value值要与被调用的服务里面的路径一致
@RequestMapping(value = "/myTest/getGoodByID",method = RequestMethod.GET)
//记住加入@RequestParam("goodID") 否则会报错(500)
String findByID(@RequestParam("goodID") int goodID);
//返回所有的商品列表
@RequestMapping("/myTest/selectAll")
List selectAllGood();
}
在controller层添加代码,调用该feign接口
@Autowired
private GoodService goodService;
//
@GetMapping("/findGoodByID")
public String findGoodByID(int goodID){
return goodService.findByID(goodID);
}
往启动类添加注解@EnableFeignClients
//必须加入@EnableEurekaClient和@EnableFeignClients注解
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class SpringdemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringdemoApplication.class, args);
}
}
至此配置完成,启动注册中心,启动微服务,在地址栏输入对应URL,即可实现微服务间调用。