SpringCloud入门

SpringCloud

1、springcloud概述

SpringCloud是一种微服务架构,依赖于SpringBoot,主要用于服务治理(解耦),其中每一个服务都可以独立运行,服务之间没有依懒关系

2、Eureka注册中心搭建

1、pom.xml配置

<parent>

      <groupId>org.springframework.boot</groupId>

      <artifactId>spring-boot-starter-parent</artifactId>

      <version>1.5.2.RELEASE</version>

      <relativePath />

   </parent>

  

   <properties>

      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

   <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

      <java.version>1.8</java.version>

   </properties>

  

   <dependencies>

      <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter</artifactId>

      </dependency>

      <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-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>Dalston.RC1</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>

   <repositories>

      <repository>

        <id>spring-milestones</id>

        <name>Spring Milestones</name>

        <url>https://repo.spring.io/milestone</url>

        <snapshots>

           <enabled>false</enabled>

        </snapshots>

      </repository>

   </repositories>

2、application.properties配置

spring.application.name=spring-cloud-eureka

server.port=8000

eureka.client.register-with-eureka=false

eureka.client.fetch-registry=false

eureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/

eureka.client.register-with-eureka :表示是否将自己注册到Eureka Server,默认为true。

eureka.client.fetch-registry :表示是否从Eureka Server获取注册信息,默认为true。

eureka.client.serviceUrl.defaultZone :服务注册中心的配置内容,指定服务注册中心的位置。默认是http://localhost:8761/eureka ;多个地址可使用 , 分隔。

注:Eureka的yml配置文件中冒号后必须有空格,不能是’\t’;

3、服务启动

@SpringBootApplication

@EnableEurekaServer

public class EurekaApp {

   public static void main(String[] args) {

      SpringApplication.run(EurekaApp.class, args);

   }

}

@EnableEurekaServer启动一个服务注册中心提供给其他服务进行注册

@SpringBootApplication:扫描当前包及其子包下的带有@Component,@Controller,@Service,@Repository注解的类,并纳入spring容器进行管理配置

4、Eureka集群

1、application.properties配置

application.properties:

spring:

  application:

    name: spring-cloud-eureka

  profiles:

   active: peer1

application-peer1.properties:

 

 

spring.profiles=peer1

server.port=8000

eureka.client.serviceUrl.defaultZone=http://peer2:8001/eureka/, http://peer3:8002/eureka/

application-peer2.properties:

spring.profiles=peer2

server.port=8001

eureka.client.serviceUrl.defaultZone=http://peer1:8000/eureka/, http://peer3:8002/eureka/

application-peer3.properties:

spring.profiles=peer3

server.port=8002

eureka.client.serviceUrl.defaultZone=http://peer1:8000/eureka/, http://peer2:8001/eureka/

2、在C:\Windows\System32\drivers\etc下的hosts文件中加入

127.0.0.1  peer1

127.0.0.1  peer2

127.0.0.1  peer3

3、打包

--->maven build …--->clean package

4、依次启动

java -jar E:\java\spring-cloud-eureka\target\spring-cloud-eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer1

java -jar E:\java\spring-cloud-eureka\target\spring-cloud-eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer2

java -jar E:\java\spring-cloud-eureka\target\spring-cloud-eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer3

 

3、服务提供者

1、pom.xml配置

<parent>

      <groupId>org.springframework.boot</groupId>

      <artifactId>spring-boot-starter-parent</artifactId>

      <version>1.5.2.RELEASE</version>

      <relativePath />

   </parent>

   <properties>

      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

   <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

      <java.version>1.8</java.version>

   </properties>

   <dependencies>

      <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-eureka</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>Dalston.RC1</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>

   <repositories>

      <repository>

        <id>spring-milestones</id>

        <name>Spring Milestones</name>

        <url>https://repo.spring.io/milestone</url>

        <snapshots>

           <enabled>false</enabled>

        </snapshots>

      </repository>

   </repositories>

2、application.properties配置

spring.application.name=spring-cloud-provider

server.port=9000

eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/

3、服务启动

@SpringBootApplication

@EnableEurekaClient

public class ProviderApp {

   public static void main(String[] args) {

      SpringApplication.run(ProviderApp.class, args);

   }

}

@EnableDiscoveryClient启用服务注册与发现

@EnableEurekaClient启用服务注册与发现

4、controller

@RestController

public class ProviderController {

   @RequestMapping("/provider")

    public String proindex(@RequestParam String name) {

        return "hello "+name+",this is first provider messge";

    }

}

 

 

4、服务消费者

1、pom.xml配置

<parent>

      <groupId>org.springframework.boot</groupId>

      <artifactId>spring-boot-starter-parent</artifactId>

      <version>1.5.2.RELEASE</version>

      <relativePath />

   </parent>

   <properties>

      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

   <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

      <java.version>1.8</java.version>

   </properties>

   <dependencies>

      <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-eureka</artifactId>

      </dependency>

      <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-test</artifactId>

        <scope>test</scope>

      </dependency>

      <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-feign</artifactId>

      </dependency>

      <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-hystrix</artifactId>

      </dependency>

      <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>

      </dependency>

      <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-actuator</artifactId>

      </dependency>

   </dependencies>

   <dependencyManagement>

      <dependencies>

        <dependency>

           <groupId>org.springframework.cloud</groupId>

           <artifactId>spring-cloud-dependencies</artifactId>

           <version>Dalston.RC1</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>

   <repositories>

      <repository>

        <id>spring-milestones</id>

        <name>Spring Milestones</name>

        <url>https://repo.spring.io/milestone</url>

        <snapshots>

           <enabled>false</enabled>

        </snapshots>

      </repository>

   </repositories>

2、application.properties配置

spring.application.name=spring-cloud-consumer

server.port=9100

eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/

 

3、服务启动

1、rest启动

@SpringBootApplication

@EnableEurekaClient

public class ConsumerApp {

   public static void main(String[] args) {

      SpringApplication.run(ConsumerApp.class, args);

   }

}

 

2、feign启动

@SpringBootApplication

@EnableEurekaClient

@EnableFeignClients

public class Consumer1App {

   public static void main(String[] args) {

      SpringApplication.run(Consumer1App.class, args);

   }

}

@EnableFeignClients启用feign进行远程调用

4、rest调用

1、controller

@RestController

public class ConsumerController {

   @Autowired

   private ConsumerService cs;

   @RequestMapping("/consumer")

    public String conindex() {

      return cs.getConsumer();

    }

}

2、service

@Service

public class ConsumerService {

   @Autowired

   private RestTemplate rt;

 

   public String getConsumer() {

      return rt.getForObject("http://spring-cloud-provider/provider",String.class);

   }

}

 

5、feign调用

1、controller

@RestController

public class Consumer1Controller {

   @Autowired

   HelloRemote helloRemote;

   @RequestMapping("/consumer1/{name}")

   public String index(@PathVariable("name") String name) {

      return helloRemote.index(name);

   }

}

2、service

@FeignClient(name="spring-cloud-provider1")

public interface HelloRemote {

   @RequestMapping("/provider1")

    public String index(@RequestParam(value = "name") String name);

}

@FeignClient指定要绑定的远程调用的服务,参数为服务的名字

@RequestMapping为调用的提供者方法的映射名

SpringMVC@RequestParam@RequestHeader注解,如果我们不指定value,则默认采用参数的名字作为其value,但是在Feign中,这个value必须明确指定,否则会报错。

5、hystrix

1、配置文件

feign.hystrix.enabled=true

2、客户端调用

@FeignClient(name="spring-cloud-provider",fallback=FallbackRemote.class)

public interface HelloRemote {

   @RequestMapping(value = "/hello1", method = RequestMethod.GET)

   String hello(@RequestParam("name") String name);

   @RequestMapping(value = "/hello2", method = RequestMethod.GET)

   User hello(@RequestHeader("name") String name, @RequestHeader("age") Integer age);

   @RequestMapping(value = "/hello3", method = RequestMethod.POST)

   String hello(@RequestBody User user);

}

3、启动类

@EnableCircuitBreaker

@EnableHystrixDashboard(开启监控)

6、zuul网关

1、pom文件配置

<dependency>

    <groupId>org.springframework.cloud</groupId>

    <artifactId>spring-cloud-starter-zuul</artifactId>

</dependency>

2、配置

eureka:

  client:

    serviceUrl:

      defaultZone: http://localhost:8000/eureka/

server:

  port: 9400

spring:

  application:

    name: zuul

zuul:

  routes:

    api-a:

      path: /provider/**

      service-id: spring-cloud-provider

    api-b:

      path: /consumer/**

      service-id: spring-cloud-consumer

1、zuul默认配置

spring cloud zuul已经帮我们做了默认配置。默认情况下,Zuul会代理所有注册到Eureka Server的微服务,并且Zuul的路由规则如下:

http://ZUUL_HOST:ZUUL_PORT/微服务在Eureka上的serviceId/**

会被转发到serviceId对应的微服务

2、zuul熔断

Zuul 目前只支持服务级别的熔断,不支持具体到某个URL进行熔断。

 

3、启动类

@EnableZuulProxy

@EnableEurekaClient

@SpringBootApplication

public class AppZull {

    public static void main(String[] args) {

      SpringApplication.run(AppZull.class, args);

   }

}

4、zuul负载均衡

Zuul负载均衡是属于客户端的负载均衡

客户端负载均衡:

基于客户端的负载均衡,简单的说就是在客户端程序里面,自己设定一个调度算法,在向服务器发起请求的时候,先执行调度算法计算出向哪台服务器发起请求,然后再发起请求给服务器。

特点:

  1. 由客户端内部程序实现,不需要额外的负载均衡器软硬件投入。
  2. 程序内部需要解决业务服务器不可用的问题,服务器故障对应用程序的透明度小。
  3. 程序内部需要解决业务服务器压力过载的问题。

使用场景:

  1. 可以选择为初期简单的负载均衡方案,和DNS负载均衡一样。
  2. 比较适合于客户端具有成熟的调度库函数,算法以及API等
  3. 比较适合对服务器入流量较大的业务,如HTTP POST文件上传,FTP文件上传,Memcache大流量写入。
  4. 可以结合其他负载均衡方案进行架构。

5、Zuul的核心Filter

1、概述

Filter是Zuul的核心,用来实现对外服务的控制。Filter的生命周期有4个,分别是“PRE”、“ROUTING”、“POST”、“ERROR”;

Zuul大部分功能都是通过过滤器来实现的,这些过滤器类型对应于请求的典型生命周期。

  • PRE 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
  • ROUTING这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
  • POST这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
  • ERROR在其他阶段发生错误时执行该过滤器。
    除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。例如,我们可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。

 

 

2、Zuul中默认实现的Filter

类型     顺序     过滤器                               功能

pre             -3         ServletDetectionFilter             标记处理Servlet的类型

pre             -2         Servlet30WrapperFilter          包装HttpServletRequest请求

pre             -1         FormBodyWrapperFilter        包装请求体

route 1          DebugFilter                          标记调试标志

route 5          PreDecorationFilter          处理请求上下文供后续使用

route 10               RibbonRoutingFilter          serviceId请求转发

route 100     SimpleHostRoutingFilter url    请求转发

route 500     SendForwardFilter                   forward请求转发

post     0          SendErrorFilter                   处理有错误的请求响应

post     1000   SendResponseFilter           处理正常的请求响应

3、禁用指定的Filter

zuul:

    FormBodyWrapperFilter:

        pre:

            disable: true

4、自定义Filter

public class MyFilter extends ZuulFilter {

    @Override

    String filterType() {

        return "pre"; //定义filter的类型,有pre、route、post、error四种

    }

    @Override

    int filterOrder() {

        return 10; //定义filter的顺序,数字越小表示顺序越高,越先执行

    }

    @Override

    boolean shouldFilter() {

        return true; //表示是否需要执行该filter,true表示执行,false表示不执行

    }

    @Override

Object run() {

return null; //filter需要执行的具体操作

/*

RequestContext ctx = RequestContext.getCurrentContext();

              HttpServletRequest request = ctx.getRequest();

              log.info(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString()));

              Object accessToken = request.getParameter("token");

              String refer=request.getHeader("refer");

      

              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;

*/

    }

}

5、将TokenFilter加入到请求拦截队列,在启动类中添加代码:

@Bean

public TokenFilter tokenFilter() {

    return new TokenFilter();

}

7、config配置中心

1、config-server搭建

1、pom依赖

<dependency>

        <groupId>org.springframework.cloud</groupId>

   <artifactId>spring-cloud-config-server</artifactId>

</dependency>

2、配置

spring.application.name=config-server

server.port=9200

spring.cloud.config.server.git.uri=https://gitee.com/archimedes123/config.git

spring.cloud.config.server.git.username=

spring.cloud.config.server.git.password=

eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/

假设远程配置文件名为config-dev.properties

内容为:hellohello im dev

它的applicationconfigprofiledev。client会根据填写的参数来选择读取对应的配置。

仓库中的配置文件会被转换成web接口,访问可以参照以下的规则:

1/{application}/{profile}[/{label}]

2/{application}-{profile}.*

3/{label}/{application}-{profile}.*

3、启动类

@SpringBootApplication

@EnableConfigServer

@EnableEurekaClient

public class ConfigServerApp {

   public static void main(String[] args) {

      SpringApplication.run(ConfigServerApp.class, args);

   }

}

4、webhook机制检测更新配置(需要消息中间件支持rabbitMQ)

1、pom依赖

<dependency>

       <groupId>org.springframework.cloud</groupId>

       <artifactId>spring-cloud-starter-bus-amqp</artifactId>

</dependency>

2、配置文件

server:

  port: 8001

spring:

  application:

    name: spring-cloud-config-server

  cloud:

    config:

      server:

        git:

          uri: https://github.com/ityouknow/spring-cloud-starter/    

# 配置git仓库的地址

          search-paths: config-repo                            

# git仓库地址下的相对地址,可以配置多个,用,分割。

          username: username                                       

# git仓库的账号

          password: password                                  

 # git仓库的密码

  rabbitmq:

    host: 192.168.0.6

    port: 5672

    username: admin

    password: 123456

eureka:

  client:

    serviceUrl:

      defaultZone: http://localhost:8000/eureka/   ## 注册中心eurka地址

management:

  security:

     enabled: false

2config-client搭建

1、pom依赖

<dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-config</artifactId>

</dependency>

<dependency>

        <groupId>org.springframework.cloud</groupId>

   <artifactId>spring-cloud-starter-eureka</artifactId>

</dependency>

<dependency>

        <groupId>org.springframework.boot</groupId>

      <artifactId>spring-boot-starter-web</artifactId>

</dependency>

<dependency>

        <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-test</artifactId>

        <scope>test</scope>

</dependency>

2、bootstrap.properties配置

spring.application.name=config-client

spring.cloud.config.name=config

spring.cloud.config.profile=dev

spring.cloud.config.label=master

server.port=9300

eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/

spring.cloud.config.discovery.enabled=true

spring.cloud.config.discovery.serviceId=config-server

  • ·         spring.cloud.config.name:对应{application}部分
  • ·         spring.cloud.config.profile:对应{profile}部分
  • ·         spring.cloud.config.label:对应git的分支。如果配置中心使用的是本地存储,则该参数无用
  • ·         spring.cloud.config.uri:配置中心的具体地址
  • ·         spring.cloud.config.discovery.service-id:指定配置中心的service-id,便于扩展为高可用配置集群。

特别注意:上面这些与spring-cloud相关的属性必须配置在bootstrap.properties中,config部分内容才能被正确加载。因为config的相关配置会先于application.properties,而bootstrap.properties的加载也是先于application.properties

@RefreshScope:使用该注解的类,会在接到SpringCloud配置中心配置刷新的时候,自动将新的配置更新到该类对应的字段中。

3、启动类

@SpringBootApplication

@EnableEurekaClient

public class ConfigClientApp {

   public static void main(String[] args) {

      SpringApplication.run(ConfigClientApp.class, args);

   }

}

4、controller

@RestController

@RefreshScope//客户端启动配置中心自动更新

public class TestController {

   @Value("${hello}")

   private String hello;

   @RequestMapping("/getHello")

   public String getHello() {

      return this.hello;

   }

}

8、springcloud负载均衡

zuul也有负载均衡的功能,它是针对外部请求做负载,那客户端ribbon的负载均衡又是怎么一回事?

客户端ribbon的负载均衡,解决的是服务发起方(在Eureka注册的服务)对被调用的服务的负载,比如我们查询商品服务要调用显示库存和商品明细服务,通过商品服务的接口将两个服务组合,可以减少外部应用的请求,比如手机App发起一次请求即可,可以节省网络带宽,也更省电。

ribbon是对服务之间调用做负载,是服务之间的负载均衡,zuul是可以对外部请求做负载均衡。 

1、负载均衡策略设置

1、rabbion配置文件

service-B.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

其中service-B是我注册到Eureka的serviceID。

2、启动类

@Bean

public IRule ribbonRule() {

       return new RandomRule();//这里配置策略,和配置文件对应

}

3、controller

@RestController

public class ConsumerController {

    @Autowired

    private RestTemplate restTemplate;

    @Autowired 

    private LoadBalancerClient loadBalancerClient; 

    @RequestMapping(value = "/add", method = RequestMethod.GET)

    public String add(@RequestParam Integer a,@RequestParam Integer b) {

        this.loadBalancerClient.choose("service-B");//负载均衡策略

        return restTemplate.getForEntity("http://service-B/add?a="+a+"&b="+b, String.class).getBody();

    }

}

9、springcloud注解

1、@EnableEurekaServer:

启动一个服务注册中心提供给其他应用进行对话

2、@EnableZuulProxy:

开启网关;

3、@FeignClient:

发现服务

4@EnableFeignClients

启用feign进行远程调用

5@EnableCircuitBreaker:

启动断路器

6、@EnableDiscoveryClient:

启用服务注册与发现

7、@EnableEurekaClient:

启用服务注册与发现

@EnableDiscoveryClient基于spring-cloud-commons; @EnableEurekaClient基于spring-cloud-netflix;其实用更简单的话来说,就是如果选用的注册中心是eureka,那么就推荐@EnableEurekaClient,如果是其他的注册中心,那么推荐使用@EnableDiscoveryClient。

 

posted @ 2018-11-17 21:11  束发读诗书  阅读(442)  评论(0编辑  收藏  举报