SpringCloud微服务实战搭建Consul+Feign/Ribbon+Config+Zuul+Hystrix+Turbine+docker项目发布

由于用户量上升,现需求项目升级,后台架构要求升级至微服务,综合后决定用spring全家桶!

接下来为大家搭建一个微服务框架,后期可以自己进行扩展。会提供一个小案例: 服务提供者和服务消费者 ,消费者会调用提供者的服务,新建的项目都是用springboot,推荐使用coding地址下载,因为可以切换分支,后期可以及时更新。

本项目coding地址https://git.coding.net/yuhaoqiang/SpringCloud.git

Eureka/Consul/Zookeeper:服务发现
Hystrix:断路器
Zuul:智能路由
Ribbon/Feign:客户端负载均衡 (Feign用的更多)
Turbine&hystrix-dashboard:集群监控
Springcloud-config:远程获取配置文

 一、搭建consul服务

springclound-consul作为服务发现的核心,第一个搭建,后面的服务都要注册到consul上,意思是告诉consul自己的服务地址是啥。当然还可以用zookeeper或者eureka。

下载安装consul:去下载

    根据自己的版本下载对应的安装包 以win64为列,下载解压后会得到一个.exe执行。cmd进入exe同级目录,输入consul agent -dev 就可以运行了, 然后consul的默认端口是8500,直接在浏览器打开http://localhost:8500,就可以看到控制台了

 二、搭建config-server服务sc-config-server

注:之前采坑,由于依赖版本有问题导致报错,一直找不到问题,经过一天的努力,才发现问题。所以在这里推荐大家使用spring官方https://start.spring.io/构建项目,或者用idea进行构建。

这里我们用idea构建如下:下一步即可

 1.修改pom文件,加入以下依赖:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>

2.修改application.yml文件

server:
    port: 8800
spring:
    security:
        basic:
            enabled: true
        user:
            name: root
            password: kaidianapp
    application:
        name: sc-config-server
    cloud:
        config:
            server:
                git:
                    uri: https://git.coding.net/yuhaoqiang/spring-cloud-demo
                    searchPaths: '{application}'
        consul:
            host: localhost
            port: 8500
            discovery:
                instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
                prefer-ip-address: true

 3.修改启动类

@EnableConfigServer
@EnableDiscoveryClient
@SpringBootApplication
public class ScConfigServerApplication {

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

}

然后运行启动springboot项目,等启动成功后访问consul的页面,会发现sc-config-server已经注册到上面了,如果启动报错,请检查错误信息。

三、搭建服务提供者服务sc-provider 

还是熟悉的配方:新建一个springboot项目...

注意 : 这里除了application.xml,还需要一个bootstrap.yml, 因为bootstrap.yml得加载顺序是在application.xml前边,服务注册和config配置必须放到bootstrap.yml 

application.yml 放在了远程仓库:远程配置文件

 

  1. 修改pom文件
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-consul-discovery</artifactId>
                <version>2.1.1.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
                <version>2.1.1.RELEASE</version>
            </dependency>
            
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-webflux</artifactId>
                <version>2.1.1.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
                <version>2.1.1.RELEASE</version>
            </dependency>

    2. 编写配置文件bootstrap.yml               application.yml在远程coding仓库
     

    spring:
      application:
        name: sc-provider
      cloud:
        consul:
          host: localhost
          port: 8500
          discovery:
          instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
          prefer-ip-address: true
        config:
          discovery:
            enabled: true
            service-id: sc-config-server
          fail-fast: true
          username: root
          password: kaidianapp
          profile: pro

    3.编写主类代码
     

    @EnableDiscoveryClient
    @SpringBootApplication
    public class ScProviderApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(ScProviderApplication.class, args);
        }
    
    }

    4.编写controller进行测试
     

    @RestController
    @RequestMapping("test")
    public class IndexController {
    
        //返回一个实体
        @GetMapping("{msg}")
        public Mono<String> sayHelloWorld(@PathVariable("msg") String msg) {
            System.out.println("come on " + msg);
            return Mono.just("sc-provider receive : " +msg);
        }
        //返回一个列表
        @GetMapping("list")
        public Flux<Integer> list() {
            List<Integer> list = new ArrayList<>();
            list.add(13);
            list.add(55);
            list.add(2);
            list.add(555);
            Flux<Integer> userFlux = Flux.fromIterable(list);
            return userFlux;
        }
    
        @GetMapping("actuator/health")
        public Mono<String> actuatorHealth() {
            return Mono.just("actuator/health : ok ");
        }
    }

    启动项目进行测试。

 四、搭建消费者服务sc-consumer

消费者要访问服务提供者的服务,这里用的是通过RestTemplate/feign请求resetful接口,使用ribbon做客户端负载均衡,hystrix做错误处理,feign和ribbon二选一,案例中ribbon和feign都有,也可以都用。

这里演示feign用法,ribbon用法请参考燕大佬博客https://blog.csdn.net/yp090416/article/details/81587110
还是熟悉的配方,熟悉的味道,新建springboot项目,添加项目依赖。

1.修改pom文件 加入以下依赖

        dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

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

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

2.修改bootstrap.yml文件

spring:
  application:
    name: sc-consumer
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
      instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
      ip-address: true
    config:
      discovery:
        enabled: true
        service-id: sc-config-server
      fail-fast: true
      username: root
      password: kaidianapp
      profile: con
#新版配置,否则后面dashboard无法找到hystrix.stream
management:
  endpoints:
    web:
      exposure:
        include: '*'
ribbon:
  eureka:
    enabled: false

3.编写主类代码

@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication
@EnableHystrix
@EnableCircuitBreaker
public class ScConsumerApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(ScConsumerApplication.class, args);
    }

}

application.yml 文件增加以下配置:

feign:
  hystrix:
    enabled: true
ribbon:
  ReadTimeout:  60000
  ConnectTimeout:  60000
hystrix:
  command:
    default:
      execution:
        isolation:
          strategy: SEMAPHORE
          thread:
            timeoutInMilliseconds: 60000

准备好一大堆代码- -

3.1 feign配置:

@Configuration
public class MFeignConfig {

    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }


}

3.2 feign 接口

@FeignClient(name = "sc-provider",fallback = MFeignClientFallback.class,configuration = MFeignConfig.class)
public interface MFeignClient {
    // 这是被请求微服务的地址,也就是provider的地址
    @GetMapping(value = "/test/{msg}")
    String sayHelloWorld(@PathVariable("msg") String msg);

    @GetMapping(value = "/test/list")
    List<Integer> list();

    @GetMapping(value = "/test/list")
    Integer[] array();
}

3.3 feign  断路器回调方法

@Component
public class MFeignClientFallback implements MFeignClient {

    @Override
    public String sayHelloWorld(String msg) {
        return "请求失败:";
    }

    @Override
    public List<Integer> list() {
        return new ArrayList<>();
    }

    @Override
    public Integer[] array() {
        return new Integer[0];
    }
}

3.4 可以用工厂代替,并且打印错误异常信息,方便排查问题(可选择)

@Component
public class MFeignClientFallbackFactory implements FallbackFactory<MFeignClient> {

    @Autowired
    private MFeignClientFallback mFeignClientFallback;

    @Override
    public MFeignClient create(Throwable throwable) {
        throwable.printStackTrace();
        return mFeignClientFallback;
    }
}

 3.5 feign controller编写

@RestController
public class FeignController {

    @Autowired
    private MFeignClient feignClient;



    @GetMapping("/feign/{wd}")
    public Mono<String> sayHelloWorld(@PathVariable("wd") String parm) {
        String result = feignClient.sayHelloWorld(parm);
        return Mono.just(result);
    }

    @GetMapping("/feigns/list")
    public Flux<Integer> list() {
        List<Integer> list = feignClient.list();
        Flux<Integer> userFlux = Flux.fromIterable(list);
        return userFlux;
    }

    @GetMapping("/feigns/array")
    public Flux<Integer> array() {
        Integer[] arrays = feignClient.array();
        Flux<Integer> userFlux = Flux.fromArray(arrays);
        return userFlux;
    }
}

3.6 启动项目 进行测试

 

这里我们尝试停止sc-provider提供者项目,测试是否进入断路器方法,也可以修改sc-provider项目让方法抛出异常.

停止后:

 

并且可以看到控制到打印的错误日志:

 五、用zuul做路由转发和负载均衡

这些微服务都是隐藏在后端的,用户是看不到,或者不是直接接触,可以用nginx或者zuul进行路由转发和负载均衡,zuul负载均衡默认用的是ribbon。

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-consul-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

2.修改bootstrap.yml

spring:
  application:
    name: sc-zuul
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
      instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
      ip-address: true
    config:
      discovery:
        enabled: true
        service-id: sc-config-server
      fail-fast: true
      username: root
      password: kaidianapp
      profile: zuul

 3.修改启动类

@EnableDiscoveryClient
@EnableZuulProxy
@RefreshScope
@SpringBootApplication
public class ScZuulApplication {

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

 启动springboot项目,访问consul

这时候,我们就要通过zuul访问微服务了,而不是直接去访问微服务。
应该访问地址http://localhost:8400/sc-consumer/feign/list,这块你要换成你的zuul地址。

但是有些人就会说,这样以后用户请求会不会太长,比较反感,所以可以通过配置进行修改访问地址。

修改application.yml文件

server:
  port: 8700
zuul:
  routes:
    sc-consumer: /consumer/**
    sc-provider: /provider/**
ribbon:
  ReadTimeout: 3000
  ConnectTimeout: 3000
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 80000

重启项目

六、用hystrix-turbine-dashboard 做集群监控

项目在生产环境中,每个服务的访问量都不通,有些服务的访问量比较大,有时候有些服务挂了,不能继续服务,需要重启的时候,我们并不知道,所以这时候就需要使用hystrix-turbine-dashboard做一个监控,监控所有的微服务,可以看到这个接口实时访问量,和健康状况。
新建一个springboot项目,老套路,加入如下依赖

1.修改pom文件

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-turbine</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>com.netflix.eureka</groupId>
                    <artifactId>eureka-client</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

 2.修改application.yml配置文件 注意不是bootstrap.yml

server:
  port: 8900
turbine:
  aggregator:
    clusterConfig: default
  appConfig: sc-consumer
  clusterNameExpression: "'default'"
spring:
  application:
    name: sc-monitor
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
      instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
      ip-address: true

 3.修改主类

@EnableDiscoveryClient
@EnableTurbine
@EnableHystrixDashboard
@SpringBootApplication
public class ScMonitorApplication {

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

}

4.访问测试

这块的端口是8900,访问地址http://localhost:8900/hystrix,看到的是下面的页面。

è¿éåå¾çæè¿°

 

以上就是大致架构,后面也可以自行加入组件.

下面我们将项目用docker打包发布到服务器上

七. 下载consul 运行在服务器上

1.服务器启动consul

我这里用的centos7 下载Linux版本后 用ftp上传到 服务器并解压

这里使用之前的命令外部会访问不到服务器,如果项目要注册上去填写的服务器ip也会连不到,所以我们要改下命令。

运行服务器启动命令 ./consul agent -dev -client 0.0.0.0 -ui

2.打包项目并上传服务器

idea 用maven 插件 直接打包:

3. 使用Dockerfile构建自己的Docker镜像

保持Dockerfile文件和jar文件放在同一目录

编写Dockerfile文件,如图:

使用 docker build -t config-server .      其中,-t指定镜像名字,命令最后的点(.)表示Dockerfile文件所在路径

执行以下命令,即可使用该镜像启动一个 Docker容器,后台运行可以加 -d

docker run -p 8800:8800 config-server

 查看一下consul 看是否注册成功。

 八.打包提供者(sc-provider)服务发布

    1.打包发布流程请参考上述远程配置服务

    2.这里讲个坑,就是消费端发布后consul Service Checks 一直检查不通过,导致服务无法访问。

       我们在这里自己更改checks接口,完成验证。

       2.1 IndexController 里面增加接口

    @GetMapping("actuator/health")
    public Mono<String> actuatorHealth() {
        return Mono.just("actuator/health : ok ");
    }

      2.2 修改bootstrap.yml

       2.3 修改完成后 打包上传并用docker构建镜像,然后发布验证即可。

 

      2.4 其他服务流程以此类推

 

 

至此微服务实战到发布就完成了!!! 

如果有问题,请在参考https://blog.csdn.net/yp090416/article/details/81587110或者在下方评论,或者加群讨论 200909980

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值