SpringCloud
官网解释为:spring Cloud为开发人员提供了快速构建分布式系统中的一些常见模式的工具(例如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导层选举、分布式会话、集群状态)。分布式系统的协调导致了锅炉板模式,使用Spring Cloud开发人员可以快速建立实现这些模式的服务和应用程序。它们在任何分布式环境中都能很好地工作,包括开发人员自己的笔记本电脑、裸机数据中心和云计算等托管平台。首先SpringCloud是基于SpringBoot开发的。
一、服务注册于发现(Eureka)
springCloud Netflix自带组件Eureka作为注册中心,实现 服务协调、负载均衡、容错、路由等
创建EurekaServer项目开启注册中心:
org.springframework.boot
spring-boot-starter-parent
1.5.2.RELEASE
UTF-8
UTF-8
1.8
org.springframework.cloud
spring-cloud-starter-eureka-server
org.springframework.boot
spring-boot-starter-test
test
org.springframework.cloud
spring-cloud-dependencies
Dalston.RC1
pom
import
设置配置文件 :application.yml
server:
port: 8888
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
启动Eureka:
@SpringBootApplication
@EnableEurekaServer
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
二、创建一个服务提供者:member-service
配置文件:application.yml 将该服务提供者注册到注册中心Eureka
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8888/eureka/
server:
port: 8762
spring:
application:
name: member-service
服务接口:
@RestController
public class MemberController {
@RequestMapping("/getUserList")
public List getUserList() {
List listUser = new ArrayList();
listUser.add("zhangsan");
listUser.add("lisi");
listUser.add("wangwu");
return listUser;
}
}
开启服务:
@SpringBootApplication
@EnableEurekaClient
public class AppMember {
public static void main(String[] args) {
SpringApplication.run(AppMember.class, args);
}
}
三、服务消费者 order-service
配置文件:application.yml
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8888/eureka/
server:
port: 8764
spring:
application:
name: order-service
编写service,调用服务生产者:
@Service
public class MemberService {
@Autowired
RestTemplate restTemplate;
public List getOrderByUserList() {
return restTemplate.getForObject("http://service-member/getUserList", List.class);
}
}
启动项目:
@EnableEurekaClient
@SpringBootApplication
public class AppOrder {
public static void main(String[] args) {
SpringApplication.run(AppOrder.class, args);
}
//配置Bean属性,往IOC里面注入一个Bean,通过@LoadBalance表明开启负载均衡
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
四、服务治理之负载均衡 - ribbon (Fegin默认集成)
Ribbon类似于Nginx反向代理,通过负载均衡算法将请求路由到指定的服务上。使用就是采用restTemplate通过@LoadBalanced注解来实现开启负载均衡功能
使用Fegin实现只需要在暴露接口的类上加注解@FeginCilent("服务名")即可,Fegin默认集成Rebbon,类似于Dubbo的暴露服务,但是Fegin是一个声明式的http客户端,Dubbo是基于私有二进制协议
五、路由网关-Zuul
Zuul 的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如/api/user 转发 到 user 服务,/api/shop 转发到 shop 服务。zuul 默认和 Ribbon 结合实现了负载均衡 的功能, 类似于 nginx 转发。
配置文件配置:
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8888/eureka/
server:
port: 8769
spring:
application:
name: service-zuul
zuul:
routes:
api-a:
path: /api-member/**
service-id: service-member
api-b:
path: /api-order/**
service-id: service-order
发送请求 http://127.0.0.1:8769/api-member/getMemberAll 转发到 http://127.0.0.1:8762/getMemberAll 开启网关 @EnableZuulProxy
服务过滤:
@Component
public class MyFilter extends ZuulFilter {
private static Logger log = LoggerFactory.getLogger(MyFilter.class);
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 0;
}
public boolean shouldFilter() {
return true;
}
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
log.info(String.format("%s >>> %s", request.getMethod(),
request.getRequestURL().toString()));
Object accessToken = request.getParameter("token");
if (accessToken != null) {
return null;
}
log.warn("token is empty");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
try {
ctx.getResponse().getWriter().write("token is empty");
} catch (Exception e) {
}
return null;
}
}
六、服务治理,解决服务器雪崩应对策略 -- 断路器(Hystrix)
在微服务架构中,我们将业务拆分成一个个的服务,服务与服务之间可以相互调用 (RPC)。为了保证其高可用,单个服务又必须集群部署。由于网络原因或者自身的原因, 服务并不能保证服务的 100%可用,如果单个服务出现问题,调用这个服务就会出现网络延 迟,此时若有大量的网络涌入,会形成任务累计,导致服务瘫痪,甚至导致服务“雪 崩”。为了解决这个问题,就出现断路器模型。
Hystrix 是一个帮助解决分布式系统交互时超时处理和容错的类库, 它同样拥有保护系统 的能力.
分布式系统中经常会出现某个基础服务不可用造成整个系统不可用的情况, 这种现象被称 为服务雪崩效应. 为了应对服务雪崩, 一种常见的做法是手动服务降级. 而 Hystrix 的出 现,给我们提供了另一种选择.
1、熔断设计:
(1)熔断请求判断机制算法:使用无锁循环队列计数,每个熔断器默认维护 10 个bucket,每 1 秒一个 bucket,每个 blucket 记录请求的成功、失败、超时、拒绝的状态,默认错误超过 50%且 10 秒内超过 20 个请求进行中断拦截。
(2)熔断恢复:对于被熔断的请求,每隔 5s 允许部分请求通过,若请求都是健康的(RT<250ms)则对请求健康恢复。
(3)熔断报警:对于熔断的请求打日志,异常请求超过某些设定则报警
2、隔离设计:
(1)线程池隔离模式:使用一个线程池来存储当前的请求,线程池对请求作处理,设置任务返回处理超时时间,堆积的请求堆积入线程池队列。这种方式需要为每个依赖的服务申请线程池,有一定的资源消耗,好处是可以应对突发流量(流量洪峰来临时,处理不完可将数据存储到线程池队里慢慢处理)
(2)信号量隔离模式:使用一个原子计数器(或信号量)来记录当前有多少个线程在运行,请求来先判断计数器的数值,若超过设置的最大线程个数则丢弃改类型的新请求,若不超过则执行计数操作请求来计数器+1,请求返回计数器-1。这种方式是严格的控制线程且立即返回模式,无法应对突发流量(流量洪峰来临时,处理的线程超过数量,其他的请求会直接返回,不继续去请求依赖的服务)
3.超时设计:
等待超时:在任务入队列时设置任务入队列时间,并判断队头的任务入队列时间是否大于超时时间,超过则丢弃任务。
运行超时:直接可使用线程池提供的 get 方法
服务降级使用:
①使用rest方式的断路器,当服务不可用时不会出现异常,降级也就是将原来的服务不可用时回调一个方法类似于 -- 前台返回“连接人数过多,请稍后是在试!”
//Rest请求方式接口改造
@HystrixCommand(fallbackMethod = "orderError")
public List getOrderUserAll() {
return restTemplate.getForObject("http://service-member/getMemberAll", List.class);
}
public List orderError() {
List listUser = new ArrayList();
listUser.add("not orderUser list");
return listUser;
}
然后启动项目,启动类和之前一样只是需要在原来的类上面加@EnableHystrix注解来启动断路器,其中@HystrixCommand表示服务发生错误的回调方法
②Fegin实现断路器,在给服务进行代理的同时进行负载均衡,设置回调函数,当出现问题时调用回调函数
@FeignClient(value="service-member",fallback=MemberFeignService.class)
public interface MemberFeign {
@RequestMapping("/getMemberAll")
public List getOrderByUserList();
}
@Component
public class MemberFeignService implements MemberFeign {
public List getOrderByUserList() {
List listUser = new ArrayList();
listUser.add("not orderUser list");
return listUser;
}
}
修改配置文件,在配置文件中添加即可
fegin:
hystrix:
enable: true
SpringCloud基础内容完毕,更多请参照SpringCloud官方文档!