spring-could的服务管理--eureka
一 . 服务注册中心
1. 导入服务端依赖
org.springframework.cloud spring-cloud-starter-netflix-eureka-server2. yml文件配置
spring:
application:
name: eurekaserver
server:
port: 8761
eureka:
instance:
# #配置运行实例
hostname: localhost
client:
service-url:
#配置eureka的服务路径,也就是客户端去管理中心的访问路径
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
# 是否注册自身
register-with-eureka: false
# 是否抓取注册信息
fetch-registry: false
3. 使用注解标识eureka的服务端
package com.gw;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer//标识这个项目是eureka的服务端
@SpringBootApplication
public class GwEurekaserverApplication {
public static void main(String[] args) {
SpringApplication.run(GwEurekaserverApplication.class, args);
}
}
二 . 生产者注册服务
1. 导入依赖
<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-client</artifactId>
</dependency>
2. 配置yml
# 应用服务 WEB 访问端口
server:
port: 9090
spring:
application:
name: producerService
# 配置注册中心地址
# 表示这个项目要注册到哪个注册中心
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
3. 使用注解标识客户端
package com.gw.gw_producer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient //标识消费者作为eureka的客户端服务
public class GwProducerApplication {
public static void main(String[] args) {
SpringApplication.run(GwProducerApplication.class, args);
}
}
4. 生产者生产接口
package com.gw.gw_producer.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ProductController {
@RequestMapping("/hello")
public String hello(String name) {
return "hello : " + name+"----producer hello";
}
}
三 . 消费者通过注册中心消费
1. 导入依赖
<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-client</artifactId>
</dependency>
2. 配置yml
# 应用服务 WEB 访问端口
server:
port: 9091
spring:
application:
name: producerService
# 配置注册中心地址
# 表示这个项目要注册到哪个注册中心
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
3. 使用注解标识客户端
package com.gw;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class GwConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(GwConsumerApplication.class, args);
}
}
4. 创建配置文件来注入对象
package com.gw.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class EurekaConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
5. 创建消费接口访问注册中心
package com.gw.controller;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class ConsumerController {
@Autowired
RestTemplate restTemplate;
@Autowired
EurekaClient eurekaClient;
@RequestMapping("/hello")
public String hello(String name) {
System.out.println(name);
//根据eureka的服务编号来获取服务实例
//表示消费者去使用哪个生产者的服务
InstanceInfo instanceInfo = eurekaClient.getNextServerFromEureka("PRODUCERSERVICE", false);
//根据服务实例获取生产者的访问根路径
String homePageUrl = instanceInfo.getHomePageUrl();
//拼接URI
String uri = homePageUrl + "/hello?name=" + name;
// String uri = "http://localhost:9090/hello?name=" + name;
//访问URI并获取返回值
String result = restTemplate.getForObject(uri, String.class);
return result;
}
}
四 . eureka安全配置
1. 导入依赖
在服务注册中心导入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2. 配置用户账号
在服务注册中心的yml文件配置用户名和密码,当其他服务注册服务时,必须使用此用户名和密码才可以成功注册
spring:
security:
user:
name: root
password: 123456
eureka:
client:
service-url:
#配置eureka的服务路径,也就是客户端去管理中心的访问路径
defaultZone: http://root:123456@localhost:8761/eureka
3. 注册服务
在其他服务注册的yml配置文件上从新配置服务注册中心的路径
eureka:
client:
service-url:
defaultZone: http://root:123456@localhost:8761/eureka
五 . Eureka高可用
为了防止服务注册中心宕机,导致服务奔溃,我们需要实现Eureka高可用.
配置多个Eureka实例
1. 将服务注册中心的项目更改为多实例模式
2. 服务注册中心配置
- 将服务注册中心更改如下配置,使得Eureka可以注册自己,并且自动抓取服务
- 将Eurcka的服务路径更改为两个不同的端口,使用逗号隔开
eureka:
instance:
# #配置运行实例
hostname: localhost
client:
service-url:
#配置eureka的服务路径,也就是客户端去管理中心的访问路径
defaultZone: http://root:123456@localhost:8761/eureka,http://root:123456@localhost:8762/eureka
# 是否注册自身
register-with-eureka: true
# 是否抓取注册信息
fetch-registry: true
3. 其他服务配置
将需要注册的服务yml文件进行如下配置,这样服务就会按照顺序遍历两个注册中心,即使有一个服务注册中心宕机,也不影响其他服务的注册.
# 配置注册中心地址
# 表示这个项目要注册到哪个注册中心
eureka:
client:
service-url:
defaultZone: http://root:123456@localhost:8761/eureka,http://root:123456@localhost:8762/eureka
4. 运行多个服务注册中心
在将服务注册中心更改为多实例模式以后,启动.
等待第一个8761端口的服务启动以后,马上将yml配置文件的端口更改为8762然后启动.这样就可以启动两个服务注册中心.
六 . eureka的其他配置
在服务注册中心可配置如下,来管理服务
spring:
application:
name: eurekaserver
security:
user:
name: root
password: 123456
server:
port: 8761
eureka:
instance:
# #配置运行实例
hostname: localhost
#心跳的间隔,默认30秒
lease-renewal-interval-in-seconds: 20
#多久没发送就将服务置为宕机,默认90
lease-expiration-duration-in-seconds: 30
client:
service-url:
#配置eureka的服务路径,也就是客户端去管理中心的访问路径
defaultZone: http://root:123456@localhost:8761/eureka,http://root:123456@localhost:8762/eureka
# 是否注册自身
register-with-eureka: true
# 是否抓取注册信
fetch-registry: true
#更新本地注册缓存信息需要的时间,默认30
registry-fetch-interval-seconds: 20
server:
# 是否开启自我保护机制
enable-self-preservation: true
七 . Eureka负载均衡
为了提高服务的相应速度,有时候需要配置多个服务提供者提供服务,对于多个服务提供者应该使用什么策略来均衡每个服务提供者的提供频率.这就是负载均衡.
负载均衡可以配置客户端负载均衡和服务端负载均衡
客户端的负载均衡实现服务使用者来进行配置,服务器端的负载均衡需要在服务中心的yml文件来进行配置,由服务注册中心来指定哪个生产者来提供服务.
使用Robbin来配置客户端的负载均衡:
1. 导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
2. 注入负载均衡
在消费者的配置文件中,为restTemplate实例注入负载均衡的属性,通过注解@LoadBalanced来注入.而这个注解需要上一步的依赖
@Bean
@LoadBalanced //添加负载均衡
public RestTemplate restTemplate() {
return new RestTemplate();
}
这样使用的restTemplate实例就会自动的按照设置的负载均衡策略去选择服务.
3. 修改访问方式
服务在服务注册中心进行注册后,会将服务名称注册在服务中心.之前我们是通过这个名字来找到服务的路劲,再访问服务的.
但是在使用负载均衡以后,我们需要换一种访问方式,通过服务名去搜索清单,按照负载均衡的策略选择服务访问,代码如下:
package com.gw.controller;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class ConsumerController {
@Autowired
RestTemplate restTemplate;
@Autowired
EurekaClient eurekaClient;
@RequestMapping("/hello")
public String hello(String name) {
// 1. 通过服务注册后的编号来访问服务
//表示消费者去使用哪个生产者的服务
// InstanceInfo instanceInfo = eurekaClient.getNextServerFromEureka("PRODUCERSERVICE", false);
//根据服务实例获取生产者的访问根路径
// String homePageUrl = instanceInfo.getHomePageUrl();
//拼接URI
// String uri = homePageUrl + "/hello?name=" + name;
//访问URI并获取返回值
// String result = restTemplate.getForObject(uri, String.class);
//2 . 通过服务名来访问远端
String uri = "http://producerService/hello?name=" + name;
//restTemplate对象是有负载均衡属性的对象
String result = restTemplate.getForObject(uri, String.class);
System.out.println("访问路径:" + uri);
return result;
}
}
4. 启动生产者的多个实例
为了模拟多个生产者提供服务,我们通过不同的端口号来启动多个生产者服务.为了方便标识,对生产者的contr做出如下修改:
package com.gw.gw_producer.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ProductController {
@Value("${server.port}")
private int port;
@RequestMapping("/hello")
public String hello(String name) {
System.out.println("端口号为" + port + "提供的服务");
return "hello : " + name + "----producer hello";
}
}
- 将生产者项目配置为多实例模式
- 运行一个生产者服务后,修改yml文件的端口号,再次启动第二个项目;
- 在浏览器访问消费者,观察控制台的服务提供者端口号被均衡分布到每一个端口
5. 负载均衡策略
可以在消费者的配置文件中配置不同的均衡策略,默认的是轮询
package com.gw.config;
import com.netflix.loadbalancer.BestAvailableRule;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RoundRobinRule;
import com.netflix.loadbalancer.WeightedResponseTimeRule;
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;
@Configuration
public class EurekaConfig {
@Bean
@LoadBalanced //添加负载均衡
public RestTemplate restTemplate() {
return new RestTemplate();
}
// 配置负载均衡策略
@Bean
public IRule rule() {
// return new RoundRobinRule();//轮询,默认的
//return new RandomRule();//随机策略
return new WeightedResponseTimeRule();//权重
// return new BestAvailableRule();//最小最优策略
}
}
八 . 总结
服务注册中心相当于一个中介,用来连接不同项目不同模块中的服务.不同的服务如果需要让其他服务访问,都需要在注册中心进行注册.
当一个服务需要访问另一个服务的时候,会去注册中心通过不同的方式来寻找自己需要的服务,而一个服务需要对外开放访问时,需要在服务注册中心进行注册,并不会去关心为谁提供服务.
为了提高服务的安全性,可以在服务配置中心进行用户配置,只有具有相应账号的服务才可以在服务中心进行注册访问.
当不同服务间的交流需要通过服务中心完成时,服务中心的安全性显得尤为重要.因此需要开启多个服务注册中心去提高其可用性,即使有一个注册中心奔溃,服务注册中心依然可以继续服务.
在不同的服务注册中心之间,对所注册的服务都会添加在一张共享的清单上,所有的服务注册中心共同维护这张服务清单.
为了提高服务的效率,我们可以注册多个生产者服务来提供服务,通过客户端负载均衡或服务端负载均衡来进一步提高性能.