SpringCloud--Netflix入门

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

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

Netflix主要使用下面的组件:

组件 描述
Eureka 服务注册中心、服务发现中心
Ribbon 负载均衡,服务如果是一个集群,会通过Ribbon实现负载均衡
Feign 服务于服务之间的调用
Hystrix 监控和熔断器,服务降级与数据统计
Zuul 网关,所有请求由网关转发到具体的服务

一、项目搭建

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

1. commons模块

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

2. dependency模块

SpringBoot和SpringCloud版本是有对应关系的,要保持版本对应,否则会出现运行不了的情况:

Spring Cloud Alibaba Version Spring Cloud Version Spring Boot Version
2021.0.1.0 Spring Cloud 2021.0.1 2.6.3
2.2.7.RELEASE Spring Cloud Hoxton.SR12 2.3.12.RELEASE
2021.1 Spring Cloud 2020.0.1 2.4.2
2.2.6.RELEASE Spring Cloud Hoxton.SR9 2.3.2.RELEASE
2.1.4.RELEASE Spring Cloud Greenwich.SR6 2.1.13.RELEASE
2.2.1.RELEASE Spring Cloud Hoxton.SR3 2.2.5.RELEASE
2.2.0.RELEASE Spring Cloud Hoxton.RELEASE 2.2.X.RELEASE
2.1.2.RELEASE Spring Cloud Greenwich 2.1.X.RELEASE
2.0.4.RELEASE(停止维护,建议升级) Spring Cloud Finchley 2.0.X.RELEASE
1.5.1.RELEASE(停止维护,建议升级) Spring Cloud Edgware 1.5.X.RELEASE

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

<?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服务依赖:

    <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:

@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中,后续调用方会使用该名称:

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客户端依赖:

    <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客户端

@SpringBootApplication
@EnableEurekaClient
public class DeptApplication {

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

}
2.3 配置Eureka服务地址
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,用于服务与服务之间传输

@AllArgsConstructor
@NoArgsConstructor
@Data
public class WDept implements Serializable {
    /**
     * 部门编号
     */
    private Integer deptId;
    /**
     * 部门名称
     */
    private String dName;
}
1.2 service层

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

接口:

public interface DeptService {
    String insertDept(WDept dept);
}

实现:

@Service
public class DeptServiceImpl implements DeptService {

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

}
1.3 提供Controller

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

@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依赖:

    <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模块差不多:

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注解配置启动类,表示作为服务调用方

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class DeptApiApplication {

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

}
2.4 @FeignClient

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

@FeignClient("aruba-dept")
public interface DeptFeignClient {

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

}
2.5 使用Feign

在调用方controller层中,注入刚刚的接口,并调用:

@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

修改端口为:

server:
  port: 8010
server:
  port: 8011
server:
  port: 8012

2. 配置启动

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

3. 调用接口

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

效果:

五、Hystrix

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

1. 依赖

dept-api模块导入hystrix依赖:

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

2. yml配置

添加hystrix相关配置:

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注解:

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableHystrix
public class DeptApiApplication {

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

}

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

@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接口,需要实现一个该接口的类作为降级回调处理类:

@Component
public class DeptFeignFallCallback implements DeptFeignClient {
    @Override
    public String insertDept(WDept dept) {
        return "服务发生错误";
    }
}

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

@FeignClient(value = "aruba-dept", fallback = DeptFeignFallCallback.class)
public interface DeptFeignClient {

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

}

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

六、Hystrix仪表盘

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

新建模块:

1. 导入依赖

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

    <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配置

spring:
  application:
    name: aruba-hystrix-client

server:
  port: 9000

hystrix:
  dashboard:
    proxy-stream-allow-list: "localhost"

3. @EnableHystrixDashboard

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

@SpringBootApplication
@EnableHystrixDashboard
public class HystrixClientApplication {

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

}

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

4. 模块中配置

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

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

@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客户端依赖:

    <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

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注解在启动类上:

@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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容