赞
踩
现在是第三天之前的晚上。第三天到来之前,先来一手预习。哈哈哈,预习以下,上课应该会轻松一点。。。。。
第二天,我们学习了注册中心Eureka,接下来我们还要学习四个核心组件。
Eureka详解
为了Eureka的高可用,我们一般会有多台Eureka,他们是听过互相注册的方式知道彼此的存在的
server: port: 10086 # 端口 spring: application: name: eureka-server # 应用名称,会在Eureka中显示 eureka: client: service-url: # 配置其他Eureka服务的地址,而不是自己,比如10087 defaultZone: http://127.0.0.1:10087/eureka registry-fetch-interval-seconds: 10 #消费者每10秒拉取服务缓存到本地,生产环境不用改
Eureka对于失效不是立即剔除的,而是通过每隔60s的轮询,就是每60秒剔除一次。
那么,这个时候,客户端注册服务的时候就要注册多个Eureka
eureka: client: service-url: # EurekaServer地址 defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eureka
总结:实现eureka高可用的方式就是多个eureka互相注册,客户端注册所有的eureka。
服务和eureka是通过续约的方式进行的,服务每隔30s向eureka发送一个心跳(数据包),证明自己还活着。由于网络波动的原因,可能有时候没有接受到心跳,eureka不会立即剔除服务,而是再给服务几次机会,如果90s内服务还没有消息,那么eureka会认为服务已死,但是eureka不会立即剔除服务,因为eureka的剔除机制是轮询,每隔60秒剔除一次死掉的服务。
instance: lease-expiration-duration-in-seconds: 10 # 10秒即过期 lease-renewal-interval-in-seconds: 5 # 5秒一次心跳
消费者每隔30s拉取一次服务
eureka: client: registry-fetch-interval-seconds: 10
每隔60s剔除一次(默认)
server: enable-self-preservation: false # 关闭自我保护模式(缺省为打开) eviction-interval-timer-in-ms: 10000 # 扫描失效服务的间隔时间
总结:各司其职,服务隔一段时间就续约,消费者隔一段时间就更新服务,eureka隔一段时间就剔除坏掉的服务。
一.robbin 负载均衡
首先回顾以下昨天的注册中心,我们客户端发送请求,会到注册中心拉取服务者,是一个集合,如果要实现负载均衡,我们可以自己编码,实现轮询或者随机,知识我们自己的方式。
而我们知道每一个服务提供者和消费者都是一个客户端,都需要引入Eureka的依赖,而Eureka给我们提供了负载均衡的算法,不需要我们自己提供,我们只需要在restTemplate上添加一个注解即可。
@Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(new OkHttp3ClientHttpRequestFactory()); }
这样就可以实现负载均衡,默认算法是轮询算法,我们可以在配置文件中修改算法。
有了负载均衡后,我们就不用自己写负载均衡算法了,下面是之前的写法
现在,我们的写法是这样的,负载均衡的底层回去eureka中去拉取服务
String url = "http://user-service/hello/user/" + id; User user = restTemplate.getForObject(url, User.class);
下面的算法是随机的算法,默认是轮询,下面这种写法是随机算法
user-service: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #负载均衡
Eureka的服务治理强调了CAP原则中的AP,即可用性和可靠性。它与Zookeeper这一类强调CP(一致性,可靠性)的服务治理框架最大的区别在于:Eureka为了实现更高的服务可用性,牺牲了一定的一致性,极端情况下它宁愿接收故障实例也不愿丢掉健康实例,正如我们上面所说的自我保护机制。
因为Eureke的特性,如果一个服务出现故障,不会立即将他剔除,这样,我们访问的时候,就有可能出现访问不到的情况,这样就会出现错误页面,这时候,有一个新的机制,重试机制,保证了我们在访问不到的时候,可以跳转到另一台机器上。
重试机制是在负载均衡的基础上实现的,因为只有负载均衡后,我们才会不确定会访问到哪一台机器,这样,我们访问的机器有时候就是坏掉的,我们需要一个重试机制,把我们定向到其他机器上。
因此Spring Cloud 整合了Spring Retry 来增强RestTemplate的重试能力,所以,我们需要先引入依赖
<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency>
依赖的版本springcloud已经帮助我们管理好了。
接下来我们要在配置文件中告诉我们的robbin需要怎么去重试
首先开启重试功能
spring: application: name: consumer cloud: loadbalancer: retry: enabled: true # 开启Spring Cloud的重试功能配置重试功能的具体信息
user-service: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #负载均衡 ConnectTimeout: 250 # Ribbon的连接超时时间 ReadTimeout: 1000 # Ribbon的数据读取超时时间 OkToRetryOnAllOperations: true # 是否对所有操作都进行重试 MaxAutoRetriesNextServer: 1 # 切换实例的重试次数 MaxAutoRetries: 1 # 对当前实例的重试次数
二.Hystix
熔断器会设置一个超时时间,默认是1s,如果超时,会熔断,返回一个友好的页面
首先,导入依赖
<!--引入hystix熔断器依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
第二步,添加注解
@EnableHystrix @EnableFeignClients public class CouldCustomerApplication {
第三步,在具体的方法上启用熔断,并且写一个熔断后的方法
@HystrixCommand(fallbackMethod = "queryUserFullBack") public User queryUserById(Long id) {
第四步,在配置文件中配置熔断实现的具体细节,设置熔断生效的时间
hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 6000
完成这四步,就可以实现熔断了。我们一般将熔断的时间设置的比重试的时间大一点,先重试,再熔断。
三.fegin 伪装
fegion就像通用mapper一样,他的出现就是为了省略代码,通过动态代理。
这是直接用负载均衡和熔断的功能
@HystrixCommand(fallbackMethod = "queryUserFullBack") public User queryUserById(Long id) { //记录时间 Long start = System.currentTimeMillis(); String url = "http://user-service/hello/user/" + id; User user = restTemplate.getForObject(url, User.class); //将响应的json解析成对象 Long end = System.currentTimeMillis(); logger.info("查询一共消耗时间{"+(end-start)+"}ms"); return user; }
我们的feign直接继承了Hystix和robbin,怎么使用 feign呢?
第一步,引入依赖
<!--引入feign依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
第二步,开启feign客户端一,feign继承了robbin,不用再写restTemplate了
@EnableFeignClients public class CouldCustomerApplication {
第三步,编写一个接口,里面包含服务名等信息
@FeignClient(value = "user-service",path = "hello/user",fallback= UserFeignClientFallback.class ) public interface UserFeignClient { @GetMapping("{id}") User queryUserById(@PathVariable("id") Long id); }
第四步,在service层直接使用fegin,fegin中自带了ribbun负载均衡
@Autowired private UserFeignClient userFeignClient;
第五步,熔断的使用,在接口中先定义一个熔断的方法,写一个类继承这个方法,并将方法交给ioc管理
@Component public class UserFeignClientFallback implements UserFeignClient { @Override public User queryUserById(Long id) { User user = new User(); user.setId(id); user.setName("用户查询出现异常!"); return user; } }
第六步,配置文件的配置。ribbon可以跟以前一样的配置,但是这里要额外开启Hystix,要不然没法开启,因为没用feign之前是注解的方式开启的
user-service: ribbon: # NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #负载均衡 ConnectTimeout: 250 # Ribbon的连接超时时间 ReadTimeout: 1000 # Ribbon的数据读取超时时间 OkToRetryOnAllOperations: true # 是否对所有操作都进行重试 MaxAutoRetriesNextServer: 1 # 切换实例的重试次数 MaxAutoRetries: 1 # 对当前实例的重试次数 #开启feign的熔断 feign: hystrix: enabled: true # 开启Feign的熔断功能
另外,feign还有其他额外的功能,对请求进行压缩,减小过程损耗
feign:
compression:
request:
enabled: true # 开启请求压缩
response:
enabled: true # 开启响应压缩
还可以对请求的数据类型,还有启动压缩下限的大小进行设置
feign:
compression:
request:
enabled: true # 开启请求压缩
mime-types: text/html,application/xml,application/json # 设置压缩的数据类型
min-request-size: 2048 # 设置触发压缩的大小下限
feign还有一个坑爹的地方,就是之前配置日志的方式会不起作用,理由如下:
feign是这样就行配置的
首先,我们要写一个配置类,设定配置的级别
@Configuration
public class FeignConfig {
@Bean
Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
}
然后,我们开启fegin客户端的地方,设置这个配置
@FeignClient(value = "user-service", fallback = UserFeignClientFallback.class, configuration = FeignConfig.class)
public interface UserFeignClient {
@GetMapping("/user/{id}")
User queryUserById(@PathVariable("id") Long id);
}
这样,就可以自定义日志的使用级别了。
四。zuul
守门员,网关
第一步,引入依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency>
二.在启动程序上用注解开启配置
@EnableZuulProxy @EnableEurekaClient public class ZuulDemoApplication {
三,在配置文件中配置eureka
zuul: prefix: /api # 配置前缀,标记通过zuul的链接 routes: user-service: /user/** #配置服务,链接中有user的都会被代理到user-service
当然,eureka的默认配置也是少不了的,引入zuul要到eureka中去拉取服务
Eureka eureka: client: registry-fetch-interval-seconds: 5 # ��ȡ�����б�����ڣ�5s service-url: defaultZone: http://127.0.0.1:10086/eureka instance: prefer-ip-address: true ip-address: 127.0.0.1
zuul还有一个重要的功能就是过滤器,实现过滤器要继承zuulFilter,并将过滤器交给ioc管理即可
@Component public class LoginFilter extends ZuulFilter { @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 1; } @Override public boolean shouldFilter() { return true; } @Override public Object run() throws ZuulException {
filterType是前置过滤的意思,filterOrder是过滤器的等级,一些内置的过滤器等级一般比较高,是-1,-2之类的
shouldFilter代表是否拦截的意思,run方法中写的是具体的拦截方法。
我们在这里写了一个登陆拦截的小demo
RequestContext ctx = RequestContext.getCurrentContext(); // 2) 从上下文中获取request对象 HttpServletRequest req = ctx.getRequest(); // 3) 从请求中获取token String token = req.getParameter("access-token"); // 4) 判断 if(token == null || "".equals(token.trim())){ // 没有token,登录校验失败,拦截 // 返回401状态码。也可以考虑重定向到登录页。 ctx.setResponseStatusCode(401); ctx.setSendZuulResponse(false); } // 校验通过,可以考虑把用户信息放入上下文,继续向后执行 return null;
zuul中负载均衡和熔断的配置
zuul:
retryable: true
ribbon:
ConnectTimeout: 250 # 连接超时时间(ms)
ReadTimeout: 2000 # 通信超时时间(ms)
OkToRetryOnAllOperations: true # 是否对所有操作重试
MaxAutoRetriesNextServer: 2 # 同一服务不同实例的重试次数
MaxAutoRetries: 1 # 同一实例的重试次数
hystrix:
command:
execution:
isolation:
thread:
timeoutInMillisecond: 6000 # 熔断超时时长:6000ms
其他:调整每个项目所占内存的大小
-Xms128m -Xmx128m
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。