eureka搭建集群服务
前言
记录eureka搭建分布式服务集群的过程,后续编写hystrix
eureka是AP结构的注册中心服务
eureka是主要三大作用就是服务治理、服务发现、服务注册。
eureka分客户端和服务端,服务端作为注册中心,管理注册进来的客户端服务。
客户端服务分为 consumer 和provider
consumer 请求eureka server ,eureka server会将请求发给对应的provider(eurekaserver 只是找到请求,实际请求还是consumer和provider之间的请求),如果provider是集群会通过负载均衡后进行请求(当然负载均衡需要开启的)。
搭建顺序
(一)eureka server 搭建
引入依赖:
spring boot 依赖,注意版本spring cloud和spring boot 版本之间有依赖关系
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
spring cloud eureka 依赖
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<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>
启动类需要添加注解
@SpringBootApplication
@EnableEurekaServer //开启eureka 服务端 注意eureka分客户端和服务端 @EnableEurekaClient是客户端 @EnableEurekaServer是服务端
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
编写配置文件
server:
port: 8000 #eureka暴露的端口号
eureka:
instance:
hostname: eureka-server #eureka的服务名
client:
register-with-eureka: false #不把自己注册到eureka上
fetch-registry: false #不从eureka上来获取服务的注册信息
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #eureka的服务地址
eureka server 注册中心搭建完成
启动服务
请求设置对应端口号的地址,显示该界面就是搭建完成了。
(二)application server provider搭建
provider作为客户端需要把自身注册到eureka server 注册中心中,让consumer 能够调用。
引入依赖:
spring boot 依赖,注意版本spring cloud和spring boot 版本之间有依赖关系
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<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>
启动类
@SpringBootApplication
@EnableEurekaClient //开启eureka provider客户端
public class ProviderServerApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderServerApplication.class, args);
}
}
编写配置文件
instance-id 配置效果看下图右侧红框
prefer-ip-address 配置效果看下图左侧红框
server:
port: 8100
spring:
application:
name: provider-server #注册到eureka server 的服务名
eureka:
client:
service-url:
defaultZone: http://localhost:8000/eureka/ #可以写ip 可以把ip写到host文件弄成域名
instance:
instance-id: provider001 #自定义在eureka server 中显示的服务名
prefer-ip-address: true #eureka server 可以查看ip
配置完成之后,运行程序,然后刷新eureka server 注册中心界面,发现服务已经注册成功了。
红字不用在意,这是eureka的自我保护机制,不影响使用。
编写简单的程序进行服务的调用并自测通过。后续会使用到
@RestController
@RequestMapping("/v1/provider")
public class ProviderController {
@Value("${server.port}")
private String port;
@GetMapping("providerinfo")
public String providerInfo()
{
return String.format("这里是provider第%s号,",port);
}
}
(三)client server consumer搭建
引入依赖:
依赖和provider基本一致
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<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>
启动类
@SpringBootApplication
@EnableEurekaClient
public class ConsumerServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerServerApplication.class, args);
}
}
编写配置文件
instance-id 配置效果看下图右侧红框
prefer-ip-address 配置效果看下图左侧红框
server:
port: 8200
spring:
application:
name: consumer-server #注册到eureka server 的服务名
eureka:
client:
service-url:
defaultZone: http://localhost:8000/eureka/ #可以写ip 可以把ip写到host文件弄成域名
instance:
instance-id: consumer001 #自定义在eureka server 中显示的服务名
prefer-ip-address: true #eureka server 可以查看ip
启动eureka server之后再启动客户端,查看注册中心。
(四)单服务测试
到这一个基础的单服务架构就搭建完成了,接下来进行服务之间的访问代码编写。
consumer端服务请求代码–RestTemplate
使用resTemplate进行服务之间的请求
resTemplate 是restful风格的请求方式。内置不同请求方式的方法get、post、delet、patch、put,以及通用的exexute,通过参数执行请求方式。
第一步:编写配置文件把resTemplate 注入到spring ioc容器中
注解@LoadBalanced 很重要,是开启负载均衡的意思,没有这个注解无法使用服务名请求。
@Configuration
@LoadBalanced
public class ConsumerConfig {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
第二步:编写客户端请求代码,
@RestController
@RequestMapping("/v1/consumer")
public class ConsumerResTemplateController{
@Autowired
RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/consumerToProviderInfo")
public String consumerToProviderInfo() {
//这两行代码获取服务的信息,额为知识点,对方法不会产生影响
//参数是服务名
List<ServiceInstance> serviceInstances = discoveryClient.getInstances("provider-server");
ServiceInstance serviceInstance = serviceInstances.get(0);
//地址格式 服务名加 请求的地址
String forObject = restTemplate.getForObject("http://provider-server/v1/provider/providerinfo", String.class);
return forObject;
}
}
第三步:请求客户端地址http://localhost:8200/v1/consumer/consumerToProviderInfo
返回值:这里是provider第8100号,
consumer端服务请求代码–openFeign
OpenFeign:将提供者的restful服务伪装成接口进行消费,消费者只需要通过feign接口+注解就可以直接调用提供者的服务,而无需通过restTemplate方式进行调用
注意一点,openFeign内置了负载均衡器-Ribbon
第一步:引入openfeign依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
第二步:启动类上添加启动 feign注解
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class ConsumerServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerServerApplication.class, args);
}
}
第三步:定义一个feign接口
@FeignClient(value = "provider-server",path = "/v1/provider")
public interface ConsumerOpenFeignService {
@GetMapping("/providerinfo")
public String providerInfo();
}
第四步:定义controller类
@RestController
@RequestMapping("/v1/consumer")
public class ConsumerOpenFeignController {
@Autowired
private ConsumerOpenFeignService consumerOpenFeignService;
@GetMapping("/consumerOpenFeignInfo")
public String consumerToProviderInfo() {
String forObject = consumerOpenFeignService.providerInfo();
return forObject;
}
}
第五步:请求http://localhost:8200/v1/consumer/consumerOpenFeignInfo
结果:这里是provider第8100号,
(五)eureka server 集群原理
单个注册中心,在服务器异常时,会导致整个系统宕机,无法正常运行。为了避免这种情况就需要多部署几台注册中心组成集群。大大降低宕机概率。
Eureka Server 是一个服务,也可以是一个客户端。也就是说们我们可以配置多个Eureka Server,让他们之间相互注册,当服务提供者向其中一个Eureka注册服务时,这个服务就会被共享到其他Eureka上,这样所有的Eureka都会有相同的服务。
Eureka Server 的连接方式,可以是单线的,也就是三台服务器A注册到B,B注册到C,当B宕机时会导致A和C连接不上,所以我们需要把自身注册到除了自身之外的所有eureka server中。
值得注意的是,虽然eureka server之间是数据共享的,但是在provider server在注册时我们还是需要注册到集群中的每个eureka server中,因为如果只注册到其中一个,当这个服务异常时,另外的服务的信息同样的会消失
(六)eureka server 集群搭建
搭建过程:
第一步:创建一个新的eureka server 端口和第一个eureka server区分开,因为我们是在本地进行测试,为了能够更清晰的查看集群,我们修改本地的host文件,文件地址:C:\Windows\System32\drivers\etc\hosts,
127.0.0.1 eurekaserver8000
127.0.0.1 eurekaserver8001
然后配置文件的服务地址进行修改。
eureka server 8000
server:
port: 8000 #eureka暴露的端口号
eureka:
instance:
hostname: eureka-server #eureka的服务名
client:
register-with-eureka: false #不把自己注册到eureka上
fetch-registry: false #不从eureka上来获取服务的注册信息
service-url:
defaultZone: http://eurekaserver8001:8001/eureka/ #集群中其他的注册中心服务地址,多个服务用逗号隔开
eureka server 8001
server:
port: 8001 #eureka暴露的端口号
eureka:
instance:
hostname: eureka-server #eureka的服务名
client:
register-with-eureka: false #不把自己注册到eureka上
fetch-registry: false #不从eureka上来获取服务的注册信息
service-url:
defaultZone: http://eurekaserver8001:8000/eureka/ #集群中其他的注册中心服务地址,多个服务用逗号隔开
启动类上记得机上@EnableEurekaServer注解
启动两个服务,能正常显示注册的服务就算搭建完成了。
(七)application server provider集群创建
第一步:对 application server provider搭建章节搭建的项目进行修改端口号和自定义的服务名,然后进行打包。
第二步:用java -jar 命令进行启动。
第三步:idea 启动provider服务
第四步:idea启动consumer服务
第五步:请求测试方法地址 http://localhost:8200/v1/consumer/consumerOpenFeignInfo
结果就可一看到每次请求返回不同端口号的返回值,依旧说明我们的负载均衡生效了并且provider集群搭建完成。