Spring Boot经过自动化的配置简化Spring原有的样板化的配置。 java
Spring Boot提供了不少现成的starter,能够快速的实现各类服务。git
actuator用于监控和管理服务信息。spring
有了,找到了!设计模式
Eureka的功能是提供服务的注册和服务的发现。api
实现一个Eureka服务很是简单:缓存
@EnableEurekaServer @SpringBootApplication public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }
配置文件:安全
server.port=1111 eureka.instance.hostname=localhost eureka.client.register-with-eureka=false eureka.client.fetch-registry=false eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
服务提供者一样简洁,只须要EnableDiscoveryClient
:服务器
@EnableDiscoveryClient @SpringBootApplication public class HelloApplication { public static void main(String[] args) { SpringApplication.run(HelloApplication.class, args); } }
提供controller:网络
@RestController public class HelloController { @RequestMapping("/hello") public String index() { return "Hello Spring Boot"; } }
配置文件application.properties:app
server.port=8888 spring.application.name=hello-service eureka.client.serviceUrl.defaultZone=http://111.222.83.251:1111/eureka/
服务消费者以下,经过url指明服务名称和接口,使用RestTemplate
进行http请求。
@Service public class HelloService { @Autowired RestTemplate restTemplate; public String helloService() { return restTemplate.getForEntity("http://HELLO-SERVICE/hello", String.class).getBody(); } }
配置文件:
eureka.client.serviceUrl.defaultZone=http://111.222.83.251:1111/eureka/
有三种方法能够运行:
java -jar
运行。spring-boot-maven-plugin
的mvn spring-boot:run
运行。我本机java环境为9,在项目中设置的java为1.8,致使只有第3种方法有效,由于其它两种依赖于本机安装的java运行环境,尽可能保持编译环境和运行环境一致。
Eureka用了双层map结构来维护注册的服务信息,第一层Key为服务的名称,第二层key为服务的实例名称。
当某一个服务向一个Eureka节点注册服务时,Eureka会将该请求转发给其它的Eureka节点,从而能够同步服务注册信息。
服务经过周期性的心跳来通知Eureka本身的状况,又称为服务续约(renew)。
经过REST请求想Eureka获取服务列表,周期性的更新服务列表缓存。
服务下线后,Eureka会通知给服务消费者。
为了防止服务的异常下线,会周期性的清理列表中未续约的服务。
一个服务能够属于一个Region和多个Zone。
服务用Region和Zone来刻画本身所处的物理位置,方便负载均衡器就近的选择同一个Zone服务。同时,服务也能够根据Region和Zone来选择应该向哪一个Eureka注册。
Spring提供了方便的RestTemplate像目标服务发送请求,有GET、POST、PUT和DELETE等基本操做。
LoadBalanced注解经过向RestTemplate添加拦截器,使其具有负载均衡的能力。
在服务消费者中实现以下,在RestTemplate上加入LoadBalanced
注解。
@SpringCloudApplication public class RibbonConsumerApplication { @Bean @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(RibbonConsumerApplication.class, args); } }
BaseLoaderBalancer
DynamicServerListLoadBalancer
ZoneAwareLoadBalancer
RandomRule
RoundRobbinRule
RetryRule
WeightedResponseTimeRule
其它。
服务降级、服务熔断、线程和信号隔离、请求缓存、请求合并以及服务监控等。
对于每个依赖的服务,Hystrix提供了专用的线程池,防止某个依赖服务影响其它的依赖服务,这种模式叫作“舱壁模式”(Bulkhead Pattern)。
Hystrix经过注解EnableCircuitBreaker
和hystrixCommand
提供了断路保护功能,在下游服务调用产生异常时进行功能降级。
在以下条件下打开断路器:
当断路器打开时,若是打开时间已经到达设定睡眠时间,则去尝试发送请求,测试下游服务是否已经恢复正常,若是请求成功,则关闭断路器,恢复正常。
保留10秒的bucket历史数据,记录请求成功、失败、延迟和拒绝次数做为开闭断路器的依据。
消费者端实现以下:
@Service public class HelloService { @Autowired RestTemplate restTemplate; @HystrixCommand(fallbackMethod = "helloFallback") public String helloService() { return restTemplate.getForEntity("http://HELLO-SERVICE/hello", String.class).getBody(); } public String helloFallback() { return "error"; } }
根据请求参数,想结果缓存入线程安全的map结构。
Hystrix提供了CacheResult
来实现缓存。
Hystrix提供了HystrixCollapser
进行请求的合并,将一小段时间内的请求合并为一个,不只减小了网络请求的次数,同时减小了线程池资源的占用。
Feign整合了Ribbon和Hystrix,除了这二者的功能,还提供了声明式的Web服务客户端的定义方式。
在调用其它服务时,能够经过以下简单封装实现。FeignClient
指明了服务的名称,RequestMapping
指明了服务的具体接口。和传统的方式相比,更为简洁方便。
@FeignClient("hello-service") public interface HelloService { @RequestMapping("/hello") String hello(); }
Feign在客户端声明的服务接口和服务端定义的接口是对应的,能够说形式彻底相同。因此,能够将这些接口发布出来,供客户端和服务端共同使用,从而减小客户端绑定配置。
Zuul针对外部客户端的访问,提供了请求路由、负载均衡和校验过滤等基本功能,还有与服务治理结合、请求转发的熔断机制、服务的聚合等。
建立一个简单的zuul,首先开启zuul:
@EnableZuulProxy @SpringBootApplication public class ApiGatewayApplication { public static void main(String[] args) { SpringApplication.run(ApiGatewayApplication.class, args); } }
配置路由规则:
spring.application.name=api-gateway server.port=5555 zuul.routes.api-a.path=/api-a/** zuul.routes.api-a.serviceId=hello-service zuul.routes.api-b.path=/api-b/** zuul.routes.api-b.serviceId=feign-consumer eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
每个路由规则包含两个部分,path指明了外部访问的url,对应的serviceId指明了所要映射到的服务。
Zuul不只作路由转发,还会对请求进行过滤。过滤会在请求的各个阶段执行:
其实Zuul的过滤器更像是设计模式中的责任链或者handler,一个请求在收到、转发、返回的各个阶段里,由多个过滤器依次处理。
Zuul结合Spring Cloud Config,能够动态的获取配置信息,从而能够实现动态的更新路由。
Zuul结合Groovy等动态语言,能够在运行时动态的加载自定义的过滤器。
建立一个Config server十分容易,首先建立一个远程git仓库,我在码云中建立了https://gitee.com/tiantianchi...。
建立spring boot项目,加入以下配置:
@EnableConfigServer @SpringBootApplication public class ConfigServerApplication { public static void main(String[] args) { SpringApplication.run(ConfigServerApplication.class, args); } }
在application.properties中加入:
spring.application.name=config-server server.port=7001 spring.cloud.config.server.git.uri=https://gitee.com/tiantianchi/spring-config spring.cloud.config.server.git.searchPaths=config-repo spring.cloud.config.server.git.username=username spring.cloud.config.server.git.password=password
在仓库中建立配置文件tc-dev.properties
,而后经过http://localhost:7001/tc/dev
能够访问其中的配置内容。
Config客户端的实现以下,首先建立配置文件boostrap.properties
文件,填入以下配置:
spring.application.name=tc spring.cloud.config.profile=dev spring.cloud.config.label=master spring.cloud.config.uri=http://localhost:7001/ server.port=7002
客户端就能够从Config server中获取tc-dev.properties配置文件。
Spring Cloud Bus依赖于现有的消息队列框架,如RabbitMQ和Kafka,实现微服务之间异步消息的发布和订阅。
能够利用Bus实现配置的自动更新。在git仓库中的配置发生变化时,经过hook将更新请求发送到Config服务,Config经过Bus发送给相关服务,告知其进行配置的更新。
在Bus中,将RabbitMQ等工具做为消息发布和获取的代理。每一个服务中,由Listener负责监听和处理事件,EventPublisher负责与消息代理进行通讯,它会收到本地发送的事件,而且发送到代理中,同时从代理中获取事件,发回给本地注册的Listener。Endpoint则负责暴露API,用户能够经过Endpoint提供的接口发起事件,Endpoint会利用EventPublisher将事件发到消息代理中。