spring cloud 之 Eureka
微服务是系统架构上的一种设计风格,他的主旨是将一个远不独立的系统拆分为多个小型服务,这些小型服务都是在各自独立的进程中运行,服务之间一般通过http的restfullAPI进行通信写作
Spring Cloud是一系列框架的有序集合
1、spring cloud 与dubbo的对比
- Spring Cloud 与 Dubbo 都是实现微服务有效的工具。
- Dubbo 只是实现了服务治理,而 Spring Cloud 子项目分别覆盖了微服务架构下的众多部件。
- Dubbo 使用 RPC 通讯协议,Spring Cloud 使用 RESTful 完成通信,Dubbo 效率略高于 Spring Cloud。
2、Eureka
Eureka是一个服务注册与发现的组件,包含两个组件:Eureka Server(注册中心)和Eureka Client(服务提供者、服务消费者)
Spring提供了一种键单便捷的模板类(RestTemplate),用于在java代码里面访问restful服务,其功能与HtppClient、okHttp类似,但是RestTemplate更舒适
实现步骤:
1、定义配置类获取模板类
1 @Configuration//创建模板配置类,定义此类为配置类 2 public class RestTemplateConfig { 3 4 @Bean 5 public RestTemplate restTemplate() { 6 return new RestTemplate(); 7 } 8 }
2、controller使用,注入RestTemplate,调用 getForObject(请求路径,字节码文件)方法
1 @RestController 2 @RequestMapping("/order") 3 public class OrderController { 4 5 @Autowired 6 public RestTemplate restTemplate; 7 8 @GetMapping("/goods/{id}") 9 public Goods findGoodsById(@PathVariable("id") int id){ 10 System.out.println("findGoodsById..."+id); 11 12 String url= "http://localhost:8000/goods/findOne/"+id; 13 //远程调用Goods服务中的findOne接口 14 Goods goods = restTemplate.getForObject(url, Goods.class); 15 return goods; 16 } 17 }
但是此时url是被写死,与别调用方的耦合较高,为了降低耦合,使用注册中心
Eureka进行注册中心的配置,需要搭建一个spring boot项目
- 配置eureka server
1、创建eureka server项目,导入spring cloud 、eureka server相关依赖
1 spring cloud 依赖 2 3 <spring-cloud.version>Greenwich.RELEASE</spring-cloud.version> 4 </properties> 5 6 <!--引入Spring Cloud 依赖--> 7 <dependencyManagement> 8 <dependencies> 9 <dependency> 10 <groupId>org.springframework.cloud</groupId> 11 <artifactId>spring-cloud-dependencies</artifactId> 12 <version>${spring-cloud.version}</version> 13 <type>pom</type> 14 <scope>import</scope> 15 </dependency> 16 </dependencies> 17 </dependencyManagement> 18 19 eureka server 依赖 20 <dependencies> 21 22 <dependency> 23 <groupId>org.springframework.boot</groupId> 24 <artifactId>spring-boot-starter-web</artifactId> 25 </dependency> 26 27 <!-- eureka-server --> 28 <dependency> 29 <groupId>org.springframework.cloud</groupId> 30 <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> 31 </dependency> 32 </dependencies>
2、 启动引导类上增加 @EnableEurekaServer 注解,开启eureka server
3、配置 application.yml文件
1 server: 2 port: 8761 3 # eureka 配置 4 # eureka 一共有4部分 配置 5 # 1. dashboard:eureka的web控制台配置 6 # 2. server:eureka的服务端配置 7 # 3. client:eureka的客户端配置 8 # 4. instance:eureka的实例配置 9 10 eureka: 11 instance: 12 hostname: localhost # 主机名 13 client: 14 service-url: 15 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka # eureka服务端地址,将来客户端使用该地址和eureka进行通信 16 17 register-with-eureka: false # 是否将自己的路径 注册到eureka上。eureka server 不需要的,eureka provider client 需要 18 fetch-registry: false # 是否需要从eureka中抓取路径。eureka server 不需要的,eureka consumer client 需要
- eureka client
1、导入eureka client依赖
1 <!-- eureka-client 坐标 start- 不要导错了 --> 2 3 <dependency> 4 <groupId>org.springframework.cloud</groupId> 5 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> 6 7 </dependency>
2、引导类上添加@EnableEurekaClient //该注解 在新版本中可以省略 启动客户端
3、配置 application.yml文件
1 server: 2 port: 8001 3 4 eureka: 5 instance: 6 hostname: localhost # 主机名 7 client: 8 service-url: 9 defaultZone: http://localhost:8761/eureka # eureka服务端地址,将来客户端使用该地址和eureka进行通信 10 spring: 11 application: 12 name: eureka-provider # 设置当前应用的名称。将来会在eureka中Application显示。将来需要使用该名称来获取路径
- 动态代码获取路径路径
1、在引导类上添加注解@EnableDiscoveryClient // 激活DiscoveryClient
2、controller中注入对象 调用方法
1 @RestController 2 @RequestMapping("/order") 3 public class OrderController { 4 5 @Autowired 6 private RestTemplate restTemplate; 7 @Autowired 8 private DiscoveryClient discoveryClient; 9 10 @GetMapping("/goods/{id}") 11 public Goods findGoodsById(@PathVariable("id") int id){ 12 System.out.println("findGoodsById..."+id); 13 14 //从eureka server中获取provider的ip和端口 15 /* 16 1 注入discoveryClient对象并激活 17 2 调用方法 18 */ 19 List<ServiceInstance> instances = discoveryClient.getInstances("EUREKA-PROVIDER"); 20 21 if (instances ==null || instances.size()==0){ 22 return null; 23 } 24 //这里是集合的原因是,后期可能是集群,要有多个实例 25 ServiceInstance serviceInstance = instances.get(0); 26 String host = serviceInstance.getHost(); 27 int port = serviceInstance.getPort(); 28 29 String url= "http://"+host+":"+port+"/goods/findOne/"+id; 30 //远程调用Goods服务中的findOne接口 31 Goods goods = restTemplate.getForObject(url, Goods.class); 32 return goods; 33 }
Eureka 属性
instance相关属性 (客户端的属性)
1 eureka: 2 instance: 3 hostname: localhost #主机名 4 prefer-ip-address: #是否将自己的ip注册到eureka中,默认false注册 主机名 5 ip-address: #设置当前实例ip 6 instance-id: #设置web控制台显示的实例id ip:应用名称:端口号7 lease-renewal-interval-in-seconds: 30 #每一次client向server发送心跳包的时间间隔 8 lease-expiration-duration-in-seconds:90 # 如果90秒以内server没有收到eureka的心跳包,则剔除该服务
server相关属性
eureka: server: enable-self-preservation: #是否开启自我保护机制,默认true eviction-interval-timer-in-ms: # 清理间隔(单位毫秒,默认是60*1000)
理解什么是Eureka的自我保护机制
Eureka默认开启自我保护机制, 客户端client默认每30s会向server发送一次心跳包,当
server 如果90s都没有接受到client的心跳包,则剔除该服务,假如有一个服务出问题了(一共3个服务),由于默认开启自我保护机制,这个时候,server就会进行一个计算,实际得到的续约值(心跳1分钟)2*2=4个(死的不参与计算);理论需要的续约值(3+1)*2*0.85=6个(n+1,85%的成功率),此时两者不相等,那么自我保护就启动了,此时有个默认清理时间60s,在这个时间段内,依旧保存此时的客户端服务地址,提高可用性
Eureka 高可用 集群的搭建
准备多个eureka-server 进行集群的搭建只需要将这多个server之间进行互相注册
1 server: 2 port: 10086 3 4 # Eureka 配置一共有4个部分 5 # 1. dashboard: eureka的web控制台 6 # 2. server: eureka的服务端配置 7 # 3. client: eureka的客户端配置 8 # 4. instance: eureka的实例配置 9 10 eureka: 11 instance: 12 hostname: eureka-server # 主机名 注意单机版本需要将这 etc中的主机名进行修改 13 prefer-ip-address: true 14 ip-address: 127.0.0.1 15 instance-id: ${eureka.instance.ip-address}:${spring.application.name}:${server.port} 16 client: 17 service-url: 18 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka,http://eureka-server1:10087/eureka 19 # eureka服务端地址,将来客户端使用该地址和eureka进行通信 20 21 register-with-eureka: true # 是否将自己的路径注册到eureka上,默认为true server可以不需要,client需要 22 fetch-registry: false # 是否需要从eureka中抓取路径 默认为true server不需要,client需要 23 spring: 24 application: 25 name: eureka-server
客户端需要的是将server的服务地址都进行注册通信
1 server: 2 port: 9000 3 4 eureka: 5 client: 6 service-url: 7 defaultZone: http://eureka-server:10086/eureka,http://eureka-server1:10087/eureka #都进行注册 8 instance: 9 hostname: localhost 10 11 spring: 12 application: 13 name: eureka-consumer
3、Consul
Consul 是由 HashiCorp 基于 Go 语言开发的,支持多数据中心,分布式高可用的服务发布和注册服务软件。
用于实现分布式系统的服务发现与配置。
下载并安装,运行就可以了 ./consul 就可以执行运行
使用步骤
- 导入坐标
- 1 <dependency> 2 <groupId>org.springframework.cloud</groupId> 3 <artifactId>spring-cloud-starter-consul-discovery</artifactId> 4 </dependency>
- 配置文件配置
-
1 server: 2 port: 8000 3 spring: 4 cloud: 5 consul: 6 host: localhost # consul 服务端的 ip 7 port: 8500 # consul 服务端的端口 默认8500 8 discovery: 9 service-name: ${spring.application.name} # 当前应用注册到consul的名称 10 prefer-ip-address: true # 注册ip 11 12 application: 13 name: consul-provider # 应用名称
其他使用与 Eureka一致,默认的图形化界面端口号为8500
4、Nacos
Nacos(Dynamic Naming and Configuration Service) 是阿里巴巴2018年7月开源的项目
使用步骤:
- 导入坐标
-
1 <!--nacos--> 2 <dependency> 3 <groupId>org.springframework.cloud</groupId> 4 <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> 5 <version>0.2.2.RELEASE</version> 6 </dependency> 7 <dependency> 8 <groupId>com.alibaba.nacos</groupId> 9 <artifactId>nacos-client</artifactId> 10 <version>1.1.0</version> 11 </dependency>
- 配置配置文件
-
1 server: 2 port: 9000 3 4 5 spring: 6 cloud: 7 nacos: 8 discovery: 9 server-addr: 127.0.0.1:8848 # 配置nacos 服务端地址 10 application: 11 name: nacos-consumer # 服务名称其他使用与 Eureka一致,默认的图形化界面端口号为8500
其他使用与 Eureka一致,默认的图形化界面端口号为8848/nacos 登录账号密码都为nacos