0


Spring Boot整合eureka和config搭建微服务框架(入门)

    最近接触了公司内部开发的项目,涉及到了Config配置中心河eureka服务注册中心,以前只用过Nacos服务配置中心,所以边学边试搭建了一个简单的微服务的项目框架,同时记录一下自己踩过的坑。**注:该demo中使用了远程调用服务,所以引入了Feign调用。**

1.从零到一搭建项目

    首先创建一个maven项目,在这里我们构建一个父子项目,拆分为四个子项目:order、product、config、eureka,具体的项目结构如下:

    父程序pom依赖如下:
  <properties>
        <java.version>1.8</java.version>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-cloud.version>2021.0.1</spring-cloud.version>
        <spring-cloud-alibaba.version>2022.0.0.0-RC2</spring-cloud-alibaba.version>
        <mybatis-spring-boot-starter.version>3.0.2</mybatis-spring-boot-starter.version>
        <spring-boot.version>2.6.4</spring-boot.version>
        <mybatis-plus.version>3.5.3.1</mybatis-plus.version>
        <hutool-all.version>5.8.20</hutool-all.version>
        <mysql.version>8.0.33</mysql.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
        </dependency>

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

            <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>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${mybatis-plus.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jdbc</artifactId>
                <version>${spring-boot.version}</version>
            </dependency>
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>${hutool-all.version}</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version> <!-- 最新稳定版本 -->
            </dependency>
        </dependencies>
    </dependencyManagement>
    如果要改成自己的版本依赖,需要注意Spring Boot、Spring Cloud和eureka之间的对应关系,建议确定其中两个依赖的版本,然后由Maven自动引入剩余依赖。

2.构建eureka服务

2.1 服务包结构和配置

    项目的启动顺序是eureka->config->其他微服务,因为其他服务需要向eureka注册中心注册服务,所以在这里先搭建eureka注册中心。

    eureka微服务结构如下:

    eureka-server的pom文件如下:
<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    application.yml:
spring:
  application:
    name: eureka-server
server:
  port: 8761
eureka:
  instance:
    hostname: 127.0.0.1
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      default-Zone: http://127.0.0.1:8761/eureka

2.2 eureka配置注意事项

  • eureka启动类需要加入@EnableEurekaServer注解。
  • eureka服务启动可能出现以下问题:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class

该问题出现的原因是引入了spring-boot-starter-jdbc 的依赖,但是并没有正确配置数据库,可以在启动类注解中加入@SpringBootApplication(exclude = DataSourceAutoConfiguration.class),去除掉数据库资源的自动扫描。

  • 在启动eureka服务之后,可以通过浏览器访问8761端口的方式来检测服务启动情况,同时在后续其他微服务发起注册之后,可以查看注册情况。

3.构建config配置中心

3.1 服务包结构和配置

    config配置中心用来存放其他微服务的配置文件,当其他微服务启动时,从配置中心拉取配置文件,完成服务启动。在该demo中,我将项目配置文件存储到了本地,并没有利用git存储到云端。项目包结构如下:

    将其他服务的配置文件放在了config目录下,同时需要在config配置文件中注明路径,xxx-test.yml表示测试环境下的配置,xxx-dev.yml表示开发环境下的配置,xxx-release.yml表示生产环境下的配置。在这里我仅引入了两个服务的dev环境下的配置。

    pom文件如下:
        <!--eureka 客户端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
    applictaion.yml如下,profiles.active=native表示配置文件存储在本地,cloud.config.server.native.search-locations表示配置文件存储的位置,即位于上一级目录的config目录下。
server:
  port: 8888
spring:
  application:
    name: config-server
  profiles:
    active: native
  cloud:
    config:
      server:
        native:
          search-locations:  file:./config/,classpath:/config/
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
    config目录下的配置文件,我仅仅进行了数据库配置, 如下:
spring:
  datasource:
    username: root
    password: ********
    url: jdbc:mysql://ip:port/database_name?characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8
    driver-class-name: com.mysql.cj.jdbc.Driver
    hikari:
      connection-test-query: select 1
      connection-timeout: 20000
      idle-timeout: 300000
      maximum-pool-size: 5
      minimum-idle: 5

3.2 config配置注意事项

  • 服务端的配置引入的相关依赖为
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-config-server</artifactId>
</dependency>

4.构建order服务

4.1 order服务包结构和配置

    在该项目demo中,order服务远程调用product服务,获取商品名和商品价格。所以应当在order服务启动类上加上@EnableFeignClients。order-server的项目结构如下:

     pom文件如下:
     <dependencies>
        <!--eureka 客户端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</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-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</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-bootstrap</artifactId>
        </dependency>
    </dependencies>
    配置文件的启动顺序为bootstrap.yml->application.yml->配置中心配置,同时后续的配置会覆盖以前的配置,注意eureka注册服务名均为大写,bootstrap.yml和application.yml文件如下:

    bootstrap.yml:
spring:
  cloud:
    config:
      discovery:
        enabled: true
        service-id: CONFIG-SERVER
      name: ${spring.application.name}
      profile: ${spring.profiles.active}
      fail-fast: true
eureka:
  client:
    service-url:
      default-zone: http://127.0.0.1:8761/eureka
    registry-fetch-interval-seconds: 30
    application.yml:
server:
  port: 8081
spring:
  application:
    name: order-server
  profiles:
    active: dev
    在bootstrap.yml中的config配置中指定了配置中心的服务id为CONFIG-SERVER,配置中心名称为order-server,配置环境为dev。

4.2 order服务配置注意事项

  • 在引入bootstrap.yml后,无法启动项目,并报出如下如下错误,这个错误的原因是,在springcloud2020版本之后,默认禁用了bootstrap配置文件的引入,所以需要我们手动引入相关依赖。
Application failed to start due to an exception
org.springframework.cloud.commons.ConfigDataMissingEnvironmentPostProcessor$ImportException: No spring.config.import set

5. 构建product服务

5.1 product服务包结构和配置

    product服务包结构如下:

     pom文件如下:
     <dependencies>
        <!--eureka 客户端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</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-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</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-bootstrap</artifactId>
        </dependency>
    </dependencies>
     bootstrap.yml文件如下:
spring:
  cloud:
    config:
      discovery:
        enabled: true
        service-id: CONFIG-SERVER
      name: ${spring.application.name}
      profile: ${spring.profiles.active}
      fail-fast: true
eureka:
  client:
    service-url:
      default-zone: http://localhost:8761/eureka
    registry-fetch-interval-seconds: 30
    application.yml文件如下:
server:
  port: 8080
spring:
  application:
    name: product-server
  profiles:
    active: dev

6. 编写product服务代码

6.1 数据库设计

DROP TABLE IF EXISTS `product`;
CREATE TABLE `product`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  `price` decimal(10, 2) NOT NULL,
  `stock` int(0) NOT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of product
-- ----------------------------
INSERT INTO `product` VALUES (1, 'Laptop', 999.99, 10);
INSERT INTO `product` VALUES (2, 'Smartphone', 499.99, 50);
INSERT INTO `product` VALUES (3, 'Tablet', 299.99, 30);
INSERT INTO `product` VALUES (4, 'Headphones', 79.99, 100);
INSERT INTO `product` VALUES (5, 'Smartwatch', 199.99, 25);

6.2 编写启动类

    因为order为服务发起方,product服务为被调用方,所以product服务仅需要添加@SpringBootApplication和@MapperScan两个注解。

6.3 编写商品服务controller层

    productController代码如下,编写了一个简单api,通过id获取商品信息
@RestController
public class ProductController {
    
    @Resource
    private ProductService productService;
    
    @GetMapping("/api/product/getProduct")
    public ProductRespDTO product(@RequestParam("id")Integer id){
        return productService.getProductById(id);
    }
}

6.4 编写商品服务Service层

   ProductService代码如下:
public interface ProductService {
    ProductRespDTO getProductById(Integer id);
}

6.5 编写商品服务Service实现层

    ProductServiceImpl代码如下,这里没有做复杂的逻辑处理,直接查数据库返回结果。我使用的是mybatis-plus,自带的函数,可以用其他代替。
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, ProductDO>implements ProductService {
    
    @Override
    public ProductRespDTO getProductById(Integer id) {
        LambdaQueryWrapper<ProductDO> queryWrapper = Wrappers.lambdaQuery(ProductDO.class)
          .eq(ProductDO::getId, id);
        ProductDO productDO = baseMapper.selectOne(queryWrapper);
        ProductRespDTO result=new ProductRespDTO();
        BeanUtil.copyProperties(productDO,result);
        return result;
    }
}

6.6 编写商品服务Dao层实体和mapper接口

    引入lombok,利用在线网站生成实体类,网站地址:凝聚力开发,实体类如下:
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TableName("product")
public class ProductDO {
    private Integer id;          // 产品 ID
    private String name;         // 产品名称
    private BigDecimal price;    // 产品价格
    private Integer stock;       // 产品库存
}
    mapper层接口如下:
@Mapper
public interface ProductMapper extends BaseMapper<ProductDO> {
}

6.7 请求返回实体类

    ProductRespDTO实体,仅返回商品的名称和价格。
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ProductRespDTO {
    private String name;         // 产品名称
    private BigDecimal price;    // 产品价格
}

7. 编写Order服务

7.1 编写订单服务启动类

    Order服务需要远程调用Product服务,所以这里涉及到Feign调用。OrderApplication.class如下:
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class,args);
    }
}

7.2 编写订单服务controller层

@RestController
public class OrderController {
    @Resource
    private ProductFeignClient productFeignClient;
    @GetMapping("/api/getOrder")
    public ProductRespDTO getProduct(@RequestParam("id")Integer id){
        return productFeignClient.getProduct(id);
    }
}

7.3 编写订单服务返回实体类

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ProductRespDTO {
    private String name;         // 产品名称
    private BigDecimal price;    // 产品价格
}

7.4 编写远程调用接口

    注意,因为在eureka服务注册中心默认注册服务名为大写,所以引入也需要用大写,同时注意远程调用的接口路径需要与被调用api的路径一致,具体代码如下:
@FeignClient(value = "PRODUCT-SERVER")
public interface ProductFeignClient {
    @GetMapping("/api/product/getProduct")
    ProductRespDTO getProduct(@RequestParam("id")Integer id);
}

8. 总结

    微服务启动顺序为:eureka->config->order/product。在后续项目启动之后可从eureka注册服务中心查看微服务注册情况,可直接访问对应接口传参进行测试。

    例如,可使用apifox或者postman对接口测试,来查看微服务搭建情况:


本文转载自: https://blog.csdn.net/m0_51373428/article/details/141682759
版权归原作者 Passion_yjx 所有, 如有侵权,请联系我们删除。

“Spring Boot整合eureka和config搭建微服务框架(入门)”的评论:

还没有评论