开发步骤
- 引 pom
- 改yaml
- 主启动类添加注解
- 启动项目,登录地址
新版eurake的依赖分成了两个依赖一个是server,一个是client,便于开发管理
服务端
pom
新版eurake的依赖分成了两个依赖一个是server,一个是client,便于开发管理
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
单机版yaml
server:
port: 8001
#单机模式
eureka:
instance:
hostname: localhost #eureka服务端的实例名称
client:
register-with-eureka: false #是否向注册中心注册自己 ,因为自己就是注册中心 所以不用向自己注册自己
fetch-registry: false # 发现服务列表,因为自己是注册中心 所以不用发现
service-url:
#单机版注册地址,写自己的地址 如果是集群,则把后面的值改成 其它的 注册中心 对应的地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
集群版yaml
集群就是相互注册, 注册中心A注册到注册中心B ,注册中心B注册到注册中心A
service-url:defaultZone 原本写自己这个注册中心的地址,现在改成写其他注册中心的地址了。多个地址用逗号隔开。
设置两台注册中心 8001和8002
8001的ymal
server:
port: 8001
#单机模式
eureka:
instance:
hostname: localhost #eureka服务端的实例名称
client:
register-with-eureka: false #是否向注册中心注册自己 ,因为自己就是注册中心 所以不用向自己注册自己
fetch-registry: false # 发现服务列表,因为自己是注册中心 所以不用发现
service-url:
#此处协商8002的注册地址
defaultZone: http://localhost:8002/eureka/
8002的yaml
server:
port: 8002
#单机模式
eureka:
instance:
hostname: localhost #eureka服务端的实例名称
client:
register-with-eureka: false #是否向注册中心注册自己 ,因为自己就是注册中心 所以不用向自己注册自己
fetch-registry: false # 发现服务列表,因为自己是注册中心 所以不用发现
service-url:
#此处写上8001的注册地址
defaultZone: http://localhost:8001/eureka/
启动
朱启动类上加注解eureka server端启动注解 @EnableEurekaServer
注意可client端的启动注解 @EnableEurekaSlient 区分
浏览器输入 localhost:端口号 即可进入eureka 的ui界面
client端
pom
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
单机版yaml
server:
port: 9001
spring:
application:
name: provider-service #这个name 会在注册中心中显示
eureka:
client:
#表示是否将自己注册进EurekaServer默认为true,注册中心的才为false
register-with-eureka: true
#是否从EurekaServer抓取已有的注册消息,默认为true,单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
#单机版
defaultZone: http://localhost:8001/eureka/
instance:
instance-id: provider9001 #主机名的修改
prefer-ip-address: true #访问路径可以显示ip
#Eureka客户端向服务端发送心跳的实际间隔,单位为秒(默认为30秒)
lease-renewal-interval-in-seconds: 1
#Eureka服务端收到最后一次心跳后等待时间上线,单位为秒(默认为90秒) 超时将剔除服务
lease-expiration-duration-in-seconds: 2
不想让服务注册金eureka 则把 register-with-eureka: true 改成false即可。
集群版yaml
与服务端的集群配置类似。
集群版的yaml相对于单机版只有一个地方改动了 ,defaultZone位置
单机版时只写一个注册中心的地址,集群版则协商多个注册中心的地址,多个地址用逗号隔开
service-url:
#集群版
defaultZone: http://localhost:8001/eureka/,http://localhost:8002/eureka/
启动
在追启动类上加@EnableEurekaClient , eureka client端的启动注解
部分参数在注册中心上的显示
instance-id: provider9001 #主机名的修改
spring.application.name: provider-service #这个app name会显示在注册中心中
prefer-ip-address: true #访问路径可以显示ip 这个参数把鼠标点在eureka界面上的主机名上就会显示ip。
映射主机地址
为什么修改
在配置集群的时候 需要映射主机地址,修改hosts文件
不然eureka的ui的显示的注册中心的名称都是 localhost,无法区分到底是哪台注册中心
如8001显示的 8002注册中心名字为 localhost.,而8002注册中心显示的8001的名字也为localhost,无法分清localhost到底指的是哪一台注册中心,所以需要映射主机地址
ps: DS Replicas显示的是其它伙伴(注册中心)的ip地址 ,
即
defaultZone:http://localhost:8001/eureka
中的 localhost。
如果把defaultZone改成
defaultZone:http://映射后的ip地址:8001/eureka
在DS Replicas上也会显示成 “映射后的ip地址”,
下面两图示 未映射的时候的显示:
修改hosts映射
修改yaml配置
需要修改两个地方
- hostname 改这个方便根据名字在代码中获取实例
- defaultZone: 改这个 是为了在ui界面上显示
这是8001修改后的yaml,8002与8001配置一样
server:
port: 8001
#单机模式
eureka:
instance:
hostname: eureka8001.com #eureka服务端的实例名称
client:
register-with-eureka: false #是否向注册中心注册自己 ,因为自己就是注册中心 所以不用向自己注册自己
fetch-registry: false # 发现服务列表,因为自己是注册中心 所以不用发现
service-url:
#单机版注册地址,写自己的地址 如果是集群,则把后面的值改成 其它的 注册中心 对应的地址
defaultZone: http://eureka8002.com:8002/eureka/
eureka UI 显示
8001的界面的 DS 显示
自我保护机制
eureka的自我保护机制默认是开启的,为了避免因为网络波动不能及时接受到心跳而错杀正常的服务器的情况。
server端配置
eureka:
server:
#eureka 的自我保护机制,默认开启 ,不会立即清除不可以的服务。默认好像是90s
#现在 我们关闭自我保护 不可用的服务直接在设置的时间后iqngchu
enable-self-preservation: false
eviction-interval-timer-in-ms: 2000 #注册中心认为某个服务挂掉后,再等2s就把这个服务干掉
client端配置
instance:
instance-id: provider9001 #主机名的修改
prefer-ip-address: true #访问路径可以显示ip #访问路径可以显示 ip地址 在eureka页面上 需要健康检查依赖
#Eureka客户端向服务端发送心跳的实际间隔,单位为秒(默认为30秒)
# 默认发送心跳是30s一次 现在测试eureka的自我保护机制 改成1s一次
lease-renewal-interval-in-seconds: 1 #续约更新时间间隔,一般设置比续约到期时间少,该配置表示,每隔多少秒就向服务端发送心跳。
#eureka服务在 在收到最后一次心跳后等待时间上限, 单位为秒(默认是90秒), 超时将刷除服务
lease-expiration-duration-in-seconds: 2 #续约到期时间,可以单独给每个服务设置,如果在多少秒 内没有给服务发送心跳,则剔除该服务。换言之就是:超过2s还没发心跳,你服务端就当我挂了
服务实际剔除时间 = client续约时间 + server认为服务挂了之后又继续等待的时间
远程调用
如果不想使用openfeign / feign 调用微服务,可以使用 spring的 RestTemplate 来调用
配置类
package com.li.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @author liql
* @date 2021/8/7
*/
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced //开启负载均衡,就可以根据eureka上的服务名称进行调用了 不用再做与eureka的相关配置
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
@LoadBalanced 注解
当远程调用的程序时写死的时候 如 url=“http://localhost:端口号/请求地址” 时可以不用添加该注解
resttemplate 的api的使用 ,可以通过源码注释自行了解
package com.li.controller;
import com.li.entities.Provider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* @author liql
* @date 2021/8/7
*/
@RestController
public class ConsulController {
//远程调用需要有个url 定义url 这个是单个提供者的 可以写死,多个提供者就不行了
private static final String PROVIDER_URL="http://localhost:9001/";
@Autowired
private RestTemplate restTemplate;
@PostMapping("consul")
public String create(@RequestBody Provider provider){
//若要携带参数 (这里的是 provider 对象) 远程接口需要添加 @RequestBody 注解来解析 (当成json解析)
return restTemplate.postForObject(PROVIDER_URL+"provider",provider,String.class);
}
}
如果使用 在eureka中注册的名字, 只需要打开该负载均衡注解,默认是轮询,
不需要在进行其它任何的配置,哪怕是有多个服务提供者
package com.li.controller;
import com.li.entities.Provider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* @author liql
* @date 2021/8/7
*/
@RestController
public class ConsulController {
//集群的微服务地址要写成微服务的名称 同时开启 RestTemplate的负载均衡功能
private static final String PROVIDER_URL="http://PROVIDER-SERVICE/";
@Autowired
private RestTemplate restTemplate;
@PostMapping("consul")
public String create(@RequestBody Provider provider){
//若要携带参数 (这里的是 provider 对象) 远程接口需要添加 @RequestBody 注解来解析 (当成json解析)
return restTemplate.postForObject(PROVIDER_URL+"provider",provider,String.class);
}
}