SpringCloud 2.2.0 搭建学习

 

目录

一.SpringCloud简介

二.常用组成

三.代码实现

1.注册中心Eureak

2.客户端client

3.配置中心Config

4.应用监控与管理:actuator (可以放在任何一个springboot项目上)

5.客户端之间的调用feign(Feign 是对 Ribbon的封装,使用注解的方式,调用起来更简单。。。 也是主流的方式~)

6.客户端之间的调用Ribbon(Ribbon 是使用 restTemplate 进行调用,并进行客户端负载均衡。)

7.熔断器:hystrix(熔断只是作用在服务调用这一端,与feign一块使用)

8.网关



一.SpringCloud简介

springcloud是微服务架构,他是由多个独立项目集合而成的,每个项目都是独立的,各自进行自己的迭代和版本发布。所以springcloud不方便使用版本号来管理,而是使用版本名。以避免和子项目版本号的冲突。

二.常用组成

  1. 注册中心:eureak(除了eureak springcloud还提供了Consul服务中心)
  2. 客户端:client
  3. 配置中心:config
  4. 应用监控与管理:actuator
  5. 客户端之间的调用:feign
  6. 客户端负载均衡:ribbon
  7. 熔断器:hystrix
  8. 服务网关: Zuul,Geteway 
  9. 消息驱动:Stream
  10. 服务链路追踪:Zipkin
  11. 消息总线:Bus
  12. 批量任务:Task
  13. 授权认证:SpringSecurity

三.代码实现

1.注册中心Eureak

  • 创建一个springboot项目,里面啥组件都不许需要添加,或者用默认的eureak组件,我是搭建了一空的架子,一个一个添
  • 添加pom
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>



-------------------------------------------------------------------------------


<dependencyManagement>
   <dependencies>
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-dependencies</artifactId>
          <version>Greenwich.SR3</version>
          <type>pom</type>
          <scope>import</scope>
       </dependency>
    </dependencies>
</dependencyManagement>
  • 在启动类添加注解,来标识这是一个eureak服务
@EnableEurekaServer
  • 配置yml,单机配置,后面有其他的会在下面添加
server:
  port: 8010

spring:
  application:
    name: eureka-server

eureka:
  #指定主机名称
  instance:
    hostname: 127.0.0.1
  #server一定程度上也是client,互为client,
  client:
    #由于自己就是服务器,不需要注册到自己
    register-with-eureka: false
    #由于自己就是服务器,不需要从服务器获取注册信息
    fetch-registry: false
    #服务地址
    service-url:
      defaultZone: http://127.0.0.1:8010/eureka/
  • 启动访问:http://localhost:8010,出现下面的界面说明基本eureak搭建好了

  • 添加security账号认证,在pom中添加security包
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>2.1.8.RELEASE</version>
        </dependency>
  • 在yml中加入
server:
  port: 8010


spring:
  application:
    name: eureka-server
  security:
    basic:
      enabled: true
    user:
      name: herbert
      password: 123456

eureka:
  #指定主机名称
  instance:
    hostname: 127.0.0.1
  #server一定程度上也是client,互为client,
  client:
    #由于自己就是服务器,不需要注册到自己
    register-with-eureka: false
    #由于自己就是服务器,不需要从服务器获取注册信息
    fetch-registry: false
    #服务地址
    service-url:
      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@${eureka.instance.hostname}:${server.port}/eureka/
  • 加入一个CSRF禁用问题,这是一个坑,大坑,查资料了解到新版(Spring Cloud 2.0 以上)的security默认启用了csrf检验,要在eurekaServer端配置security的csrf检验为false
@EnableWebSecurity
class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().ignoringAntMatchers("/eureka/**");
        super.configure(http);
    }
}

 

2.客户端client

  • 创建一个springboot项目,里面啥组件都不许需要添加,或者用默认的eureak组件,我是搭建了一空的架子,一个一个添
  • 添加pom
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>


-------------------------------------------------------------------------------


<dependencyManagement>
   <dependencies>
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-dependencies</artifactId>
          <version>Greenwich.SR3</version>
          <type>pom</type>
          <scope>import</scope>
       </dependency>
    </dependencies>
</dependencyManagement>
  • 在启动类添加以下注解标识客户端
@EnableEurekaClient
  • 配置yml文件,现在连接的是没有security的服务端
server:
  port: 8005

spring:
  application:
    name: client-student-one

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8010/eureka/
  • 访问服务端eureak地址:http://localhost:8010,会出现下面红线的地方

  • 配置yml文件,现在连接的是有security的服务端
server:
  port: 8005

spring:
  application:
    name: client-student-one

eureka:
  client:
    service-url:
      defaultZone: http://herbert:[email protected]:8010/eureka/
  • 客户端自此配置完成,可以多配置几个客户端,方便后期的学习,我这边还添加了
server:
  port: 8006

spring:
  application:
    name: client-student-two

eureka:
  client:
    service-url:
      defaultZone: http://herbert:[email protected]:8010/eureka/


---------------------------------------------------------------------------------



server:
  port: 8007

spring:
  application:
    name: client-student-three

eureka:
  client:
    service-url:
      defaultZone: http://herbert:[email protected]:8010/eureka/

3.配置中心Config

  • 添加pom
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-config-server</artifactId>
</dependency>


-------------------------------------------------------------------------------


<dependencyManagement>
   <dependencies>
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-dependencies</artifactId>
          <version>Greenwich.SR3</version>
          <type>pom</type>
          <scope>import</scope>
       </dependency>
    </dependencies>
</dependencyManagement>
  • 再启动类加入以下配置来标记是配置中心
@EnableConfigServer
  • 配置yml,看下图我的几个配置

(1)application-client.yml

eureka:
  client:
    service-url:
      defaultZone: http://herbert:[email protected]:8010/eureka/

(2)application-eureka.yml

server:
  port: 8010


spring:
  application:
    name: eureka-server
  security:
    basic:
      enabled: true
    user:
      name: herbert
      password: 123456

eureka:
  instance:
    hostname: 127.0.0.1
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@${eureka.instance.hostname}:${server.port}/eureka/

(3)application.yml

server:
  port: 8102

spring:
  cloud:
    config:
      server:
        native:
          search-locations: classpath:/server/
  application:
    name: eureka-config
  profiles:
    active: native
  • eureka config-server就搭建完了,我们来测试一下,项目跑起来,输入:http://127.0.0.1:8102/server/client,如下图就搭建完了

  • 或者输入:http://127.0.0.1:8102/server/application-client.yml出现以下内容,就说明搭建成功

  • 下一步就是让客户端链接我们的服务中心,这里有一个大坑,就是springboot读取配置文件的顺序,这里要把application.yml改成bootstrap.yml  , 我这里将application.yml改成了bootstrap.yml

(1)加入pom的包

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

(2)配置bootstrap.yml

spring:
  cloud:
    config:
      label: server
      profile: client
      uri: http://localhost:8102
server:
  port: 8007

将所有的springboot都修改了,连接一个config,修改完后可以将config-server中的配置加载在其他服务里面

 

4.应用监控与管理:actuator (可以放在任何一个springboot项目上)

  • 新建一个springboot项目,查看一下
  • 添加pom
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  •  修改yml端口为 8011
server:
  port: 8011
management:
  endpoints:
    web:
      exposure:
        include: "*" #暴露所有端点 默认是info,health
{"status":"UP"} 是健康状态

具体可以参考一下下面的接口

其他的具体操作可以参考:https://blog.csdn.net/wya1993/article/details/80540981

 

5.客户端之间的调用feign(Feign 是对 Ribbon的封装,使用注解的方式,调用起来更简单。。。 也是主流的方式~)

  • 我们用客户端2通过feign调用客户端1的接口

在客户端2中引入pom

<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <version>2.1.3.RELEASE</version>
</dependency>

加入feign启动注解,表示我是一个feign客户端

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients
@EnableEurekaClient
public class ClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(ClientApplication.class, args);
    }

}

调用客户1的注解,首先在客户端1写一个接口

 客户端2开始调用这个接口了,通过接口调用,其中@FeigenClient里面的迷你必须是注册中心的名字,在http://localhost:8010/eureak服务中心查找

 最后就是在controller调用这个接口,调用成功

 访问这个接口调用成功

6.客户端之间的调用Ribbon(Ribbon 是使用 restTemplate 进行调用,并进行客户端负载均衡。)

  • 我们还是用客户端2和客户端1做测试,首先在客户端1中写一个接口为

  •  我们用客户端2通过ribbon调用客户端1的ribbon接口

1.在客户端2添加pom


<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>

 

2.我们初始化restTemplate (RestTemplate 是由 Spring Web 模块提供的工具类,与 SpringCloud 无关,是独立存在的因 SpringCloud 对 RestTemplate 进行了一定的扩展,所以 只注入实例化时被@LoadBalanced修饰的实例。)再启动类中加入

    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

3.调用客户端1的ribbon接口

这就是ribbon的调用,个人觉得还不如用feign

 

7.熔断器:hystrix(熔断只是作用在服务调用这一端,与feign一块使用)

  • 我们继续用客户端2调用客户端1的接口,使用feign+hystrix

1.现在客户端1写一个接口

2.在客户端2的yml中开启hystrix

feign:
  hystrix:
    enabled: true

3.因为hystrix和feign一块用,一个客户端不能出现两个接口连接同一个feign,所以我们在上面的feign上修改

修改FeignService接口

添加ProductClientFeignHystrix类

@Component
public class ProductClientFeignHystrix implements FeignService {

    @Override
    public String getFrignHystrix() {
        return "这个接口错了,现在到了这个接口这就是hystrix";
    }

    @Override
    public String getFeign() {
        return "这个接口错了,现在到了这个接口这就是hystrix";
    }
}

在FeignController添加api接口

 

测试:你先访问http://localhost:8006/feignHystrix  然后再把客户端1断开,你在访问自己可以试试两次结果

8.网关

zuul和getway的区别和选择

Spring Cloud Gateway 是 Spring Cloud 微服务平台的一个子项目,属于 Spring 开源社区,依赖名叫:spring-cloud-starter-gateway。它是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。

Spring Cloud Gateway 的特征:

  • 基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0
  • 动态路由
  • Predicates 和 Filters 作用于特定路由
  • 集成 Hystrix 断路器
  • 集成 Spring Cloud DiscoveryClient
  • 易于编写的 Predicates 和 Filters
  • 限流
  • 路径重写

 

Zuul 是 Netflix 公司的开源项目,Spring Cloud 在 Netflix 项目中也已经集成了 Zuul,依赖名叫:spring-cloud-starter-netflix-zuul。它提供了一个框架,可以对过滤器进行动态的加载,编译,运行。过滤器之间没有直接的相互通信。他们是通过一个RequestContext的静态类来进行数据传递的。RequestContext类中有ThreadLocal变量来记录每个Request所需要传递的数据。过滤器是由Groovy写成。这些过滤器文件被放在Zuul Server上的特定目录下面。Zuul会定期轮询这些目录。修改过的过滤器会动态的加载到Zuul Server中以便于request使用。

Zuul可以通过加载动态过滤机制,从而实现以下各项功能:

  • 验证与安全保障: 识别面向各类资源的验证要求并拒绝那些与要求不符的请求。
  • 审查与监控: 在边缘位置追踪有意义数据及统计结果,从而为我们带来准确的生产状态结论。
  • 动态路由: 以动态方式根据需要将请求路由至不同后端集群处。
  • 压力测试: 逐渐增加指向集群的负载流量,从而计算性能水平。
  • 负载分配: 为每一种负载类型分配对应容量,并弃用超出限定值的请求。
  • 静态响应处理: 在边缘位置直接建立部分响应,从而避免其流入内部集群。
  • 多区域弹性: 跨越AWS区域进行请求路由,旨在实现ELB使用多样化并保证边缘位置与使用者尽可能接近。



作者:一个会写诗的程序员
链接:https://www.jianshu.com/p/e0434a421c03
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

 

 

一、Zuul(俗称springcloud的看门狗)

1.新建一个springboot2.0x的空架子,在pom中引入

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
        
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
   <version>2.1.2.RELEASE</version>
</dependency>


--------------------------------------------------------

<dependencyManagement>
   <dependencies>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-dependencies</artifactId>
         <version>Hoxton.RC2</version>
         <type>pom</type>
         <scope>import</scope>
       </dependency>
    </dependencies>
</dependencyManagement>

2.再启动类加入注解

@EnableZuulProxy
@EnableEurekaClient

 3.配置yml文件

server:
  port: 8017
eureka:
  client:
    serviceUrl:
      defaultZone: http://herbert:[email protected]:8010/eureka/
spring:
  application:
    name: eureka-zuul
zuul:
  routes:
    api-a:
      path: /api-one/**
      serviceId: CLIENT-STUDENT-ONE
    api-b:
      path: /api-two/**
      serviceId: CLIENT-STUDENT-TWO

4.现在基本的zuul就搭建起来了。把项目跑起来访问client1的feign接口

原来访问是:localhost:8005/feign

现在通过zuul访问:localhost:8017/api-one/feign 就可以了

5.写zuulFilter

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * @Author:hemingzhu
 * @date: 2019/11/23 10:27
 * @Explanation:
 */
@Component
public class ZuulFiterTest extends ZuulFilter {

    @Override
    public String filterType() {
        System.out.println("11111");
        return "pre"; // 可以在请求被路由之前调用
    }

    @Override
    public int filterOrder() {
        // filter执行顺序,通过数字指定 ,优先级为0,数字越大,优先级越低
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        // 是否执行该过滤器,此处为true,说明需要过滤
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        System.out.println(("--->>> TokenFilter {},{}"+ request.getMethod()+"->"+request.getRequestURL().toString()));
        String token = request.getParameter("token");// 获取请求的参数
        if (StringUtils.isNotBlank(token)) {
            ctx.setSendZuulResponse(true); //对请求进行路由
            ctx.setResponseStatusCode(200);
            ctx.set("isSuccess", true);
            return null;
        } else {
            ctx.setSendZuulResponse(false); //不对其进行路由
            ctx.setResponseStatusCode(400);
            ctx.setResponseBody("token is empty");
            ctx.set("isSuccess", false);
            return null;
        }
    }
}

过滤器这就成功了

6.回退机制fallback

package com.herbert.eureak.zuul.fallback;


import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;



/**
 * @Author:hemingzhu
 * @date: 2019/11/23 10:54
 * @Explanation:
 */
@Component
public class ZuulFallBack implements FallbackProvider {

    @Override
    public String getRoute() {
        return null;  //服务id,可以用* 或者 null 代表所有服务都过滤
    }

    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        return new ClientHttpResponse() {
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.OK; //请求网关成功了,所以是ok
            }

            @Override
            public int getRawStatusCode() throws IOException {
                return HttpStatus.OK.value();
            }

            @Override
            public String getStatusText() throws IOException {
                return HttpStatus.OK.getReasonPhrase();
            }

            @Override
            public void close() {

            }

            @Override
            public InputStream getBody() throws IOException {
                return new ByteArrayInputStream("错误".getBytes("UTF-8")); //返回前端的内容
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders httpHeaders = new HttpHeaders();
                httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); //设置头
                return httpHeaders;
            }
        };


    }
}

测试:我们将客户端挂了访问  ----》 localhost:8017/api-one/feign?token=1  (token主要是过filter的,如果不写将filter屏蔽了就好)

zuul我们就说到这里

二、getway

 

 

 

 

 

---------------------------------------------------后续慢慢更新------------------------------------------------------

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章