SpringCloud--Netflix入门

2022-09-20 16:53:02 浏览数 (1)

SpringCloud是一系列框架的集合,目的是将业务系统拆分成一个个微服务,服务于服务之间相互独立,支持水平扩展,高可用,微服务架构主要的功能有服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,Netflix虽然已经过时了,但是他框架集和其他微服务框架集作用差不多

微服务整体架构如下图,看看就好:

Netflix主要使用下面的组件:

组件

描述

Eureka

服务注册中心、服务发现中心

Ribbon

负载均衡,服务如果是一个集群,会通过Ribbon实现负载均衡

Feign

服务于服务之间的调用

Hystrix

监控和熔断器,服务降级与数据统计

Zuul

网关,所有请求由网关转发到具体的服务

一、项目搭建

首先搭建一个聚合项目,结构如下:

1. commons模块

commons模块是一个普通的Maven项目,存放JavaBean和工具类

2. dependency模块

其他模块都依赖于dependency模块,主要做SpringBoot的版本控制:

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>

    <groupId>com.aruba</groupId>
    <artifactId>dependency</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>dependency</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>2.3.7.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>
3. eureka模块

eureka模块就是我们首先使用的组件,用于服务注册和发现

二、Eureka

1. eureka服务端

eureka模块单独启动,作为服务端

1.1 依赖

导入eureka服务依赖:

代码语言:javascript复制
    <parent>
        <artifactId>dependency</artifactId>
        <groupId>com.aruba</groupId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../dependency/pom.xml</relativePath>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--eureka服务-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>
1.2 @EnableEurekaServer

SpringBoot启动类上添加@EnableEurekaServer注解开启Eureka:

代码语言:javascript复制
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {

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

}

启动后可以访问到eureka界面:

1.3 配置Eureka服务地址

此时虽然可以访问页面,但是eureka服务并没有真正的启动,yml文件需要配置,需要注意的是application.name将会作为服务名注册到eureka中,后续调用方会使用该名称:

代码语言:javascript复制
spring:
  application:
    name: aruba-eureka

server:
  port: 7000

eureka:
  instance:
    hostname: aruba-eureka
  client:
    service-url:
      # 指定eureka服务的地址
      defaultZone: http://127.0.0.1:7000/eureka
    # 当前项目关闭注册服务
    register-with-eureka: false
    # 当前项目关闭获取服务
    fetch-registry: false
2. eureka客户端

再次新建一个dept模块作为eureka的客户端,用于注册服务到eureka服务器

2.1 依赖

导入eureka客户端依赖:

代码语言:javascript复制
    <parent>
        <artifactId>dependency</artifactId>
        <groupId>com.aruba</groupId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../dependency/pom.xml</relativePath>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--eureka客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.aruba</groupId>
            <artifactId>commons</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
2.2 @EnableEurekaClient

使用@EnableEurekaClient注解开启Eureka客户端

代码语言:javascript复制
@SpringBootApplication
@EnableEurekaClient
public class DeptApplication {

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

}
2.3 配置Eureka服务地址
代码语言:javascript复制
spring:
  application:
    name: aruba-dept

server:
  port: 8000

eureka:
  client:
    service-url:
      # 指定eureka服务的地址
      defaultZone: http://127.0.0.1:7000/eureka
2.4 启动客户端服务

启动服务后,再次访问Eureka管理页面,可以看到新注册的服务:

三、Feign

有了服务提供者,注册中心,消费者就可以通过Feign调用提供者

1. 完善dept模块
1.1 Javabean

commons模块中创建实体类:WDept,用于服务与服务之间传输

代码语言:javascript复制
@AllArgsConstructor
@NoArgsConstructor
@Data
public class WDept implements Serializable {
    /**
     * 部门编号
     */
    private Integer deptId;
    /**
     * 部门名称
     */
    private String dName;
}
1.2 service层

dept模块中编写相应的service层代码

接口:

代码语言:javascript复制
public interface DeptService {
    String insertDept(WDept dept);
}

实现:

代码语言:javascript复制
@Service
public class DeptServiceImpl implements DeptService {

    @Override
    public String insertDept(WDept dept) {
        return "收到:"   dept.toString();
    }

}
1.3 提供Controller

Feign本质上是通过http进行调用的,controller层对外提供接口:

代码语言:javascript复制
@RestController
public class DeptController {
    @Autowired
    private DeptService deptService;

    @RequestMapping("/insertDept")
    public String insertDept(@RequestBody WDept wDept) {
        return deptService.insertDept(wDept);
    }

}
2. 调用方模块

新建模块,作为调用方:

2.1 依赖

导入eureka客户端和openFeign依赖:

代码语言:javascript复制
    <parent>
        <artifactId>dependency</artifactId>
        <groupId>com.aruba</groupId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../dependency/pom.xml</relativePath>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--eureka客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.aruba</groupId>
            <artifactId>commons</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
2.2 yml文件配置

需要配置的和dept模块差不多:

代码语言:javascript复制
spring:
  application:
    name: aruba-dept-api

server:
  port: 8001

eureka:
  client:
    service-url:
      # 指定eureka服务的地址
      defaultZone: http://127.0.0.1:7000/eureka
2.3 @EnableFeignClients

使用@EnableFeignClients注解配置启动类,表示作为服务调用方

代码语言:javascript复制
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class DeptApiApplication {

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

}
2.4 @FeignClient

使用@FeignClient注解接口,并指定调用服务名,对应application.name,定义一个和调用方接口一样的方法

代码语言:javascript复制
@FeignClient("aruba-dept")
public interface DeptFeignClient {

    @RequestMapping("/insertDept")
    String insertDept(WDept dept);

}
2.5 使用Feign

在调用方controller层中,注入刚刚的接口,并调用,需要注意的是加上@CrossOrigin注解支持跨域

代码语言:javascript复制
@RestController
@CrossOrigin
public class DeptController {
    @Autowired
    private DeptFeignClient deptFeignClient;

    @RequestMapping("/insertDept")
    public String insertDept(@RequestParam("deptId") Integer id) {
        return deptFeignClient.insertDept(new WDept(id, "Feign"));
    }

}

尝试调用:

四、Robbin

Feign集成了Robbin,默认就支持负载均衡,默认使用轮询策略,一旦遇上服务集群就会触发

1. 配置多个yml

修改端口为:

代码语言:javascript复制
server:
  port: 8010
代码语言:javascript复制
server:
  port: 8011
代码语言:javascript复制
server:
  port: 8012
2. 配置启动

配置多个启动项,并指定使用yml文件:--spring.profiles.active=xxx,这边对应就是1,2,3:

3. 调用接口

启动多个服务,并调用消费者接口:

效果:

五、Hystrix

hystrix作为保证整体服务可用的组件,拥有服务降级和服务熔断功能,当一个微服务无法访问或长时间无响应,hystrix会自动帮助调用方进行处理,防止出现服务雪崩,因为hystrix是集成在服务调用方

1. 依赖

dept-api模块导入hystrix依赖:

代码语言:javascript复制
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
2. yml配置

添加hystrix相关配置:

代码语言:javascript复制
spring:
  application:
    name: aruba-dept-api

server:
  port: 8001

eureka:
  client:
    service-url:
      # 指定eureka服务的地址
      defaultZone: http://127.0.0.1:7000/eureka

# 开启hystrix
feign:
  hystrix:
    enabled: true

# 请求超时时间
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 2000
3. @EnableHystrix

启动类添加@EnableHystrix注解:

代码语言:javascript复制
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableHystrix
public class DeptApiApplication {

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

}

此时为服务提供方接口调用添加一个睡眠:

代码语言:javascript复制
@Service
public class DeptServiceImpl implements DeptService {

    @Override
    public String insertDept(WDept dept) {
        System.out.println(dept);
        try {
            Thread.sleep(13000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "收到:"   dept.toString();
    }

}

再次调用接口,2秒后会出现500错误,表示hystrix生效了:

4. 失败处理

接下来就要指定hystrix服务降级后,进行自己的业务处理,实际上feign与hystrix已经结合,我们之前定义了DeptFeignClient接口,需要实现一个该接口的类作为降级回调处理类:

代码语言:javascript复制
@Component
public class DeptFeignFallCallback implements DeptFeignClient {
    @Override
    public String insertDept(WDept dept) {
        return "服务发生错误";
    }
}

接口类的@FeignClient注解添加fallback属性值,指定为处理类:

代码语言:javascript复制
@FeignClient(value = "aruba-dept", fallback = DeptFeignFallCallback.class)
public interface DeptFeignClient {

    @RequestMapping("/insertDept")
    String insertDept(WDept dept);

}

再次调用接口,会返回自定义回调处理的结果:

六、Hystrix仪表盘

Hystrix仪表盘是监测触发熔断数据统计的管理页面,配置好后可以方便查看信息

新建模块:

1. 导入依赖

除了web外,还需要actuatorhystrix-dashboard依赖

代码语言:javascript复制
    <parent>
        <artifactId>dependency</artifactId>
        <groupId>com.aruba</groupId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../dependency/pom.xml</relativePath>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>
    </dependencies>
2. yml配置
代码语言:javascript复制
spring:
  application:
    name: aruba-hystrix-client

server:
  port: 9000

hystrix:
  dashboard:
    proxy-stream-allow-list: "localhost"
3. @EnableHystrixDashboard

使用@EnableHystrixDashboard注解在启动类上:

代码语言:javascript复制
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixClientApplication {

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

}

启动后访问localhost:9000/hystrix,就可以看到管理界面了:

4. 模块中配置

仅仅有上面的配置是不够的,还需要指定监测服务的一些配置,我们监测的是使用hystrix的dept-api模块,所以在该模块中添加配置类:

配置类提供ServletRegistrationBean的注入,内容为:

代码语言:javascript复制
@Configuration
public class DeptActuator {

    @Bean
    public ServletRegistrationBean getServletRegistrationBean(){

        HystrixMetricsStreamServlet mss = new HystrixMetricsStreamServlet();

        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(mss);

        servletRegistrationBean.setName("servletRegistrationBean");
        servletRegistrationBean.setLoadOnStartup(1);
        servletRegistrationBean.addUrlMappings("/hystrix.stream");
        return servletRegistrationBean;
    }

}
5. 输入具体监测地址

管理中输入:http://localhost:8001/hystrix.stream,对应提供配置的dept-api模块的端口和配置的url

进入后,尝试访问服务接口后,有了数据,才会出现数据统计:

七、Zuul

Zuul是微服务中的网关,在所有微服务内部,所有请求都应该由网关进行转发请求,网关提供统一的对外接口,功能概念和nginx差不多,但是nginx处于更上的接入层,性能方面没有可比较性,而微服务的网关组件都和SpringBoot有着较好的融合,使用方便

新建模块:

1. 依赖

导入zuul依赖以及eureka客户端依赖:

代码语言:javascript复制
    <parent>
        <artifactId>dependency</artifactId>
        <groupId>com.aruba</groupId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../dependency/pom.xml</relativePath>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
    </dependencies>
2. yml配置

争对对外的微服务配置路由,可以配置多条,一般使用服务的application.name作为配置名,path为反向代理后的访问前缀,serviceId为服务的application.name

代码语言:javascript复制
spring:
  application:
    name: aruba-zuul

server:
  port: 8080

#配置一个路由器
zuul:
  routes:
    dept-api:
      path: /oapi/**
      serviceId: aruba-dept-api

#从eureka获取我们的服务器的真实ip地址
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:7000/eureka

  instance:
    prefer-ip-address: true
    instance-id: ${spring.cloud.client.ip-address}:${server.port}
3. @EnableZuulProxy

使用@EnableZuulProxy注解在启动类上:

代码语言:javascript复制
@SpringBootApplication
@EnableZuulProxy
@EnableEurekaClient
public class ZuulApplication {

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

}

启动后,可以通过http://localhost:8080/oapi/xxx进行对dept-api模块的访问:

项目地址:

https://gitee.com/aruba/netflix-study.git

0 人点赞