当前位置:   article > 正文

SpringCloud 教程总结 从Eureka到zuul_springcloud服务启动顺序config zuul eureka

springcloud服务启动顺序config zuul eureka

第一篇:服务的注册与发现Eureka

创建服务注册中心

Eureka作为服务注册与发现的组件

2.1 首先创建一个maven主工程。

**2.2 然后创建2个model工程:**一个model工程作为服务注册中心,即Eureka Server,另一个作为Eureka Client。

下面以创建server为例子,详细说明创建过程:

2.3 启动一个服务注册中心,只需要一个注解@EnableEurekaServer,这个注解需要在springboot工程的启动application类上加:

 

  1. @SpringBootApplication
  2. @EnableEurekaServer
  3. public class EurekaServerApplication {
  4. public static void main(String[] args) {
  5. SpringApplication.run( EurekaServerApplication.class, args );
  6. }
  7. }

**2.4 **eureka是一个高可用的组件,它没有后端缓存,每一个实例注册之后需要向注册中心发送心跳(因此可以在内存中完成),在默认情况下erureka server也是一个eureka client ,必须要指定一个 server。eureka server的配置文件appication.yml:

  1. server:
  2. port: 8761
  3. eureka:
  4. instance:
  5. hostname: localhost
  6. client:
  7. registerWithEureka: false
  8. fetchRegistry: false
  9. serviceUrl:
  10. defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  11. spring:
  12. application:
  13. name: eurka-server

通过eureka.client.registerWithEureka:false和fetchRegistry:false来表明自己是一个eureka server.

2.5 eureka server 是有界面的,启动工程,打开浏览器访问:
http://localhost:8761 ,界面如下:

在这里插入图片描述

 第二篇: 服务消费者(rest+ribbon)

在微服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于http restful的。Spring cloud有两种服务调用方式,一种是ribbon+restTemplate,另一种是feign。在这一篇文章首先讲解下基于ribbon+rest。

Ribbon is a client side load balancer which gives you a lot of control over the behaviour of HTTP and TCP clients. Feign already uses Ribbon, so if you are using @FeignClient then this section also applies.

ribbon是一个负载均衡客户端,可以很好的控制htt和tcp的一些行为。Feign默认集成了ribbon。

ribbon 已经默认实现了这些配置bean:

  • IClientConfig ribbonClientConfig: DefaultClientConfigImpl

  • IRule ribbonRule: ZoneAvoidanceRule

  • IPing ribbonPing: NoOpPing

  • ServerList ribbonServerList: ConfigurationBasedServerList

  • ServerListFilter ribbonServerListFilter: ZonePreferenceServerListFilter

  • ILoadBalancer ribbonLoadBalancer: ZoneAwareLoadBalancer

二、准备工作

启动eureka-server 工程;启动service-hi工程,它的端口为8762;将service-hi的配置文件的端口改为8763,并启动,这时你会发现:service-hi在eureka-server注册了2个实例,这就相当于一个小的集群。

三、建一个服务消费者

重新新建一个spring-boot工程,取名为:service-ribbon;
在它的pom.xml继承了父pom文件,并引入了以下依赖:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <groupId>com.forezp</groupId>
  6. <artifactId>service-ribbon</artifactId>
  7. <version>0.0.1-SNAPSHOT</version>
  8. <packaging>jar</packaging>
  9. <name>service-ribbon</name>
  10. <description>Demo project for Spring Boot</description>
  11. <parent>
  12. <groupId>com.forezp</groupId>
  13. <artifactId>sc-f-chapter2</artifactId>
  14. <version>0.0.1-SNAPSHOT</version>
  15. </parent>
  16. <dependencies>
  17. <dependency>
  18. <groupId>org.springframework.cloud</groupId>
  19. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.springframework.boot</groupId>
  23. <artifactId>spring-boot-starter-web</artifactId>
  24. </dependency>
  25. <dependency>
  26. <groupId>org.springframework.cloud</groupId>
  27. <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
  28. </dependency>
  29. </dependencies>
  30. </project>

在工程的配置文件指定服务的注册中心地址为http://localhost:8761/eureka/,程序名称为 service-ribbon,程序端口为8764。配置文件application.yml如下:

  1. eureka:
  2. client:
  3. serviceUrl:
  4. defaultZone: http://localhost:8761/eureka/
  5. server:
  6. port: 8764
  7. spring:
  8. application:
  9. name: service-ribbon

在工程的启动类中,通过@EnableDiscoveryClient向服务中心注册;并且向程序的ioc注入一个bean: restTemplate;并通过@LoadBalanced注解表明这个restRemplate开启负载均衡的功能。

  1. @SpringBootApplication
  2. @EnableEurekaClient
  3. @EnableDiscoveryClient
  4. public class ServiceRibbonApplication {
  5. public static void main(String[] args) {
  6. SpringApplication.run( ServiceRibbonApplication.class, args );
  7. }
  8. @Bean
  9. @LoadBalanced
  10. RestTemplate restTemplate() {
  11. return new RestTemplate();
  12. }
  13. }

写一个测试类HelloService,通过之前注入ioc容器的restTemplate来消费service-hi服务的“/hi”接口,在这里我们直接用的程序名替代了具体的url地址,在ribbon中它会根据服务名来选择具体的服务实例,根据服务实例在请求的时候会用具体的url替换掉服务名,代码如下:

  1. @Service
  2. public class HelloService {
  3. @Autowired
  4. RestTemplate restTemplate;
  5. public String hiService(String name) {
  6. return restTemplate.getForObject("http://SERVICE-HI/hi?name="+name,String.class);
  7. }
  8. }

写一个controller,在controller中用调用HelloService 的方法,代码如下:

  1. @RestController
  2. public class HelloControler {
  3. @Autowired
  4. HelloService helloService;
  5. @GetMapping(value = "/hi")
  6. public String hi(@RequestParam String name) {
  7. return helloService.hiService( name );
  8. }
  9. }

在浏览器上多次访问http://localhost:8764/hi?name=forezp,浏览器交替显示:

  1. hi forezp,i am from port:8762
  2. hi forezp,i am from port:8763

ribbon在这里起到了负载均衡的作用。

在这里插入图片描述

第三篇: 服务消费者(Feign)

Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单。使用Feign,只需要创建一个接口并注解。它具有可插拔的注解特性,可使用Feign 注解和JAX-RS注解。Feign支持可插拔的编码器和解码器。Feign默认集成了Ribbon,并和Eureka结合,默认实现了负载均衡的效果。

简而言之:

  • Feign 采用的是基于接口的注解
  • Feign 整合了ribbon,具有负载均衡的能力
  • 整合了Hystrix,具有熔断的能力

二、准备工作

继续用上一节的工程, 启动eureka-server,端口为8761; 启动service-hi 两次,端口分别为8762 、8773.

三、创建一个feign的服务

新建一个spring-boot工程,取名为serice-feign,在它的pom文件引入Feign的起步依赖spring-cloud-starter-feign、Eureka的起步依赖spring-cloud-starter-netflix-eureka-client、Web的起步依赖spring-boot-starter-web,代码如下:

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>com.forezp</groupId>
  5. <artifactId>service-feign</artifactId>
  6. <version>0.0.1-SNAPSHOT</version>
  7. <packaging>jar</packaging>
  8. <name>service-feign</name>
  9. <description>Demo project for Spring Boot</description>
  10. <parent>
  11. <groupId>com.forezp</groupId>
  12. <artifactId>sc-f-chapter3</artifactId>
  13. <version>0.0.1-SNAPSHOT</version>
  14. </parent>
  15. <dependencies>
  16. <dependency>
  17. <groupId>org.springframework.cloud</groupId>
  18. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  19. </dependency>
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-starter-web</artifactId>
  23. </dependency>
  24. <dependency>
  25. <groupId>org.springframework.cloud</groupId>
  26. <artifactId>spring-cloud-starter-openfeign</artifactId>
  27. </dependency>
  28. </dependencies>
  29. </project>

在工程的配置文件application.yml文件,指定程序名为service-feign,端口号为8765,服务注册地址为http://localhost:8761/eureka/ ,代码如下:

  1. eureka:
  2. client:
  3. serviceUrl:
  4. defaultZone: http://localhost:8761/eureka/
  5. server:
  6. port: 8765
  7. spring:
  8. application:
  9. name: service-feign

在程序的启动类ServiceFeignApplication ,加上@EnableFeignClients注解开启Feign的功能:

  1. @SpringBootApplication
  2. @EnableEurekaClient
  3. @EnableDiscoveryClient
  4. @EnableFeignClients
  5. public class ServiceFeignApplication {
  6. public static void main(String[] args) {
  7. SpringApplication.run( ServiceFeignApplication.class, args );
  8. }
  9. }

定义一个feign接口,通过@ FeignClient(“服务名”),来指定调用哪个服务。比如在代码中调用了service-hi服务的“/hi”接口,代码如下:

  1. @FeignClient(value = "service-hi")
  2. public interface SchedualServiceHi {
  3. @RequestMapping(value = "/hi",method = RequestMethod.GET)
  4. String sayHiFromClientOne(@RequestParam(value = "name") String name);
  5. }

在Web层的controller层,对外暴露一个"/hi"的API接口,通过上面定义的Feign客户端SchedualServiceHi 来消费服务。代码如下:

  1. @RestController
  2. public class HiController {
  3. //编译器报错,无视。 因为这个Bean是在程序启动的时候注入的,编译器感知不到,所以报错。
  4. @Autowired
  5. SchedualServiceHi schedualServiceHi;
  6. @GetMapping(value = "/hi")
  7. public String sayHi(@RequestParam String name) {
  8. return schedualServiceHi.sayHiFromClientOne( name );
  9. }
  10. }

启动程序,多次访问http://localhost:8765/hi?name=forezp,浏览器交替显示:

  1. hi forezp,i am from port:8762
  2. hi forezp,i am from port:8763

第四篇:断路器(Hystrix)

在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以相互调用(RPC),在Spring Cloud可以用RestTemplate+Ribbon和Feign来调用。为了保证其高可用,单个服务通常会集群部署。由于网络原因或者自身的原因,服务并不能保证100%可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应。

为了解决这个问题,业界提出了断路器模型。

一、断路器简介

Netflix has created a library called Hystrix that implements the circuit breaker pattern. In a microservice architecture it is common to have multiple layers of service calls.

Netflix开源了Hystrix组件,实现了断路器模式,SpringCloud对这一组件进行了整合。 在微服务架构中,一个请求需要调用多个服务是非常常见的,如下图:

在这里插入图片描述

较底层的服务如果出现故障,会导致连锁故障。当对特定的服务的调用的不可用达到一个阀值(Hystric 是5秒20次) 断路器将会被打开。

在这里插入图片描述

断路打开后,可用避免连锁故障,fallback方法可以直接返回一个固定值。

二、准备工作

这篇文章基于上一篇文章的工程,首先启动上一篇文章的工程,启动eureka-server 工程;启动service-hi工程,它的端口为8762。

三、在ribbon使用断路器

改造serice-ribbon 工程的代码,首先在pox.xml文件中加入spring-cloud-starter-netflix-hystrix的起步依赖:

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  4. </dependency>

 

在程序的启动类ServiceRibbonApplication 加@EnableHystrix注解开启Hystrix:

  1. @SpringBootApplication
  2. @EnableEurekaClient
  3. @EnableDiscoveryClient
  4. @EnableHystrix
  5. public class ServiceRibbonApplication {
  6. public static void main(String[] args) {
  7. SpringApplication.run( ServiceRibbonApplication.class, args );
  8. }
  9. @Bean
  10. @LoadBalanced
  11. RestTemplate restTemplate() {
  12. return new RestTemplate();
  13. }
  14. }

改造HelloService类,在hiService方法上加上@HystrixCommand注解。该注解对该方法创建了熔断器的功能,并指定了fallbackMethod熔断方法,熔断方法直接返回了一个字符串,字符串为"hi,"+name+",sorry,error!",代码如下:

  1. @Service
  2. public class HelloService {
  3. @Autowired
  4. RestTemplate restTemplate;
  5. @HystrixCommand(fallbackMethod = "hiError")
  6. public String hiService(String name) {
  7. return restTemplate.getForObject("http://SERVICE-HI/hi?name="+name,String.class);
  8. }
  9. public String hiError(String name) {
  10. return "hi,"+name+",sorry,error!";
  11. }
  12. }

启动:service-ribbon 工程,当我们访问http://localhost:8764/hi?name=forezp,浏览器显示:

hi forezp,i am from port:8762

此时关闭 service-hi 工程,当我们再访问http://localhost:8764/hi?name=forezp,浏览器会显示:

hi ,forezp,orry,error!

这就说明当 service-hi 工程不可用的时候,service-ribbon调用 service-hi的API接口时,会执行快速失败,直接返回一组字符串,而不是等待响应超时,这很好的控制了容器的线程阻塞。防止了线程cpu资源的浪费,同时熔断器结合ribbon联合起到了负载均衡和熔断的效果!

四、Feign中使用断路器

Feign是自带断路器的,在D版本的Spring Cloud之后,它没有默认打开。需要在配置文件中配置打开它,在配置文件加以下代码:

feign.hystrix.enabled=true

基于service-feign工程进行改造,只需要在FeignClient的SchedualServiceHi接口的注解中加上fallback的指定类就行了:

  1. @FeignClient(value = "service-hi",fallback = SchedualServiceHiHystric.class)
  2. public interface SchedualServiceHi {
  3. @RequestMapping(value = "/hi",method = RequestMethod.GET)
  4. String sayHiFromClientOne(@RequestParam(value = "name") String name);
  5. }

SchedualServiceHiHystric需要实现SchedualServiceHi 接口,并注入到Ioc容器中,代码如下:

  1. @Component
  2. public class SchedualServiceHiHystric implements SchedualServiceHi {
  3. @Override
  4. public String sayHiFromClientOne(String name) {
  5. return "sorry "+name;
  6. }
  7. }

启动四servcie-feign工程,浏览器打开http://localhost:8765/hi?name=forezp,注意此时service-hi工程没有启动,网页显示:

sorry forezp

打开service-hi工程,再次访问,浏览器显示:

  1. hi forezp,i am from port:8762

这证明断路器起到作用了。

第五篇: 路由网关(zuul)(Finchley版本)

在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现、服务消费、负载均衡、断路器、智能路由、配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统。一个简答的微服务系统如下图:

注意:A服务和B服务是可以相互调用的,作图的时候忘记了。并且配置服务也是注册到服务注册中心的。

在Spring Cloud微服务系统中,一种常见的负载均衡方式是,客户端的请求首先经过负载均衡(zuul、Ngnix),再到达服务网关(zuul集群),然后再到具体的服。,服务统一注册到高可用的服务注册中心集群,服务的所有的配置文件由配置服务管理(下一篇文章讲述),配置服务的配置文件放在git仓库,方便开发人员随时改配置。

一、Zuul简介

Zuul的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如/api/user转发到到user服务,/api/shop转发到到shop服务。zuul默认和Ribbon结合实现了负载均衡的功能。

zuul有以下功能:

  • Authentication
  • Insights
  • Stress Testing
  • Canary Testing
  • Dynamic Routing
  • Service Migration
  • Load Shedding
  • Security
  • Static Response handling
  • Active/Active traffic management

二、准备工作

继续使用上一节的工程。在原有的工程上,创建一个新的工程。

三、创建service-zuul工程

其pom.xml文件如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <groupId>com.forezp</groupId>
  6. <artifactId>service-zuul</artifactId>
  7. <version>0.0.1-SNAPSHOT</version>
  8. <packaging>jar</packaging>
  9. <name>service-zuul</name>
  10. <description>Demo project for Spring Boot</description>
  11. <parent>
  12. <groupId>com.forezp</groupId>
  13. <artifactId>sc-f-chapter5</artifactId>
  14. <version>0.0.1-SNAPSHOT</version>
  15. </parent>
  16. <dependencies>
  17. <dependency>
  18. <groupId>org.springframework.cloud</groupId>
  19. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.springframework.boot</groupId>
  23. <artifactId>spring-boot-starter-web</artifactId>
  24. </dependency>
  25. <dependency>
  26. <groupId>org.springframework.cloud</groupId>
  27. <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
  28. </dependency>
  29. </dependencies>
  30. </project>

其入口applicaton类加上注解@EnableZuulProxy,开启zuul的功能:

  1. @SpringBootApplication
  2. @EnableZuulProxy
  3. @EnableEurekaClient
  4. @EnableDiscoveryClient
  5. public class ServiceZuulApplication {
  6. public static void main(String[] args) {
  7. SpringApplication.run( ServiceZuulApplication.class, args );
  8. }
  9. }

加上配置文件application.yml加上以下的配置代码:

  1. eureka:
  2. client:
  3. serviceUrl:
  4. defaultZone: http://localhost:8761/eureka/
  5. server:
  6. port: 8769
  7. spring:
  8. application:
  9. name: service-zuul
  10. zuul:
  11. routes:
  12. api-a:
  13. path: /api-a/**
  14. serviceId: service-ribbon
  15. api-b:
  16. path: /api-b/**
  17. serviceId: service-feign

首先指定服务注册中心的地址为http://localhost:8761/eureka/,服务的端口为8769,服务名为service-zuul;以/api-a/ 开头的请求都转发给service-ribbon服务;以/api-b/开头的请求都转发给service-feign服务;

依次运行这五个工程;打开浏览器访问:http://localhost:8769/api-a/hi?name=forezp ;浏览器显示:

hi forezp,i am from port:8762

打开浏览器访问:http://localhost:8769/api-b/hi?name=forezp ;浏览器显示:

hi forezp,i am from port:8762

这说明zuul起到了路由的作用

四、服务过滤

zuul不仅只是路由,并且还能过滤,做一些安全验证。继续改造工程;

  1. @Component
  2. public class MyFilter extends ZuulFilter {
  3. private static Logger log = LoggerFactory.getLogger(MyFilter.class);
  4. @Override
  5. public String filterType() {
  6. return "pre";
  7. }
  8. @Override
  9. public int filterOrder() {
  10. return 0;
  11. }
  12. @Override
  13. public boolean shouldFilter() {
  14. return true;
  15. }
  16. @Override
  17. public Object run() {
  18. RequestContext ctx = RequestContext.getCurrentContext();
  19. HttpServletRequest request = ctx.getRequest();
  20. log.info(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString()));
  21. Object accessToken = request.getParameter("token");
  22. if(accessToken == null) {
  23. log.warn("token is empty");
  24. ctx.setSendZuulResponse(false);
  25. ctx.setResponseStatusCode(401);
  26. try {
  27. ctx.getResponse().getWriter().write("token is empty");
  28. }catch (Exception e){}
  29. return null;
  30. }
  31. log.info("ok");
  32. return null;
  33. }
  34. }
  • filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下:
    • pre:路由之前
    • routing:路由之时
    • post: 路由之后
    • error:发送错误调用
  • filterOrder:过滤的顺序
  • shouldFilter:这里可以写逻辑判断,是否要过滤,本文true,永远过滤。
  • run:过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。

这时访问:http://localhost:8769/api-a/hi?name=forezp ;网页显示:

token is empty

访问 http://localhost:8769/api-a/hi?name=forezp&token=22 ;
网页显示:

hi forezp,i am from port:8762

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/寸_铁/article/detail/794203
推荐阅读
相关标签
  

闽ICP备14008679号