SpringCloud的介绍以及快速入门

Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,
如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。
Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,
通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。

微服务中的相关概念:

  服务注册与发现:

    服务注册:服务实例将自身服务信息注册到注册中心。这部分服务信息包括服务所在主机IP和提供服务的Port,以及暴露服务自身状态以及访问协议等信息。
    服务发现:服务实例请求注册中心获取所依赖服务信息。服务实例通过注册中心,获取到注册到其中的服务实例的信息,通过这些信息去请求它们提供的服务。
  负载均衡:

    负载均衡是高可用网络基础架构的关键组件,通常用于将工作负载分布到多个服务器来提高网站、应用、数据库或其他服务的性能和可靠性。
  熔断:

    熔断这一概念来源于电子工程中的断路器(Circuit Breaker)。在互联网系统中,当下游服务因访问压力过大而响应变慢或失败,
    上游服务为了保护系统整体的可用性,可以暂时切断对下游服务的调用。这种牺牲局部,保全整体的措施就叫做熔断。
  链路追踪:

    随着微服务架构的流行,服务按照不同的维度进行拆分,一次请求往往需要涉及到多个服务。互联网应用构建在不同的软件模块集上,
    这些软件模块,有可能是由不同的团队开发、可能使用不同的编程语言来实现、有可能布在了几千台服务器,横跨多个不同的数据中心。
    因此,就需要对一次请求涉及的多个服务链路进行日志记录,性能监控即链路追踪
  API网关:

    随着微服务的不断增多,不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,
    如果让客户端直接与各个微服务通信可能出现:
      客户端需要调用不同的url地址,增加难度
      在一定的场景下,存在跨域请求的问题
      每个微服务都需要进行单独的身份认证
    针对这些问题,API网关顺势而生。
      API网关直面意思是将所有API调用统一接入到API网关层,由网关层统一接入和输出。一个网关的基本功能有:
        统一接入、安全防护、协议适配、流量管控、长短链接支持、容错能力。
        有了网关之后,各个API服务提供团队可以专注于自己的的业务逻辑处理,而API网关更专注于安全、流量、路由等问题。

SpringCloud中的核心组件:

  Spring Cloud的本质是在 Spring Boot 的基础上,增加了一堆微服务相关的规范,并对应用上下文(Application Context)进行了功能增强。
  既然 Spring Cloud 是规范,那么就需要去实现,目前Spring Cloud 规范已由 Spring官方Spring Cloud Netflix,Spring Cloud Alibaba等实现。
  通过组件化的方式,Spring Cloud将这些实现整合到一起构成全家桶式的微服务技术栈。
  Spring Cloud Netflix组件:

    

   Spring Cloud Alibaba组件:

    

   Spring Cloud原生及其他组件:

    

  注册中心负责服务的注册与发现,很好将各服务连接起来
  断路器负责监控服务之间的调用情况,连续多次失败进行熔断保护。
  API网关负责转发所有对外的请求和服务
  配置中心提供了统一的配置信息管理服务,可以实时的通知各个服务获取最新的配置信息

  链路追踪技术可以将所有的请求数据记录下来,方便我们进行后续分析
  各个组件又提供了功能完善的dashboard监控平台,可以方便的监控各组件的运行状况

快速入门:

  使用微服务架构的分布式系统,微服务之间通过网络通信。我们通过服务提供者与服务消费者来描述微服务间的调用关系。
    服务提供者:服务的被调用方,提供调用接口的一方
    服务消费者:服务的调用方,依赖于其他服务的一方
  以电商系统中常见的用户下单为例,用户向订单微服务发起一个购买的请求。在进行保存订单之前需要调用商品微服务查询当前商品库存,单价等信息。
  在这种场景下,订单微服务就是一个服务消费者,商品微服务就是一个服务提供者

    

  数据库表:

    商品表

CREATE TABLE `tb_product` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`product_name` varchar(40) DEFAULT NULL COMMENT '名称',
`status` int(2) DEFAULT NULL COMMENT '状态',
`price` decimal(10,2) DEFAULT NULL COMMENT '单价',
`product_desc` varchar(255) DEFAULT NULL COMMENT '描述',
`caption` varchar(255) DEFAULT NULL COMMENT '标题',
`inventory` int(11) DEFAULT NULL COMMENT '库存',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8

    订单表

CREATE TABLE `tb_order` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL COMMENT '用户id',
`product_id` int(11) DEFAULT NULL COMMENT '商品id',
`number` int(11) DEFAULT NULL COMMENT '数量',
`price` decimal(10,2) DEFAULT NULL COMMENT '单价',
`amount` decimal(10,2) DEFAULT NULL COMMENT '总额',
`product_name` varchar(40) DEFAULT NULL COMMENT '商品名',
`username` varchar(40) DEFAULT NULL COMMENT '用户名',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

  搭建环境:

    1.创建父工程并引入坐标

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

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.32</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
View Code

    2.创建微服务工程模块

      创建公共模块 common_service ,用于存放公共的实体类和工具类

      创建商品微服务模块 product_service

      创建订单微服务模块 order_service

    3.工程的依赖结构

      

  搭建公共模块:

    1.在common_service创建实体类

/**
 * 商品实体类
 */
@Data
@Entity
@Table(name="tb_product")
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String productName;
    private Integer status;
    private BigDecimal price;
    private String productDesc;
    private String caption;
    private Integer inventory;
}
View Code

  搭建商品微服务:

    1.在product_service的pom文件中引入坐标

<dependency>
    <groupId>com.fgy</groupId>
    <artifactId>common_service</artifactId>
    <version>1.0-SNAPSHOT</version>
    <scope>compile</scope>
</dependency

    2.编写dao接口

/**
 * 商品持久层接口
 */
public interface ProductDao extends JpaRepository<Product,Long>, JpaSpecificationExecutor<Product> {
}

    3.编写service层

/**
 * 商品业务层接口
 */
public interface ProductService {

    /**
     * 根据id查询
     * @return
     */
    Product findById(Long id);

    /**
     * 保存
     */
    void save(Product product);

    /**
     * 更新
     */
    void update(Product product);

    /**
     * 删除
     */
    void delete(Long id);
}
View Code
/**
 * 商品业务层实现类
 */
@Service
public class ProductServiceImpl implements ProductService {

    @Autowired
    private ProductDao productDao;

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

    @Override
    public void save(Product product) {
        productDao.save(product);
    }

    @Override
    public void update(Product product) {
        productDao.save(product);
    }

    @Override
    public void delete(Long id) {
        productDao.deleteById(id);
    }
}
View Code

    4.编写web层

/**
 * 商品控制层
 */
@RestController // 使用rest风格
@RequestMapping("/product")
public class ProductController {

    @Autowired
    private ProductService productService;

    @GetMapping(value = "/{id}")
    public Product findById(@PathVariable Long id) {
        Product product = productService.findById(id);
        return product;
    }

    @PostMapping
    public String save(@RequestBody Product product) {
        productService.save(product);
        return "保存成功";
    }
}
View Code

    5.配置启动类

@SpringBootApplication
@EntityScan("com.fgy.common.domain")
public class ProductApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProductApplication.class,args);
    }
}
View Code

    6.配置yml文件

server:
  port: 9001
spring:
  application:
    name: service-product #服务名称
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud?useUnicode=true&characterEncoding=utf8
    username: root
    password: root
  jpa:
    database: MySQL
    show-sql: true
    open-in-view: true
View Code

    7.在启动类启动测试

      访问:http://localhost:9001/product/1  返回商品信息的json字符串,则商品微服务可正常访问

  服务调用:

    前文已经编写了基础的微服务,在用户下单时需要调用商品微服务获取商品数据。那应该怎么做呢?
    商品微服务提供了供别人调用的HTTP接口。所以可以在下定单的时候使用http请求的相关工具类完成,如常见的HttpClient,OkHttp,当然也可以使用Spring提供的RestTemplate
      RestTemplate介绍:

        Spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接, 我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。
        在Spring应用程序中访问第三方REST服务与使用Spring RestTemplate类有关。RestTemplate类的设计原则与许多其他Spring 模板类(例如JdbcTemplate、JmsTemplate)相同,为执行复杂任务提供了一种具有默认行为的简化方法。
        RestTemplate默认依赖JDK提供http连接的能力(HttpURLConnection),如果有需要的话也可以通过setRequestFactory方法替换为例如 Apache HttpComponents、Netty或OkHttp等其它HTTP library。
        考虑到RestTemplate类是为调用REST服务而设计的,因此它的主要方法与REST的基础紧密相连就不足为奇了,后者是HTTP协议的方法:HEAD、GET、POST、PUT、DELETE和OPTIONS。例如,RestTemplate类具有headForHeaders()、getForObject()、postForObject()、put()和delete()等方法。
      RestTemplate方法介绍:

        

  搭建订单微服务,调用商品微服务:

    1.在order_service的pom文件中引入坐标

<dependency>
    <groupId>com.fgy</groupId>
    <artifactId>common_service</artifactId>
    <version>1.0-SNAPSHOT</version>
    <scope>compile</scope>
</dependency>

    2.编写web层

/**
 * 订单控制层
 */
@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 通过订单系统,调用商品服务根据id查询商品信息
     * @param id
     * @return
     */
    @GetMapping("/buy/{id}")
    public Product findById(@PathVariable("id") Long id) {
        return restTemplate.getForObject("http://localhost:9001/product/" + id, Product.class);
    }
}
View Code

    3.配置yml文件

server:
  port: 9002
spring:
  application:
    name: order-product #服务名称
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud?useUnicode=true&characterEncoding=utf8
    username: root
    password: root
  jpa:
    database: MySQL
    show-sql: true
    open-in-view: true
View Code

    4.配置启动类

@SpringBootApplication
@EntityScan("com.fgy.common.domain")
public class OrderApplication {

    // 配置RestTemplate交给spring管理
    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }

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

服务注册与发现Eureka:https://www.cnblogs.com/roadlandscape/p/12491040.html

原文地址:https://www.cnblogs.com/roadlandscape/p/12491002.html