第一章springcloud之微服务概念,基于rest调用例子。

 好记性不如烂笔头。有些事情看着简单,做起来可能就会碰到问题。这是我从视频上看到的一个例子,决定把它写下来

1、先介绍一下单体应用架构和微服务的区别
单个应用包含所有功能,不涉及多个应用的互联互调,便于在团队之间开发与测试。
易于部署:只需将单个应用打成war或jar包,进行部署到Tomcat即可,运维起来比较方便。
易于整体扩展:当应用负载压力大时,将这个应用复制几份,分别部署在不同的服务器上,再通过负载
均衡即可提高应用的并发能力。
缺点
复杂性高:由于是单个应用,所以整个项目文件包含的模块非常多,导致模块的边界模糊、依赖关
系不清晰、代码的质量参差不齐,混乱的堆在一起,使得整个项目非常复杂。以致每次修改代码,都非
常小心,可能添加一个简单的功能,或者修改一个Bug都会带来隐藏的缺陷。
技术债务:随着时间的推
移、需求的变更和技术人员的更替,会逐渐形成应用程序的技术债务,并且越积越多。
碍技术创新
对于单体应用来说,技术是在开发之前经过慎重评估后选定的,每个团队成员都必须使用相同的开发语
言、持久化存储及消息系统

微服务架构的优缺点
优点
1. 易于开发和维护:一个微服务只会关注一个特定的业务功能,所以业务清晰、代码量较少。开发和
维护单个微服务相对简单。
2. 单个微服务启动较快
3. 局部修改容易部署:单一应用只要有修改,就得重新部署整个应用。微服务解决了这样的问题。一
般来说,对某个微服务进行修改,只需要重新部署这个服务即可。
4. 技术栈不受限制:在微服务架构中,可以结合项目业务及团队的特点,合理的选择技术栈。不同的模块可以用不同的开发语言
5. 按需伸缩:可根据需求,实现细粒度的扩展。
缺点
1. 运维要求高:更多的服务意味着要投入更多的运维。
2. 分布式固有的复杂性:使用微服务构建的是分布式系统。对于一个分布式系统,系统容错、网络延
迟、分布式事务等都会带来巨大的问题。
3. 接口调整成本高:微服务之间通过接口进行通信。如果修改某一个微服务的API,可能所有用到这
个接口的微服务都需要进行调整。

 

2、什么是 Spring Cloud

Spring Cloud,基于 Spring Boot 提供了一套微服务解决方案,包括服务注册与发现,配置中心,全链路监
控,服务网关,负载均衡,熔断器等组件,除了基于NetFlix的开源组件做高度抽象封装之外,还有一些选型
中立的开源组件。
官方译文:构建分布式系统不用特别的复杂且避免容易出现的错误。Spring Cloud为最常见的分布式系统模式
提供了一个简单和可访问的编程模型,帮助开发人员构建弹性、可靠和协调的应用程序。SpringCloud构建在
SpringBoot之上,使开发人员很容易开始工作并迅速提高生产力。

3、SpringBoot和SpringCloud的关系
Spring Boot 可以离开 Spring Cloud 单独使用开发项目,但是Spring Cloud离不开SpringBoot,属于依赖的
关系.
Spring Boot 专注于快速方便的开发单个个体微服务,Spring Cloud 关注全局的服务治理框架。
Spring Cloud 是关注全局的微服务协调整理治理框架,它将 Spring Boot 开发的一个个单体微服务整合并管
理起来,为各个微服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策
竞选、分布式会话等等集成服务

4、参考资料
官网: http://spring.io/projects/spring-cloud
各组件说明(中文版):https://springcloud.cc/spring-cloud-netflix.html
详细文档版:
英文版:https://cloud.spring.io/spring-cloud-static/Finchley.SR2/single/spring-cloud.html
中文版:https://springcloud.cc/spring-cloud-dalston.html
Spring Cloud 中国社区:http://springcloud.cn/
Spring Cloud 中文网:https://springcloud.cc/
Spring Cloud 目前集合了21种分布式微服务架构技术

5、开发环境
jdk1.8 (Spring Boot 推荐jdk1.8及以上): java version "1.8.0_151"
Maven 3.x (maven 3.2 以上版本):Apache Maven 3.3.9
IntelliJ IDEA :IntelliJ IDEA 2018.2.1 x64
Spring Boot :Spring Boot 2.0.7
Spring Cloud 使用当前最新稳定版本:Finchley SR2 , 搭配 Spring Boot 2.0.7 稳定版

一:安装maven,在maven的settings.xml 中添加如下依赖。
<!--开始处更改下载依赖的存放路径, 以下目录需要已经创建-->
<localRepository>D:\javasource\maven-repository</localRepository>
<!--在 mirrors 标签下 添加阿里云maven私服库-->
<mirrors>
<mirror> 
   <id>alimaven</id> 
   <mirrorOf>central</mirrorOf> 
   <name>aliyun maven</name> 
   <url>http://maven.aliyun.com/nexus/content/groups/public/</url> 
  </mirror>
</mirrors>
<!-- 在 profiles 标签下指定jdk版本 -->
<profile>
 <id>jdk-1.8</id>
 <activation>
  <activeByDefault>true</activeByDefault>
  <jdk>1.8</jdk>
 </activation>
 <properties>
  <maven.compiler.source>1.8</maven.compiler.source>
  <maven.compiler.target>1.8</maven.compiler.target>
  <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
 </properties>
</profile>

二:idea 配置maven
settings----搜索maven--找到Maven home directory,配置maven的安装路径 
 

三:以 商品管理模块 做一个微服务架构通用案例,消费者Consumer(Client)通过REST调用 提供者
Provider(Server)提供的商品管理服务。

Maven的分包分模块架构
一个 Project 父工程下有多个 Module 子模块
microservice-cloud-01 父工程(Project)下初始化 3个子模块(Module):
microservice-cloud-02-api 封装的整体Entity/接口/公共配置等
microservice-cloud-03-provider-product-8001 微服务的服务提供者Provider
microservice-cloud-04-consumer-product-80 微服务的服务消费者Consumer
浏览器发送URL请求服务默认的端口号都是80,因此只需输入IP或域名即可,可省略 :80

1)构建一个空的工程。

2)创建父工程(pom类型)


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>com.run.springcloud</groupId>
    <artifactId>microservice-cloud-01</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.7.RELEASE</version>
        <relativePath/>
    </parent>


    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <junit.version>4.12</junit.version>
        <!-- spring cloud 采用 Finchley.SR2 版本 -->
        <spring-cloud.version>Finchley.SR2</spring-cloud.version>
    </properties>


    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <!--maven不支持多继承,使用import来依赖管理配置-->
                <scope>import</scope>
            </dependency>
            <!--导入 mybatis 启动器-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.2</version>
            </dependency>
            <!--druid数据源-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.12</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.13</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

注意:如果是copy的pom文件,可能会碰到下面的这个提示。拷贝时带了特殊符号。在idea中将每行前面的空格删除。然后Alt+Ctrl+L格式化。提示信息:expected START_TAG or END_TAG not TEXT (position: TEXT seen ...<properties>\n \ua0\ua0\ua0\ua0<p... 
 

 最后删除 src 目录及子目录。

3)构建公共模块(microservice-cloud-02-api)



pom中可以看到它的parent为:

<parent>
<groupId>com.run.springcloud</groupId>
<artifactId>run-cloud-01</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../run-cloud-01/pom.xml</relativePath>
 </parent>ent>

 

 

 

1.创建product实体类:

package com.caxa.entities;

import java.io.Serializable;

public class Product implements Serializable {

    public String pid;
    public String productName;
    public String dbSource;

    public Product() {
    }

    public Product(String pid, String produceName, String dbSource) {
        this.pid = pid;
        this.productName = produceName;
        this.dbSource = dbSource;
    }

    public String getPid() {
        return pid;
    }

    public void setPid(String pid) {
        this.pid = pid;
    }

    public String getProduceName() {
        return productName;
    }

    public void setProduceName(String produceName) {
        this.productName = produceName;
    }

    public String getDbSource() {
        return dbSource;
    }

    public void setDbSource(String dbSource) {
        this.dbSource = dbSource;
    }
}

4)构建服务提供者
创建Module:microservice-cloud-03-provider-product-8001



配置 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>microservice-cloud-01</artifactId>
        <groupId>com.run.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../microservice-cloud-01/pom.xml</relativePath>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>microservice-cloud-03-provider-product-8001</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.run.springcloud</groupId>
            <artifactId>microservice-cloud-02-api</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!--springboot web启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- mybatis 启动器-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
    </dependencies>
</project>

在 src/main/resources下新建application.yml文件,配置如下,注意其中的空格

server:
  port: 8001
mybatis:
  config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路径
  type-aliases-package: com.mengxuegu.springcloud.entities # 所有Entity别名类所在包
  mapper-locations: classpath:mybatis/mapper/**/*.xml # mapper映射文件
spring:
  application:
    name: microservice-product #这个很重要,这在以后的服务与服务之间相互调用一般都是根据这个name
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型
    driver-class-name: com.mysql.cj.jdbc.Driver # mysql驱动包
    url: jdbc:mysql://127.0.0.1:3306/springcloud_db01?serverTimezone=GMT%2B8 # 数据库名称
    username: root
    password: root
    dbcp2:
     min-idle: 5 # 数据库连接池的最小维持连接数
     initial-size: 5 # 初始化连接数
     max-total: 5 # 最大连接数
     max-wait-millis: 150 # 等待连接获取的最大超时时间

创建mysql数据库脚本:

DROP DATABASE IF EXISTS springcloud_db01;
CREATE DATABASE springcloud_db01 CHARACTER SET UTF8;
USE springcloud_db01;
CREATE TABLE product
(
pid BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
product_name VARCHAR(50),
db_source VARCHAR(50)
);
INSERT INTO product(product_name,db_source) VALUES('格力空调',DATABASE());
INSERT INTO product(product_name,db_source) VALUES('海尔冰箱',DATABASE());
INSERT INTO product(product_name,db_source) VALUES('小短裙',DATABASE());
INSERT INTO product(product_name,db_source) VALUES('羽绒服',DATABASE());
INSERT INTO product(product_name,db_source) VALUES('韩版休闲鞋',DATABASE());
INSERT INTO product(product_name,db_source) VALUES('高贵鞋',DATABASE());

创建 Mapper 接口

package com.run.springcloud.mapper;
import com.run.springcloud.entities.Product;

import java.util.List;

public interface ProductMapper{
    public Product findById(Long pid);
    public List<Product> findAll();
    public boolean addProduct(Product product);
}

Mybatis 相关配置

src/main/resources下新建 mybatis 目录后新建 mybatis.cfg.xml 核心配置文件,内容如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <settings>
        <!--开启驼峰命名-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
</configuration>

src/main/resources/mybatis 下新建 mapper 目录后新建 ProductMapper.xml 映射文件,内容如下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.run.springcloud.mapper.ProductMapper">
    <select id="findById" resultType="Product" parameterType="Long">
        select pid, product_name, db_source from product where pid=#{pid};
    </select>
    <select id="findAll" resultType="Product">
        select pid, product_name, db_source from product;
    </select>
    <insert id="addProduct" parameterType="Product">
        INSERT INTO product(product_name, db_source) VALUES(#{productName},
        DATABASE());
    </insert>
</mapper>

创建 服务层,服务接口:ProductService

package com.run.springcloud.service;

import com.run.springcloud.entities.Product;

import java.util.List;

public interface ProductService {
    public Product findById(Long id);
    public List<Product> findAll();
    public boolean addProduct(Product product);
}

服务接口实现类 ProductServiceImpl

package com.run.springcloud.service.com.run.springcloud.service.impl;

import com.run.springcloud.mapper.ProductMapper;
import com.run.springcloud.entities.Product;
import com.run.springcloud.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ProductServiceImpl implements ProductService {
    @Autowired
    private ProductMapper productMapper;

    @Override
    public Product findById(Long id) {
        return productMapper.findById(id);
    }

    @Override
    public List<Product> findAll() {
        return productMapper.findAll();
    }

    @Override
    public boolean addProduct(Product product) {
        return productMapper.addProduct(product);
    }
}

创建 控制层-提供者

package com.run.springcloud.controller;

import com.run.springcloud.entities.Product;
import com.run.springcloud.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.Method;
import java.util.List;

@RestController
public class ProductController {
    @Autowired
    private ProductService productService;

    @RequestMapping(value = "/product/add", method = RequestMethod.POST)
    public boolean add(@RequestBody Product product) {
        return productService.addProduct(product);
    }


    @RequestMapping(value = "/product/get/{id}")
    public Product get(@PathVariable("id") Long id) {
        return productService.findById(id);
    }
    
    @RequestMapping(value = "/product/list", method = RequestMethod.GET)
    public List<Product> list() {
        return productService.findAll();
    }

}

创建主启动类:ProductProvider_8001

package com.run.springcloud;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("com.run.springcloud.mapper")
@SpringBootApplication
public class ProductProvider_8001 {

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

功能测试
get方法的直接在浏览器中测试。
http://localhost:8001/product/get/3
http://localhost:8001/product/list

注意add的post方法测试。使用postman测试。如下图:

 

创建服务消费者。microservice-cloud-04-consumer-product-80

配置 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>microservice-cloud-01</artifactId>
        <groupId>com.run.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../microservicecloud01/pom.xml</relativePath>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>microservice-cloud-04-consumer-product-80</artifactId>
    <dependencies>
    <dependency>
        <groupId>com.run.springcloud</groupId>
        <artifactId>microservice-cloud-02-api</artifactId>
        <version>${project.version}</version>
    </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>

配置 application.yml 文件

server:
  port: 80

自定义Rest相关配置类
在 com.run.springcloud.config 包下新建配置类: ConfigBean
向容器中注入 RestTemplate 组件, 提供了多种简单便捷的访问 Restful 服务的方法,是Spring提供的用于访
问Rest服务的客户端模板工具集。 (url, requestMap, ResponseBean.class)这三个参数分别代表:
REST请求地址、请求参数、HTTP响应转换被转换成的对象类型。

package com.run.springcloud.config;


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

@Configuration
public class ConfigBean {

    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

创建 控制层-消费者
在 com.run.springcloud.controller 包下新建消费者: ProductController_Consumer

package com.run.springcloud.controller;

import com.run.springcloud.entities.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
public class ProductController_Consumer {
    private static final  String REST_URL_PREFIX = "http://localhost:8001";

    @Autowired
    private RestTemplate restTemplate;
    @RequestMapping(value="consumer/product/add",method = RequestMethod.POST)
    public boolean add(@RequestParam Product product){
        return restTemplate.postForObject(REST_URL_PREFIX+"/product/add",product,Boolean.class);
    }
    @RequestMapping(value="consumer/product/get/{id}",method = RequestMethod.GET)
    public Product get(@PathVariable("id") String id){

        return restTemplate.getForObject(REST_URL_PREFIX+"/product/get/"+id,Product.class,);
    }
    @RequestMapping(value="consumer/product/list",method = RequestMethod.GET)
    public List<Product> list(){
        return restTemplate.getForObject(REST_URL_PREFIX+"/product/list/",List.class);
    }


}

创建 主启动类

package com.run.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ProductConsumer_80 {

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

测试:

http://localhost/consumer/product/get/3
http://localhost/consumer/product/list
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值