一、Eureka
-
Eureka:就是服务注册中心(可以是一个集群),对外暴露自己的地址
-
提供者:启动后向Eureka注册自己信息(地址,提供什么服务)
-
消费者:向Eureka订阅服务,Eureka会将对应服务的所有提供者地址列表发送给消费者,并且定期更新
-
心跳(续约):提供者定期通过http方式向Eureka刷新自己的状态
注册中心搭建:
pom.xml:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>eureka</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>2020.0.3</spring-cloud.version>
</properties>
<dependencies>
<!-- eureka-server -->
<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>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
配置文件:
server:
port: 10086
spring:
application:
name: eureka-server
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:${server.port}/eureka
server:
enable-self-preservation: false # 关闭自我保护模式(缺省为打开)
eviction-interval-timer-in-ms: 1000 # 扫描失效服务的间隔时间(缺省为60*1000ms)
服务下线
当服务进行正常关闭操作时,它会触发一个服务下线的REST请求给Eureka Server,告诉服务注册中心:“我要下线了”。服务中心接受到请求之后,将该服务置为下线状态。
失效剔除
有些时候,我们的服务提供方并不一定会正常下线,可能因为内存溢出、网络故障等原因导致服务无法正常工作。Eureka Server需要将这样的服务剔除出服务列表。因此它会开启一个定时任务,每隔60秒对所有失效的服务(超过90秒未响应)进行剔除。
可以通过eureka.server.eviction-interval-timer-in-ms参数对其进行修改,单位是毫秒,生产环境不要修改。
这个会对我们开发带来极大的不便,你对服务重启,隔了60秒Eureka才反应过来。开发阶段可以适当调整,比如:10秒
自我保护
当一个服务未按时进行心跳续约时,Eureka会统计最近15分钟心跳失败的服务实例的比例是否超过了85%。在生产环境下,因为网络延迟等原因,心跳失败实例的比例很有可能超标,但是此时就把服务剔除列表并不妥当,因为服务可能没有宕机。Eureka就会把当前实例的注册信息保护起来,不予剔除。生产环境下这很有效,保证了大多数服务依然可用。
但是这给我们的开发带来了麻烦, 因此开发阶段我们都会关闭自我保护模式
启动类:添加@EnableEurekaServer注解
至此,一个简单的eureka注册中心配置完成。
二、创建一个服务提供方 provider
1.pom.xml文件添加依赖
<!-- springMVC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- eureka-client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2.配置文件将服务注册到eureka
server:
port: 8080
spring:
application:
name: provider
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
3.启动类添加
@EnableDiscoveryClient注解
4.添加controller
三、服务消费方 customer 使用feign调用provider接口
Feign可以把Rest的请求进行隐藏,伪装成类似SpringMVC的Controller一样。你不用再自己拼接url,拼接参数等等操作,一切都交给Feign去做。
使用RestTemplate调用服务
下面customer通过使用feign来调用provider的接口
1.pom.xml
<!-- eureka客户端依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.配置文件
server:
port: 8081
spring:
application:
name: customer
eureka:
client:
registry-fetch-interval-seconds: 3 #服务拉取时间
service-url:
defaultZone: http://127.0.0.1:10086/eureka
3.启动类加上@EnableFeignClients注解
4.创建client类
@FeignClient(value = "provider",fallback = ClientFallback.class)
@Component
public interface ProviderClient{
@RequestMapping("provider/demo")
public String providerDemo();
}
-
@FeignClient
,声明这是一个Feign客户端,同时通过value
属性指定服务名称 -
接口中的定义方法,完全采用SpringMVC的注解,Feign会根据注解帮我们生成URL,并访问获取结果
5.编写controller类调用client接口
@RestController
@RequestMapping("customer")
public class CustomerController {
@Autowired
private ProviderClient providerClient;
@RequestMapping("demo")
public String customerDemo(){
return providerClient.providerDemo();
}
}
6.启动并访问
四、创建provider2形成集群,实现负载均衡
参照provider1创建provider2
配置文件:服务名称相同,设置不同的端口
feign默认集成ribbon,并且默认配置
Ribbon是Netlix发布的负载均衡器,它有助于控制HTTP和TCP客户端的行为。为Ribbon配置服务提供者地址列表后,Ribbon 就可基于某种负载均衡算法,自动地帮助服务消费者去请求。Ribbon默认为我们提供了很多的负载均衡算法,例如轮询、随机等。当然,我们也可为Ribbon实现自定义的负载均衡算法。
所以,当一个服务存在集群,feign会通过ribbon的默认的负载均衡策略是简单的轮询来访问服务
当customer多次连续访问provider,provider1和provider2一次轮流被调用
五、实现容错处理
Hystix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败。
雪崩问题:例如,一次业务请求,需要调用A、P、H、I四个服务,这四个服务又可能调用其它服务。如果此时,某个服务出现异常: 如果一个服务出现异常,用户的请求会被阻塞,用户不会得到响应,则tomcat的这个线程不会释放,于是越来越多的用户请求到来,越来越多的线程会阻塞:服务器支持的线程和并发数有限,请求一直阻塞,会导致服务器资源耗尽,从而导致所有其它服务都不可用,形成雪崩效应。
Hystix解决雪崩问题的手段有两个:
-
线程隔离
-
服务熔断
Hystrix为每个依赖服务调用分配一个小的线程池,如果线程池已满调用将被立即拒绝,默认不采用排队.加速失败判定时间。
用户的请求将不再直接访问服务,而是通过线程池中的空闲线程来访问服务,如果线程池已满,或者请求超时,则会进行降级处理,什么是服务降级?
服务降级:优先保证核心服务,而非核心服务不可用或弱可用。
用户的请求故障时,不会被阻塞,更不会无休止的等待或者看到系统崩溃,至少可以看到一个执行结果(例如返回友好的提示信息) 。
服务降级虽然会导致请求失败,但是不会导致阻塞,而且最多会影响这个依赖服务对应的线程池中的资源,对其它服务没有响应。
触发Hystix服务降级的情况:
-
线程池已满
-
请求超时
feign也集成了hystrix,但是要默认时没有打开的,所以需要在配置文件中配置
1.在customer配置文件中添加配置:
feign:
hystrix:
enabled: true
2.创建ClientFallback类实现ProviderClient,作为fallback的处理类
@Component
public class ClientFallback implements ProviderClient{
@Override
public String providerDemo() {
return "服务器忙碌,请稍后再试";
}
}
3.在ProviderClient中添加fallback = ClientFallback.class
4.将provider2停止,测试