微服务架构整理-(四、无框架搭建微服务)

之前整理过一些微服务的相关知识,这里打算通过一个小demo逐渐了解微服务的搭建过程。

环境

  1. IDE:IntelliJ 社区版2018.1
  2. JDK: Open jdk 11
  3. SpringBoot: 2.2.6.RELEASE

业务逻辑

模仿一个商城,在自己的订单(order)中查询商品(product)
在这里插入图片描述

创建maven聚合工程

父工程

步骤:File->New->Project->maven,定义好groupId 和artifactId 然后下一步。创建成功后删除src,并导入相应的依赖.

  1. 工程目录
    在这里插入图片描述

  2. 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>

    <groupId>cn.research</groupId>
    <artifactId>spring_cloud_demo</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>product_service</module>
        <module>order_service</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-logging -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId> <!-- This one is super important for web controller -->
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR10</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

        </dependencies>
    </dependencyManagement>

</project>

子工程(product 服务)

此服务提供了根据商品id查询商品的API
这里只展示代码结构和Controller层的代码,其他部分的代码,可以免分下载
步骤:spring_cloud_demo工程名上右击New->Module->maven,输入artifact_id:product_service

  1. 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">
    <parent>
        <artifactId>spring_cloud_demo</artifactId>
        <groupId>cn.research</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>product_service</artifactId>
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.23</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
    </dependencies>
</project>
  1. 在数据库cloud创建product表
CREATE TABLE `product` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) DEFAULT NULL,
  `price` decimal(10,2) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;

3.搭建各层的结构,项目结构下
在这里插入图片描述
其中controller中向外暴露了一个接口:

package com.research.product.controller;

import com.research.product.entity.Product;
import com.research.product.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * @author :TS六道轮回
 * @date :Created in 2021/3/6 22:47
 * @description:${description}
 */
@RestController
@RequestMapping("/product")
public class ProductController {
    @Autowired
    ProductService productService;

    @GetMapping(value = "/{id}")
    public Product findById(@PathVariable Long id){
        return productService.findById(id);
    }
}
  1. 配置文件
server:
  port: 9001 #端口
spring:
  favicon:
    enabled: false
  application:
    name: service-product #服务名称
  datasource:
    username: root
    password: abcde
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/cloud?useUnicode=true&characterEncoding=UTF-8
  jpa:
    database: MySQL
    show-sql: true
    open-in-view: true
  1. 程序运行结果
    在这里插入图片描述

子工程(order 服务)

此服务通过调用product 服务提供的接口来获取商品。
同product 服务一样,这里也只展示代码结构和Controller层以及与product服务不一致的地方,其他部分的代码,可以免分下载
步骤:spring_cloud_demo工程名上右击New->Module->maven,输入artifact_id:order_service

  1. 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">
    <parent>
        <artifactId>spring_cloud_demo</artifactId>
        <groupId>cn.research</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>order_service</artifactId>
	<dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.23</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
    </dependencies>
</project>
  1. 搭建各层的结构,项目结构下
    为了模拟简单的功能,order服务只访问product服务,结构上主要有如下区别
    a. 没有与数据库进行交互,因此没有Dao层和Entity包
    b. 对product服务的访问放到Controller层中完成,因此这里没有Service层,真正开发过程中应该是在Service层中完成。
    c. 对product的访问使用了RestTemplate, 在config中将其加入到容器中,因此多了config包。
    d. 对返回值处理时使用了product dto来接受的,因此多了dto包。
    在这里插入图片描述
    config中使用@Bean创建RestTemplate
package com.research.order.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * @author :TS六道轮回
 * @date :Created in 2021/3/9 22:02
 */
@Configuration
public class Config {
    @Bean
    public RestTemplate getRestTemplate(){
        return  new RestTemplate();
    }
}

controller中使用RestTemplate调用product服务,并且向外暴露接口

package com.research.order.controller;

import com.research.order.dto.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @author :TS六道轮回
 * @date :Created in 2021/3/9 21:48
 */
@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    RestTemplate restTemplate;
    @GetMapping(value = "/buy/{id}")
    public Product findById(@PathVariable Long id) {
        Product product = null;
        //真正的开发过程这部分代码应该放到service层里
        product = restTemplate.getForObject("http://localhost:9001/product/"+id,Product.class);
        return product;
    }
}

  1. 配置文件
    没有与数据库进行交互,因此删掉数据库相关的配置
server:
  port: 9002 #端口
spring:
  favicon:
    enabled: false
  application:
    name: service-order #服务名称
  1. 程序运行结果
    在这里插入图片描述

分析代码问题

通过上面的例子,虽然服务之间的通信没有问题,但随着规规模不断的扩大,相应的问题也随之出现,通过下图分析
在这里插入图片描述

  1. 服务调用者将服务提供者的接口路径硬编码到自己的代码中,如果服务提供者修改接口路径,服务调用者必定要修改,无形中增加了调用者开发难度。
  2. 当前事例中只有一个服务提供者,随着业务的扩展服务提供者的数量会越来越多,如果所有的接口路径都硬编码到服务调用者中,一旦发生变动,服务调用者的修改工作量无法估量
  3. 为了提供系统的可靠性,一个服务提供者必定会构建多个节点,服务调用者又如何去选择哪一个节点,因此负载均衡无法保证。
  4. 服务调用者需要知道每个服务的地址,任务太重了,如果中间有一个管理者就好了,服务调用者只需要将请求发给这个中间人就可以了,因此无法实现网关的功能,
  5. 当服务调用者需要的服务来自各个服务提供者的协作完成时,这种情况日志又如何记录,因此链路追踪无法保证。
  6. 当服务提供者的数量越来越多时,相应的配置文件也随之增多,一旦修改某个配置文件,将造成其他服务的变动,因此无法对配置进行统一管理。
    可见,自己手动搭一套微服务框架,需要我们自己解决很多的问题,并且解决起来都不是那么简单的一件事,好在SpringCloud为我们提供了解决方案,在下一篇博客中,介绍如何使用SpringCloud来搭建微服务。

代码下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浦江之猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值