手摸手学会Spring Cloud Alibaba微服务构建示例,从0到1

前言

PS:一切脱离业务的架构,都是耍流氓~

为何需要微服务

当传统的单体应用无法满足日益见长的业务需求时(例如:并发,性能,可用性),就需要开始考虑微服务的架构。

总的来说,现有的微服务体系,包含有许多的模块,这些模块需要互相搭配着使用,才能展现出微服务架构的魅力于优势。

Spring Cloud Alibaba这一套,官方文档:https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md

一些准备

nacos启动

在微服务架构中,nacos为我们提供了服务发现与注册,统一配置的管理等一些功能。

nacos下载地址:https://nacos.io/zh-cn/docs/quick-start.html,为了友好体验本实例,避免各组件间因版本不一致,导致冲突,我们下载2.0.3版本。

默认配置情况下,nacos服务端口是8848,地址与端口后面的微服务里边会用到。

sentinel启动

在微服务架构中,sentinel为我们提供了服务的降级、熔断、限流等功能,可以很好的保证微服务系统中,核心接口的高可用性。

下载地址:https://github.com/alibaba/Sentinel/releases/tag/1.8.2

启动命令:nohup java -Dserver.port=9090  -Dcsp.sentinel.dashboard.server=localhost:9090 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.2.jar >> sentinel.log 2>&1 &

PS:我们修改了sentinel服务的端口为9090

工程结构

工程pom.xml配置

ParentPro父级工程pom.xml文件配置

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

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

  <groupId>com.wslio</groupId>
  <artifactId>ParentPro</artifactId>
  <version>1.0</version>

  <!-- 父级项目中,此处配置为pom -->
  <packaging>pom</packaging>

  <properties>
    <java.version>1.8</java.version>
    <spring-boot-version>2.3.2.RELEASE</spring-boot-version>
    <spring-cloud-version>2.2.6.RELEASE</spring-cloud-version>
    <spring-cloud-dependencies>2.2.6.RELEASE</spring-cloud-dependencies>
    <spring-cloud-nacos-version>2.2.6.RELEASE</spring-cloud-nacos-version>
    <spring-cloud-openfeign-version>2.2.6.RELEASE</spring-cloud-openfeign-version>
    <spring-cloud-gateway-version>2.2.6.RELEASE</spring-cloud-gateway-version>
    <ali-csp-version>1.8.1</ali-csp-version>
  </properties>

  <!-- 这里放子模块 -->
  <modules>
    <module>Child-Common</module>
    <module>Child-Provider</module>
    <module>Child-Consumer</module>
    <module>Child-Gateway</module>
  </modules>

  <!-- 放共有的依赖 -->
  <dependencies>
    <!-- 所有的子工程都会用nacos来注册服务 -->
    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>

    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.20</version>
      <scope>provided</scope>
    </dependency>

  </dependencies>

  <!-- 统一依赖版本管理 -->
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-dependencies</artifactId>
        <version>${spring-cloud-dependencies}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>

      <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        <version>${spring-cloud-nacos-version}</version>
      </dependency>

      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
        <version>${spring-cloud-openfeign-version}</version>
      </dependency>

      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
        <version>${spring-cloud-gateway-version}</version>
      </dependency>

      <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-core</artifactId>
        <version>${ali-csp-version}</version>
      </dependency>
      <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-transport-simple-http</artifactId>
        <version>${ali-csp-version}</version>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <skip>true</skip>
        </configuration>
        <executions>
          <execution>
            <goals>
              <goal>repackage</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>
View Code

 

Child-Common子工程pom.xml文件配置

存放一些通用的方法、类在此。

<?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>
    <parent>
        <groupId>com.wslio</groupId>
        <artifactId>ParentPro</artifactId>
        <version>1.0</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <groupId>com.wslio</groupId>
    <artifactId>Child-Common</artifactId>
    <version>1.0</version>

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <!--被依赖的公共模块必须加上这个,打包之后启动,选择后面带EXE的启动,依赖该模块的其他模块就不会因为找不到依赖而打包出错-->
                    <classifier>exe</classifier>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
View Code

Child-Consumer子工程pom.xml文件配置

服务消费者,消费Provider工程的一些api接口。

<?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>
    <parent>
        <groupId>com.wslio</groupId>
        <artifactId>ParentPro</artifactId>
        <version>1.0</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <groupId>com.wslio</groupId>
    <artifactId>Child-Consumer</artifactId>
    <version>1.0</version>

    <dependencies>
        <dependency>
            <groupId>com.wslio</groupId>
            <artifactId>Child-Common</artifactId>
            <version>1.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-core</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-transport-simple-http</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-web-servlet</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>
</project>
View Code

Child-Gateway子工程pom.xml文件配置

在微服务架构中,gateway为我们的微服务提供了统一的入口,避免了微服务的调用难题,在gateway这层,还适合做一些通用的功能,比如微服务鉴权,操作日志等。

<?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>
    <parent>
        <groupId>com.wslio</groupId>
        <artifactId>ParentPro</artifactId>
        <version>1.0</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <groupId>com.wslio</groupId>
    <artifactId>Child-Gateway</artifactId>
    <version>1.0</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
    </dependencies>
</project>
View Code

Child-Provider子工程pom.xml文件配置

服务提供方,提供一些api接口服务,给其他工程调用的。

<?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>
    <parent>
        <groupId>com.wslio</groupId>
        <artifactId>ParentPro</artifactId>
        <version>1.0</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <groupId>com.wslio</groupId>
    <artifactId>Child-Provider</artifactId>
    <version>1.0</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>
View Code

 工程application.yml配置

ParentPro工程

不用配置application.yml

Child-Common子工程

server:
  port: 9003
spring:
  application:
    name: child-common
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.50.16:8848
View Code

Child-Consumer子工程

server:
  port: 9012
spring:
  application:
    name: child-consumer
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.50.16:8848
    sentinel:
      transport:
        port: 8719
        dashboard: 192.168.50.16:9090
  main:
    allow-bean-definition-overriding: true
feign:
  sentinel:
    enabled: true
View Code

Child-Gateway子工程

server:
  port: 9004
spring:
  application:
    name: child-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.50.16:8848
    gateway:
      routes:
        - id: child-consumer
          uri: lb://child-consumer
          predicates:
            - Path=/consumer/*
View Code

Child-Provider子工程

server:
  port: 9006
spring:
  application:
    name: child-provider
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.50.16:8848
View Code

工程java源代码

ParentPro工程

该工程没有源代码

Child-Common子工程

目录结构

Child-Consumer子工程

目录结构

源代码:

package com.wslio.childconsumer.controller;

import com.wslio.childconsumer.service.ProviderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;

@RestController
@Slf4j
public class PlayerController {
    @Resource
    private ProviderService providerService;

    @RequestMapping("/consumer/musicplay")
    public String musicplay(@RequestParam String musicPath){
        log.info("musicplay 调用!");
        return providerService.musicPlay(musicPath);
    }

    @RequestMapping("/consumer/videoplay")
    public String videoplay(@RequestParam String videoPath){
        return providerService.videoPlay(videoPath);
    }
}
PlayerController.java
package com.wslio.childconsumer.service;

import com.wslio.childconsumer.service.impl.MusicServiceFallBack;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Component
@FeignClient(value = "child-provider", fallback = MusicServiceFallBack.class)
public interface ProviderService {

    @RequestMapping("/provider/musicplay")
    String musicPlay(@RequestParam String musicPath);

    @RequestMapping("/provider/videoplay")
    String videoPlay(@RequestParam String videoPath);
}
ProviderService.java
package com.wslio.childconsumer.service.impl;

import com.wslio.childconsumer.service.ProviderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class MusicServiceFallBack implements ProviderService {
    @Override
    public String musicPlay(String musicPath) {
        log.error("musicPlay 调用失败! 服务降级!");
        return "musicPlay error!";
    }

    @Override
    public String videoPlay(String videoPath) {
        log.error("videoPlay 调用失败! 服务降级!");
        return "videoPlay error!";
    }
}
MusicServiceFallBack.java

config目录下的文件没用到。

Child-Gateway子工程

目录结构

Child-Provider子工程

目录结构

 源代码:

package com.wslio.childprovider.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
public class MusicController {

    @RequestMapping("/provider/musicplay")
    public String musicPlay(@RequestParam String musicPath){
        log.info("播放音乐文件[{}]", musicPath);
        return musicPath;
    }
}
MusicController.java
package com.wslio.childprovider.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
public class VideoController {

    @RequestMapping("/provider/videoplay")
    public String videoPlay(@RequestParam String videoPath){
        log.info("播放视频文件[{}]", videoPath);
        return videoPath;
    }
}
VideoController.java

PS:以上源码,里边没有涉及到分布式事务,没时间搞了。。。,但大致的架子已经搭起来,通过consumer可以顺利调取provider的服务,亦能通过gateway服务调用微服务!

不想手动搞的,这里有git直通车分享,https://github.com/wslio/ParentPro.git

原文地址:https://www.cnblogs.com/wslio/p/15286614.html