一、微服务
1、微服务介绍
微服务化的核心就是将传统的一站式应用,根据业务拆分成一个一个的服务,彻底地去耦合,每一个微服务提供单个业务功能的服务,一个服务做一件事,从技术角度看就是一种小而独立的处理过程,类似进程概念,能够自行单独启动或销毁,拥有自己独立的数据库。
2、微服务和微服务架构
微服务: 强调的是服务的大小,它关注的是某一个点,是具体解决某一个问题或提供落地对应服务的一个服务应用,狭意的看,可以看作Eclipse里面的一个个微服务工程或者Module
微服务架构: 是⼀种架构模式,它提倡将单⼀应⽤程序划分成⼀组小的服务,服务之间互相协调、互相配合,为⽤户提供最终价值。每个服务运⾏在其独⽴的进程中,服务与服务间采用轻量级的通信机制互相协作(通常是基于HTTP协议的RESTful API)。每个服务都围绕着具体业务进行构建,并且能够被独⽴的部署到⽣产环境、类⽣产环境等。另外,应当尽量避免统⼀的、集中式的服务管理机制,对具体的⼀个服务而言,应根据业务上下文,选择合适的语言、⼯具对其进行构建。
3、微服务优缺点
优点:
- 每个服务足够内聚,足够小,代码容易理解这样能聚焦一个指定的业务功能或业务需求
- 开发简单、开发效率提高,一个服务可能就是专一的只干一件事。
- 微服务能够被小团队单独开发,这个小团队是2到5人的开发人员组成。
- 微服务是松耦合的,是有功能意义的服务,无论是在开发阶段或部署阶段都是独立的。
- 微服务能使用不同的语言开发。
- 易于和第三方集成,微服务允许容易且灵活的方式集成自动部署,通过持续集成工具,如Jenkins, Hudson, bamboo 。
- 微服务易于被一个开发人员理解,修改和维护,这样小团队能够更关注自己的工作成果。无需通过合作才能体现价值。
- 微服务允许你利用融合最新技术。
- 微服务只是业务逻辑的代码,不会和HTML,CSS 或其他界面组件混合。
- 每个微服务都有自己的存储能力,可以有自己的数据库。也可以有统一数据库。
缺点:
- 开发人员要处理分布式系统的复杂性
- 多服务运维难度,随着服务的增加,运维的压力也在增大
- 系统部署依赖
- 服务间通信成本
- 数据一致性
二、SpringCloud概述
1、介绍
分布式微服务架构下的一站式解决方案,是各个微服务架构落地技术的集合体,俗称微服务全家桶。
SpringCloud利用SpringBoot的开发便利性巧妙地简化了分布式系统基础设施的开发,SpringCloud为开发人员提供了快速构建分布式系统的一些工具,包括 配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等 ,它们都可以用SpringBoot的开发风格做到一键启动和部署。
2、SprintBoot与SpringCloud的关系
- SpringBoot专注于快速方便的开发单个个体微服务。
- SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来,为各个微服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等集成服务。
- SpringBoot可以离开SpringCloud独立使用开发项目,但是SpringCloud离不开SpringBoot ,属于依赖的关系.
总结:SpringBoot专注于快速、方便的开发单个微服务个体,SpringCloud关注全局的服务治理框架。
3、版本对应关系
SpringBoot 和 SpringCloud 之间的依赖关系:https://spring.io/projects/spring-cloud#overview
4、版本选择
SpringBoot:2.2.2.RELEASE
SpringCloud:Hoxton.SR1
5、参考文档
官网:https://cloud.spring.io/spring-cloud-static/Hoxton.SR1/reference/htmlsingle/
中文文档:https://www.bookstack.cn/read/spring-cloud-docs/docs-index.md
6、与Dubbo的区别
Dubbo | SpringCloud | |
服务注册中心 | Zookeeper | Spring Cloud Netflix Eureka |
服务调用方式 | RPC | REST API |
服务监控 | Dubbo-monitor | Spring Boot Admin |
断路器 | 不完善 | Spring Cloud Netflix Hystrix |
服务网关 | 无 | Spring Cloud Netflix Zuul |
分布式配置 | 无 | Spring Cloud Config |
服务跟踪 | 无 | Spring Cloud Sleuth |
消息总线 | 无 | Spring Cloud Bus |
数据流 | 无 | Spring Cloud Stream |
批量任务 | 无 | Spring Cloud Task |
最大区别:SpringCloud抛弃了Dubbo的RPC通信,采用的是基于HTTP的REST方式。
严格来说,这两种方式各有优劣。虽然从一定程度上来说,后者牺牲了服务调用的性能,但也避免了上面提到的原生RPC带来的问题。而且REST相比RPC更为灵活,服务提供方和调用方的依赖只依靠一纸契约,不存在代码级别的强依赖,这在强调快速演化的微服务环境下,显得更加合适。
总结:Dubbo的定位始终是一款RPC框架。而SpringCloud的目标是微服务架构下的一站式解决方案。在面临微服务基础框架选型时Dubbo与SpringCloud只能二选一。
三、RestTemplate
1、概述
RestTemplate 提供了多种便捷访问远程 Http 服务的方法,是一种简单便捷的访问 restful 服务模板类,是Spring提供的用于访问 Rest 服务的客户端模板工具集。
2、使用
使用 restTemplate 访问 restful 接口非常的简单粗暴无脑。(url, requestMap, ResponseBean.class) 这三个参数分别代表 REST 请求地址、请求参数、HTTP响应转换被转换成的对象类型。
//get方式
restTemplate.getForObject(url+参数,返回值类型);
//post方式
restTemplate.postForObject(url,参数,返回值类型);
四、环境搭建
1、建数据库表
CREATE TABLE `payment` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`serial` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
2、新建一个Maven父工程
工程名:cloud2020
File—>New Project—>Maven(什么都不需要勾选直接Finish即可),Packageing是pom模式
1、pom.xml配置
<!--统一管理jar包版本-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>12</maven.compiler.source>
<maven.compiler.target>12</maven.compiler.target>
<junit.version>4.12</junit.version>
<lombok.version>1.18.10</lombok.version>
<log4j.version>1.2.17</log4j.version>
<mysql.version>8.0.18</mysql.version>
<druid.version>1.1.18</druid.version>
<mybatis.spring.boot.version>2.1.1</mybatis.spring.boot.version>
<fastjson.version>1.2.49</fastjson.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</dependency>
<!--spring boot 2.2.2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Hoxton.SR1-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud 阿里巴巴-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
<scope>runtime</scope>
</dependency>
<!-- druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.version}</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
3、新建一个子Module服务提供
项目名:cloud-provider-payment8001
1、配置pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
</dependencies>
2、配置application.yml
server:
port: 8001
spring:
application:
name: cloud-payment-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://47.115.85.67:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 123456
mybatis:
# 开启打印SQL
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 引入mapper.xml文件
mapperLocations: classpath:mapper/*.xml
# 别名注入
type-aliases-package: com.itan.entity
3、主启动类
package com.itan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan(basePackages = {"com.itan.dao"})//扫描mapper接口
public class Payment8001 {
public static void main(String[] args) {
SpringApplication.run(Payment8001.class,args);
}
}
4、实体类
package com.itan.eneity;
import lombok.Data;
import java.io.Serializable;
@Data
public class Payment implements Serializable {
private Integer id;
private String serial;
}
5、返回类CommonResult
package com.itan.common;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> implements Serializable {
/**状态码**/
private String code;
/**返回消息**/
private String message;
/**返回数据**/
private T data;
/**返回成功方法**/
public static CommonResult success(Object data) {
return new CommonResult("200","success",data);
}
}
6、dao接口
package com.itan.dao;
import com.itan.eneity.Payment;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
@Repository
public interface PaymentMapper {
/**
* 根据id获取payment信息
* @param id
* @return
*/
Payment getOne(@Param("id") Integer id);
}
7、mapper.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.itan.dao.PaymentMapper">
<resultMap id="PaymentMapper" type="com.itan.eneity.Payment">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="serial" property="serial" jdbcType="VARCHAR"/>
</resultMap>
<sql id="Base_Column_List">
id, serial
</sql>
<select id="getOne" resultMap="PaymentMapper" parameterType="java.lang.Integer">
select <include refid="Base_Column_List"/> from payment where id = #{id,jdbcType=INTEGER}
</select>
</mapper>
8、service接口和实现类
package com.itan.service;
import com.itan.eneity.Payment;
public interface PaymentService {
/**
* 根据id获取信息
* @param id
* @return
*/
Payment getOne(Integer id);
}
package com.itan.service.impl;
import com.itan.dao.PaymentMapper;
import com.itan.eneity.Payment;
import com.itan.service.PaymentService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class PaymentServiceImpl implements PaymentService {
@Resource
private PaymentMapper paymentMapper;
@Override
public Payment getOne(Integer id) {
return paymentMapper.getOne(id);
}
}
9、controller类
package com.itan.controller;
import com.alibaba.fastjson.JSON;
import com.itan.common.CommonResult;
import com.itan.eneity.Payment;
import com.itan.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("payment")
public class PaymentController {
@Autowired
private PaymentService paymentService;
@PostMapping("getOne")
public CommonResult getOne(@RequestBody Payment payment){
log.info("入参:" + JSON.toJSONString(payment));
CommonResult result = CommonResult.success(paymentService.getOne(payment.getId()));
log.info("出参:" + JSON.toJSONString(result));
return result;
}
}
10、启动测试
http://localhost:8001/payment/getOne
4、新建一个子Module服务消费
项目名:cloud-consumer-order80
1、配置pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
</dependencies>
2、配置application.yml
server:
port: 80
3、主启动类
package com.itan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Consumer80 {
public static void main(String[] args) {
SpringApplication.run(Consumer80.class,args);
}
}
4、将返回类和实体类复制到此工程下
5、配置RestTemplate
package com.itan.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ApplicationContextConfig {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
6、创建消费者REST风格接口
package com.itan.controller;
import com.alibaba.fastjson.JSON;
import com.itan.common.CommonResult;
import com.itan.entity.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@Slf4j
@RestController
@RequestMapping("consumer")
public class OrderController {
private static final String PAYMENT_URL = "http://localhost:8001/";
@Resource
private RestTemplate restTemplate;
@PostMapping("getOne")
public CommonResult getOne(@RequestBody Payment payment){
log.info("入参:" + JSON.toJSONString(payment));
CommonResult result = restTemplate.postForObject(PAYMENT_URL + "payment/getOne", payment, CommonResult.class);
log.info("出参:" + JSON.toJSONString(result));
return result;
}
}
7、测试
1、先启动 cloud-provider-payment8001 项目
2、再启动 cloud-consumer-order80 项目
3、http://localhost:80/consumer/getOne
5、新建一个子Module公共类
项目名:cloud-api-commons
1、配置pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
2、将entity包和common包中类全部复制到此工程下
3、删掉其他工程中的entity和common包
4、在其他工程的pom文件中引入cloud-api-commons即可