一、注册中心介绍
- 各个服务间调用错综复杂,类似医院中医生和患者的关系一样,因此需要多个挂号中心(注册中心及集群),来告诉患者(消费方),哪些医生们(服务方及服务方集群)有空;
- Eureka注册中心是SpringCloud的一种注册中心,包含服务端(注册中心)和客户端(各微服务);
二、Eureka服务端及集群
1.pom依赖
<!--Eurake的服务端依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
2.主启动类
package org.zte;
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);
}
}
3.1 application.yaml(注册中心一)
- 单个eureka如果挂了,就会出现单点故障,因此采用eureka集群的方式;
- 各个eureka服务端互相注册,互相守望;
- 各个eureka服务端互相同步数据,如某个服务只要注册到集群一上,只要集群一和集群二互相注册,集群二就会自动同步集群一的数据;
server:
port: 7001
# eureka的配置
eureka:
# 注册中心server的名字,客户端不用配置
# 在下面访问地址时也做相应eureka01的配置
# 为了区分不同的注册中心,在host文件配置映射关系
# 127.0.0.1 eureka01
# 127.0.0.1 eureka02
instance:
hostname: eureka01
client:
# 是否向注册中心注册first_eureka本服务,注册中心不必向自己注册自己,默认为true
register-with-eureka: false
# 是否检索服务,一般是客户端开启这个功能,默认为true
fetch-registry: false
# 注册到了7002的注册中心上,但由于上面false,不会在注册中心显示
# defaultZone 必须用eureka02
service-url:
defaultZone: http://eureka02:7002/eureka
3.2 application.yaml(注册中心二)
server:
port: 7002
# eureka的相关配置
eureka:
instance:
hostname: eureka02
client:
# 是否向注册中心注册该服务,注册中心不必向自己注册自己,默认为true
register-with-eureka: false
# 是否检索服务,一般是客户端开启这个功能,默认为true
fetch-registry: false
service-url:
defaultZone: http://eureka01:7001/eureka
4.浏览器访问地址
# 四个地址均可访问到两个注册中心
http://localhost:7001
http://eureka01:7001
http://localhost:7002
http://eureka02:7002
5.验证集群搭建
- DS Replicas: 这个Eureka Server相邻节点,互为一个集群;
- 输入7001,DS为02; 输入7002,DS为01;表明集群搭建成功;
三、Eureka服务提供方集群
集群搭建只需要改变该服务的启动端口即可
1.pom依赖
<!--eureka客户端的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2.主启动类
package org.zte;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
/**开启eureka客户端注册功能,表明这是一个微服务的客户端*/
@EnableEurekaClient
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class,args);
}
}
3.application.yaml
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://120.79.28.20:3308/cloud
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
# 注册到服务中心的服务 实列名称,后续可以直接用该名称来调用服务
application:
name: cloud-order
# eureka的相关配置
eureka:
client:
# 是否向注册中心注册该服务,注册中心不必向自己注册自己,默认为true
register-with-eureka: true
# 是否检索当前注册中心上的服务,一般是客户端开启这个功能,默认为true
fetch-registry: true
# 注册到哪个eureke注册中心上面,eureka是固定写法
# localhost,eurake01,eureka02是等价的,都可以配置地址
service-url:
defaultZone: http://localhost:7001/eureka,
http://localhost:7002/eureka
四、Eureka消费服务端
pom依赖,主启动类,yam文件都类似服务提供方;
1.远程调用RestTemplate及负载均衡
package org.zte.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;
/**将该类放在Spring容器中*/
@Configuration
public class RestTemplateConfig {
/** Spring的,用于服务间调用的*/
@Bean
// 负载均衡,默认轮询
@LoadBalanced
public RestTemplate getTemplate(){
return new RestTemplate();
}
}
2.服务调用Controller
package org.zte.controller;
import io.swagger.annotations.Api;
import org.common.entity.OrderBO;
import org.common.result.ServiceData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("/pay")
public class PaymentController {
// 注册eureka后,不用再写ip地址和端口号,直接用eureka的服务名称
// 注册中心有两个cloud-order服务,默认轮询
private String serviceUrl = "http://cloud-order";
@Autowired
private RestTemplate restTemplate;
@GetMapping("/findById")
public ServiceData findById() {
ServiceData<OrderBO> serviceData = new ServiceData<OrderBO>();
serviceData = restTemplate.getForObject(serviceUrl + "/order/order/findById", ServiceData.class);
return serviceData;
}
}
3. 注册中心
五、注册中心信息完善
5.1 微服务主机名称和IP(端口)显示及修改
在客户端,加上如下两个标签,结合pom文件,注册中心上的服务的名字就可以改变,并且鼠标移上去,就可以出现当前服务的IP及端口
1: 添加actuator依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--web监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- 修改application.yaml文件
# eureka的相关配置
eureka:
# 可以在eureka界面显示当前实列的名称
# 鼠标移到当前实列上,会显示ip及端口,默认为false
instance:
instance-id: order_second
prefer-ip-address: true
client:
# 是否向注册中心注册该服务,注册中心不必向自己注册自己,默认为true
register-with-eureka: true
# 是否检索当前注册中心上的服务,一般是客户端开启这个功能,默认为true
fetch-registry: true
# 注册到哪个eureke注册中心上面,eureka是固定写法
service-url:
defaultZone: http://localhost:7001/eureka,
http://localhost:7002/eureka
默认用{电脑主机名}:{服务实列名}:{端口号}
修改后如下下图所示
5.2 自我保护机制
服务定期向注册中心发送心跳,当超过该时间,Eureka没有发现心跳,会继续等待一段时间(即保护机制),再将该服务从注册中心剔除;
保护步骤:
- 服务定期向注册中心汇报心跳; lease-renewal-interval-in-seconds: 2
- 超过一定心跳时间不会报,eureka会认为该服务已经挂掉;lease-expiration-duration-in-seconds: 1
- 再经过一定时间,将该服务剔除;evicti-interval-times-in-ms: 2000
注册中心
# eureka的相关配置
eureka:
# 注册中心的名字,只有注册中心才需要配置
# 在host文件配置映射关系
# 127.0.0.1 first_eureka
# 127.0.0.1 second_eureka
instance:
hostname: eureka02
client:
# 是否向注册中心注册该服务,注册中心不必向自己注册自己,默认为true
register-with-eureka: false
# 是否检索服务,一般是客户端开启这个功能,默认为true
fetch-registry: false
service-url:
defaultZone: http://eureka01:7001/eureka
server:
# 关闭自我保护机制,默认开启
# 没有收到心跳,2秒后剔除
enable-self-preservation: false
evicti-interval-times-in-ms: 2000
微服务
# eureka的相关配置
eureka:
# 可以在eureka界面显示当前实列的名称
# 鼠标移到当前实列上,会显示ip及端口,默认为false
instance:
instance-id: order_first
prefer-ip-address: true
# 服务每隔2秒向注册中心发送一次心跳,默认30秒
lease-renewal-interval-in-seconds: 2
# 注册中心在最后一次接受心跳后,等待的时间,默认为90秒,超时将剔除服务
lease-expiration-duration-in-seconds: 1
client:
# 是否向注册中心注册该服务,注册中心不必向自己注册自己,默认为true
register-with-eureka: true
# 是否检索当前注册中心上的服务,一般是客户端开启这个功能,默认为true
fetch-registry: true
# 注册到哪个eureke注册中心上面,eureka是固定写法
service-url:
defaultZone: http://localhost:7001/eureka,
http://localhost:7002/eureka
5.3 获取当前注册中心微服务的信息
在任意一个微服务中,只要该服务注册到了eureka注册中心上,就可以获取到当前注册中心注册的所有服务(医生可以通过医院公告发现所有的医生和患者的具体动态)
package org.zte.controller;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/service")
@Api(tags = "获取注册中心所有服务")
public class GetServiceInfo {
@Autowired
private DiscoveryClient discoveryClient;
// 获取注册中心所有服务的服务名,多个重名服务,按照一个来对待
@GetMapping("/getServiceNames")
public Object getServiceName() {
List<String> services = discoveryClient.getServices();
for (String service:services){
System.out.println(service);
}
return null;
}
// 根据服务名,获取具体该服务实例的信息
@GetMapping("/getServiceDetails")
public Object getServiceDetails() {
List<ServiceInstance> instances = discoveryClient.getInstances("cloud-order");
for (ServiceInstance instance:instances){
System.out.println(instance.getServiceId());
System.out.println(instance.getInstanceId());
System.out.println(instance.getPort());
System.out.println(instance.getUri());
}
return null;
}
}