欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

新手必备系列之从零开始搭建springcloud脚手架

程序员文章站 2022-07-12 20:19:27
...

基本微服务架构
新手必备系列之从零开始搭建springcloud脚手架
1、创建项目
新手必备系列之从零开始搭建springcloud脚手架
groupId: 项目名称
artifactId: 工程名称
project: 新建项目名称
创建项目后:pom.xml包含创建的
新手必备系列之从零开始搭建springcloud脚手架
在pom.xml文件中配置:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.5.RELEASE</version>
</parent>

<properties>
    <java.version>1.8</java.version>
    <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>

<dependencies>

<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>${spring-cloud.version}</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>

注意:配置在dependencyManagement里的dependency需要制定其版本,而配置在dependencies中的不需要, 所有生命在dependencies里的依赖都会自动引入,并默认被所有的子项目继承。 dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。

2、服务注册中心(Eureka(老版本,demo使用的)、Consul(实际生产)、ZK 常用),作用:服务的发现与治理,负载均衡(自带)有类似负载均衡的算法,对于服务集群配置,该服务能知道调用哪些服务才能平均分配请求的压力;并且,如果哪个服务崩溃,该服务还能快速知道并不再向崩溃的服务发送请求,步骤:
(1)在根目录下面创建一个新的模块(module),命名为demo-eureka,创建启动类 EurekaApplication

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

注意: 创建文件时若不能新建class文件,则设置Sources Root: 通过这个类指定一个文件夹,你告诉IntelliJ IDEA,这个文件夹及其子文件夹中包含的源代码,可以编译为构建过程的一部分。

(2)在resources文件夹下创建 application.yml文件,配置:

spring:
    application:
        # 应用名称
        name: demo-eureka
server:
    port: 8080

eureka:
    instance:
        # Eureka注册中心HOST主机地址,可以采用:1.直接配置IP;2.配置本地域名并修改本地hosts文件
        hostname: localhost
    client:
        # 是否将自己注册到注册中心。因为项目中只有一个注册中心就是自己,所以无需再注册
        register-with-eureka: false
        # 是否从远程拉取其他注册中心,因为注册中心只有自己所以不需要。如果注册中心有多个,可以相互暴露,相互拉取
        fetch-registry: false
        service-url:
            # 该注册中心连接地址
            defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

注意: yml文件的格式一定要配置对,不对是识别不了配置的

(3)在pom.xml配置在dependencies:

<!--增加eureka-server的依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

(4)配置完成,启动服务,访问localhost:8080,显示即为配置成功
新手必备系列之从零开始搭建springcloud脚手架
3、搭建生产者服务,在根目录下创建模块demo-admin
(1)在pom.xml添加依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
</dependencies>

(2)创建启动类 AdminApplication,只要加了注解@EnableEurekaClient 即表示该服务为Eureka的一个服务生产者

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

(3)在resources文件夹下创建 application.yml文件,配置:

server:
    port: 9001
spring:
    application:
        name: demo-admin
eureka:
    client:
        service-url:
            # Eureka注册中心连接地址
            # 如果注册中心地址配置的域名,这里使用 http://域名/eureka/ 格式
            defaultZone: http://localhost:8080/eureka/

(4)配置完成,启动启动类,观察服务是否已经在Eureka注册上
(5)在 /controller 下创建测试方法(AdminController)

@RestController
public class AdminController {

    @GetMapping("/hello/{name}")
    public String hello(@PathVariable String name) {
        return "hello" + name + "this is demo-admin";
    }
}

(6)重启服务,访问: http://localhost:9001/hello/zhangsan
新手必备系列之从零开始搭建springcloud脚手架
4、demo-admin暴露了Rest接口,那么其他服务想要调用生产者服务的接口,即消费者,在这里我们使用Feign实现,在根目录下面创建demo-auth文件夹
(1) 在pom.xml 文件下配置依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    <--开启Feign-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
</dependencies>

(2)创建服务的启动类(AuthApplication)

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

注意: 添加@EnableDiscoveryClient注解声明该服务为Eureka中服务消费方;添加@EnableFeignClients开启Feign声明式服务间通信(配合@FeignClient注解使用)

(3)在resources文件夹下创建 application.yml文件,配置:

server:
    port: 9002
spring:
    application:
        name: demo-auth
eureka:
    client:
        service-url:
            # Eureka注册中心连接地址
            # 如果注册中心地址配置的域名,这里使用 http://域名/eureka/ 格式
            defaultZone: http://localhost:8080/eureka/

(4)创建一个demo的Controller:

@RestController
public class AuthController {
    @GetMapping("/hello/{name}")
        public String hello(@PathVariable String name) {
            return "hello " + name + ", this is demo-auth";
        }
}

(5) 访问localhost:9002/hello/zhangsan,正常访问则搭建完成
(6) 在demo-auth下创建feign或者service 文件夹,并创建AuthFeignService接口:

@FeignClient(value = "demo-admin")
public interface AuthFeignService {

    /**
    * 这里暴露一个Feign接口地址,其中`@GetMapping`中的地址一定对应了`demo-admin`服务中某个Controller中的请求地址(如果`demo-admin`服务中没有这个接口地址就会404)
    * 如果其他地方调用了AuthFeignService接口的hello方法,FeignClient将类似通过转发的方式去请求调用`demo-admin`服务中符合的接口地址的方法
    * 如果请求传递了参数,需要加@RequestParam注解标识。如果URL中有动态参数,要添加@PathVariable注解
    *
    * @param name
    * @return
    */
    @GetMapping("/hello/{name}")
    public String hello(@PathVariable(name = "name") String name);
}

注意:

  • 如上,这是一个供Feign调用的接口。Feign实现服务端通信有几个基本条件:
  • 该服务添加了spring-cloud-starter-openfeign依赖
  • 该服务的启动器类上添加了@EnableFeignClients注解
  • 该服务提供了一个接口类,并在该接口上添加了@FeignClient注解,并且@FeignClient注解中value属性值必须等于一个已在Eureka中注册的服务名称。
  • 在该接口上添加一个调用的方法,该方法必须和被调用服务方Controller中的方法格式相同(除了没有方法具体实现,方法的返回值、参数列表都要相同),并且需要和被调用方Controller接口一样在方法上添加@RequestMapping注解,指明被调用方接口的具体URL。

(7)在AuthController中添加一个接口:

	// 导入需要的接口 
    @Autowired
    private AuthFeignService authFeignService;
    /**
    * 模拟Feign远程调用,这里暴露一个请求接口`/feignHello`
    * 这个请求接口将调用`AuthFeignService`(Feign接口)
    * Feign接口(`AuthFeignService`接口)将会通过`@FeignClient(value = "demo-admin")`在Eureka注册中心寻找`demo-admin`模块
    * Feign接口类似Controller的Rest接口,也暴露一个地址,这个地址对应`demo-admin`模块的一个Controller接口地址
    *
    * @param name
    * @return
    */
    @GetMapping("/feignHello/{name}")
    public String feignHello(@PathVariable String name) {
        return authFeignService.hello(name);
    }

注意: 如果authFeignService导入后显示红色,则只需要根据提示取消掉标红,不影响运行的报错

5、配置Hystrix熔断机制
原理: Hystrix主要用于在多个服务间存在通信,而通信的某一方因为压力过大、响应时间过长而导致不可用,Hystrix就会阻止Eureka再给该服务分配请求,从而保证服务的高可用
使用: Hystrix主要配置在存在服务间通信的地方。因为我们使用的Feign,Feign正是用来实现服务间通信的。所以我们只需要在自己创建的Feign接口中配置熔断器即可。因为Feign已经内置了Hystrix,我们只需要配置启用hystrix即可
(1)在demo-auth 的yml文件中添加配置

feign:
    hystrix:
        # 开启Feign的Hystrix熔断器支持
        enabled: true
(2)在demo下面创建文件夹fallback,创建 AuthFeignServiceFallbackImpl 类
@Component
public class AuthFeignServiceFallbackImpl implements AuthFeignService {
    @Override
    public String hello(String name) {
        return "hello " + name + ", this is demo-auth, but request error";
    }
}

(2)在demo下面创建文件夹fallback,创建 AuthFeignServiceFallbackImpl 类

@Component
public class AuthFeignServiceFallbackImpl implements AuthFeignService {
    @Override
    public String hello(String name) {
        return "hello " + name + ", this is demo-auth, but request error";
    }
}

这个类实现了AuthFeignService远程调用接口,作用就是当AuthFeignService调用的服务不可用时,Hystrix直接执行这个实现类中的方法,而不再执行AuthFeignService中的远程调用方法。
(3)重启demo-auth服务,关闭demo-admin,观察访问结果,返回错误即正常。
!注意:使用熔断的时候,需要在feign接口处配置熔断fallback指定的类,举例:
新手必备系列之从零开始搭建springcloud脚手架
6、配置Hystrix-DashBoard熔断监控
使用: 通过hystrix-dashboard工具实现对熔断器Hystrix的实时监控。因为我们在demo-auth服务中使用了Feign远程调用,并且使用了Hystrix熔断器,所以我们只需要在demo-auth服务中配置熔断监控
(1)引入依赖

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

(2)在demo-auth启动类上添加 @EnableHystrixDashboard注解
(3)创建config文件夹,创建类 HystrixDashboardConfig:

@Configuration
public class HystrixDashboardConfig {
    @Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }
}

注意: 在SpringBoot2.x之前的版本中,SpringBoot默认提供了一个接口地址用于访问Hystrix熔断器。但是在SpringBoot2版本中需要手动提供一个Hystrix监控地址。上面的配置就是将Servlet ( HystrixMetricsStreamServlet )注入到Web容器中,类似web.xml中的和

(4)重启demo-auth服务,访问 localhost:9002/hystrix,名称输入 localhost:9002/hystrix.stream,刷新时间可以自己定义,默认两秒,关闭demo-admin服务后,再访问 http://localhost:9002/feignHello/tycoding,进入熔断机制,则可实时监控熔断的情况。
新手必备系列之从零开始搭建springcloud脚手架
7、配置网关服务demo-gateway,创建demo-gateway文件夹(使用zuul)
(1)在pom文件里引入依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    </dependency>
</dependencies>

(2)创建启动类 GatewayApplication:

// 此注解开启Zuul网关的支持
@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

(3)创建配置文件 application.yml:

server:
    port: 9003

spring:
    application:
        name: demo-gateway

eureka:
    client:
        service-url:
        # Eureka注册中心连接地址
        # 如果注册中心地址配置的域名,这里使用 http://域名/eureka/ 格式
        defaultZone: http://localhost:8080/eureka/

zuul:
    routes:
        # 路由名称,随意
        demo-admin:
            # 路由地址
            path: /api/admin/**
            # 该路由地址对应的服务名称
            serviceId: demo-admin
        demo-auth:
            path: /api/auth/**
            serviceId: demo-auth

注意: zuul.routers下可以配置多个路由表,每个路由表中对应了具体的请求路径前缀path,这个请求路径最终会被Zuul路由到某个服务中,所需需要对应配置一个serviceId对应某个服务的名称。这样就实现了请求/api/admin/xx接口Zuul就会将请求转发到demo-admin服务、请求/api/auth/xx接口Zuul就会将请求转发到demo-auth服务

(4)通过网关访问各模块服务,正常访问则搭建完成
!!注意: 如果Zuul路由服务失败不应该给客户端返回404、500等错误,因为客户端直接请求的是demo-zuul路由网关服务,而请求demo-zuul服务是成功的,demo-zuul将请求转发到其他服务属于服务器内部错误,这中错误不应该暴露给客户端。除非是demo-zuul路由网关服务自己挂了,才会返回给客户端404、500等错误
(5)服务通过网关是需要拦截请求是不是合法请求(比如token的验证),我们在此也模拟一下网关 的验证,创建filter 文件夹,创建类LoginFilter

@Component
public class LoginFilter extends ZuulFilter {
  private Logger logger = LoggerFactory.getLogger(this.getClass());

  /**
  * 过滤器类型:
  * pre: 路由前
  * routing: 路由时
  * post: 路由后
  * error: 路由发生错误时
  *
  * @return
  */
  @Override
  public String filterType() {
      return "pre";
  }

  /**
  * 过滤的顺序
  *
  * @return
  */
  @Override
  public int filterOrder() {
      return 0;
  }

  /**
  * 是否需要过滤
  *
  * @return
  */
  @Override
  public boolean shouldFilter() {
      return true;
  }

  /**
  * 过滤器的具体业务逻辑
  *
  * @return
  * @throws ZuulException
  */
  @Override
  public Object run() throws ZuulException {
      RequestContext currentContext = RequestContext.getCurrentContext();
      HttpServletRequest request = currentContext.getRequest();
      logger.info("{} >>> {}", request.getMethod(), request.getRequestURI().toString());
      String token = request.getParameter("token");
      if (token == null) {
          logger.error("Error! Request Token is Empty");
          currentContext.setSendZuulResponse(false);
          currentContext.setResponseStatusCode(401);
          try {
              currentContext.getResponse().getWriter().write("Request token is empty");
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
      return null;
  }
}

(6)重启demo-gateway服务,访问 localhost:9003/api/admin/hello/zhangsan,不能正常访问, localhost:9003/api/admin/hello/zhangsan?token=123可正常访问则搭建完成。
8、搭建配置中心config服务(一般系统利用工具配置(apllo,nacos),这里测试使用模块使用)
(1)在根目录下创建demo-config模块
(2)添加依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
    </dependency>
</dependencies>

(3)添加配置文件

server:
    port: 8888

spring:
    application:
        name: demo-config

    # 获取本地配置文件,本身支持:本地储存、git远程、SVN
    profiles:
        active: native

    cloud:
        config:
            server:
            # 获取本地配置文件的位置
                native:
                    search-locations: classpath:config/
eureka:
    client:
        service-url:
            # Eureka注册中心连接地址
            # 如果注册中心地址配置的域名,这里使用 http://域名/eureka/ 格式
            defaultZone: http://localhost:8080/eureka/

注意:由于项目为demo,获取的配置都在本地配置,正式环境可从远程仓库获取:

# 远程读取
# cloud:
# config:
# label: master # 配置仓库的分支
# server:
# git:
# uri: https://github.com/xx/spring-cloud-config # 配置Git仓库地址,如果用Github需要加.git,如果用Gitlab则不需要
# search-paths: respo # 配置仓库路径
# username: # 访问Git仓库的账号
# password: # 访问Git仓库的密码

(3)创建服务的启动类 ConfigApplication

// 开启配置文件服务支持
@EnableConfigServer
@EnableEurekaClient
@SpringBootApplication
public class ConfigApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigApplication.class, args);
    }
}

(4)将demo-gateway服务的配置文件copy到demo-config服务的/resources/config文件夹下,启动demo-config服务,访问 localhost:8888/config/application-zuul-dev.yml:
新手必备系列之从零开始搭建springcloud脚手架
成功访问则说明配置文件中的内容已经通过外部接口访问,即搭建成功。
(5)client端的搭建,在根目录下的pom文件中添加依赖:

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

(6)在根目录的resource文件夹下创建application.yml文件,写入配置文件:

spring:
    profiles:
        active: native
    cloud:
        config:
            uri: http://locahost:8888
            name: application-zuul
            profile: dev
            # label:

参数说明:

  • spring.cloud.config.uri: 配置服务中心的网址
  • spring.cloud.config.name: 配置文件的前缀名
  • spring.cloud.config.label: 配置仓库的分支。如果是本地读取,可不配置
  • spring.cloud.config.profile: 配置文件的环境标识
  • dev: 开发环境
  • test: 测试环境
  • prod: 生产环境

重启demo-gateway服务,删除配置,用配置中心配置,访问成功即可。

!!注意: 配置服务器的默认端口是 8888, 如果修改了默认端口,则客户端项目中就不能在application.yml或application.properties中配置spring.cloud.config.uri,必须在bootstrap.yml或是bootstrap.properties中配置,原因是bootstrap开头的配置文件会优先加载和配置。

9、开启 Spring Boot Profile:

如果项目中分别部署了开发、测试、生产环境的配置文件,但如果切换不同的开发环境就可能要修改对应配置文件中的配置 ( spring.cloud.config.profile的参数值 ),而使用Spring Boot Profile就仅需要在启动项目时指定加载的文件,Spring就会自动加载该配置文件来启动项目。举个栗子:java -jar demo-auth-1.0.0-SNAPSHOT.jar --spring.profiles.active=prod其中–spring.prodiles.active=prod就会自动加载application-auth-prod.yml配置文件

10、搭建zipkin链路追踪服务(文章中的服务搭建已过时,具体搭建参考官网或者 https://www.cnblogs.com/danghuijian/p/9482279.html)
11、搭建SpringBootAdmin服务
(1)Server端:创建demo-boot-admin模块
(2)在pom.xml文件夹下添加依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.jolokia</groupId>
        <artifactId>jolokia-core</artifactId>
    </dependency>
    <dependency>
        <groupId>de.codecentric</groupId>
        <artifactId>spring-boot-admin-starter-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-zipkin</artifactId>
    </dependency>
</dependencies>

(3)在父节点pom文件下添加依赖

<properties>
    <spring-boot-admin.version>2.1.5</spring-boot-admin.version>
</properties>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-server</artifactId>
            <version>${spring-boot-admin.version}</version>
        </dependency>
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-client</artifactId>
            <version>${spring-boot-admin.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

注意:在dependencyManagement下添加依赖,需要制定version的版本
(4)添加配置文件:application.yml

server:
    port: 9004

spring:
    application:
        name: demo-boot-admin
    zipkin:
        base-url: http://localhost:9411

eureka:
    client:
        service-url:
            # Eureka注册中心连接地址
            # 如果注册中心地址配置的域名,这里使用 http://域名/eureka/ 格式
            defaultZone: http://localhost:8080/eureka/

management:
    endpoint:
        health:
            show-details: always
    endpoints:
        web:
            exposure:
                include: health,info

(5)创建该服务的启动类: BootAdminApplication.java

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-client</artifactId>
</dependency>
修改application.yml文件,添加配置:
spring:
    boot:
        admin:
            client:
                url: http://localhost:9004

(7) 按照demo-eureka、demo-config、demo-zipkin、demo-boot-admin、demo-admin、demo-auth、demo-gateway 顺序依次启动服务。

访问localhost:9004成功访问SpringBootAdmin界面则搭建成功
12、邮箱报警设置
(1)在demo-boot-admin模块pom下新增依赖:

<!--邮箱报警-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

(2)在application.yml文件spring下新增配置:

mail:
    host: smtp.163.com
    username: ********
    password: ********(密码)
    boot:
        admin:
            notify:
                mail:
                    to: *********(到达邮箱)
                    from: **********(发出邮箱)

注意:如果无法使用,观察自己的163邮箱是否开始SMTP服务,并开始客户端授权密码
新手必备系列之从零开始搭建springcloud脚手架
如果未打开,打开即可正常使用,亲测可用!

好了,到这里搭建过程已经结束了,整个demo应该还是很全面的,大家有补充的可以留言,有错误的也欢迎大家指正~

相关标签: java 新手必备