SpringCloud從看不懂到放棄,第一章
內容簡述:
1、Springcloud入門概述
2、Rest微服務構建案例工程
3、服務註冊與發現Eureka
4、Ribbon負載均衡
5、Feign負載均衡
6、Hystrix斷路器
7、Zuul路由網關
8、SpringCloud Config分佈式配置中心
一、SpringCloud入門概述
1、什麼是微服務
提倡將單一的應用程序劃分成一組組小的服務。每個服務運行在其獨立的自己的進程中。服務間互相協調、互相配合。
服務之間採用輕量級的通訊機制互相溝通(dubbo是RPC、SpringCloud是基於HTTP的restful api)。
每個服務都圍繞着具體的業務進行構建,都能部署到獨立的生產環境中。
(根據業務拆分成一個個的服務,徹底的去耦合)
2、微服務的優缺點是什麼?以及在項目開發中碰到的坑
優點:
每一個服務專注聚焦於一個指定的業務功能和需求
鬆解耦的
各服務間可以用不同的語言
前後端分離
靈活搭配的數據庫:自己的數據庫+統一的公共數據庫
缺點:
服務間通訊成本增加
數據一致性
運維難度增加等
3、微服務的技術棧有哪些
服務開發 springboot、spring、springmvc等
服務配置與管理 Netflix公司的Archaius、阿里的Diamond
服務註冊與發現 Eureka、Consul、zookeeper
服務調用 Rest、RPC、gRPC
服務熔斷器 Hystrix(dashboard服務監控)、Envoy
負載均衡 Ribbon、Nginx
服務接口調用 Feign
消息隊列 kafka、RabbitMq、ActiveMq
服務配置中心管理 SpringCloudConfig、Chef
服務路由 Zuul
服務監控 Zabbix、Nagios、Metrics、Spectator
全鏈路追蹤 Zipkin、Brave、Dapper
服務部署 Docker、Openstack、Kubernetes
數據流操作開發包 SpringCloud Stream(封裝與Redis\Rabbit\kafka等發送接收消息)
事件消息總線 SpringCloud Bus
4、springcloud和dubbo有哪些區別
Dubbo SpringCloud
註冊中心 zookeeper Eureka
調用方式 RPC REST API
服務監控 Dubbo-monitor SpringBoot Admin
斷路器 ------- Hystrix
服務網管 Zuul
分佈式配置 SpringCloud config
服務跟蹤 SpringCloud Sleuth
消息總線 SpringCloud Bus
數據流 SpringCloud stream
批量任務 SpringCloud Task
。。。。 。。。。。。。 。。。。。。。
dubbo服務治理
官網
https://spring.io/projects/spring-cloud
https://springcloud.cc 中文社區
https://springcloud.cn 中文官網
二、Rest微服務構建案例工程
以Dept部門模塊做一個微服務通用案例、Consumer消費者[client]通過rest調用Provider提供的服務
結構
cloud:
cloud-api 封裝整體entity、接口和 公共配置等
cloud-provider-dept-8001 微服務的服務提供者
cloud-consumer-dept-80 微服務的服務消費者
1、父工程
new maven project
groupID com.lee
artifact id cloud
packaging pom
POM
<?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.lee</groupId>
<artifactId>cloud</artifactId>
<version>1.0-SNAPSHOT</version>
<!--重要POM-->
<packaging>pom</packaging>
<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>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.16.18</lombok.version>
</properties>
<dependencyManagement>
<dependencies>
<!--cloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--SpringBoot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.9.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.4</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.31</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
2、cloud-api公共子模塊
new maven module
moduleName cloud-api
parentProject cloud
groupId com.lee
artifactId cloud-api
packaging jar
創建完成後 父工程POM文件會多了個標籤
POM
<?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>cloud</artifactId>
<groupId>com.lee</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-api</artifactId>
<dependencies>
<!-- 當前Module需要用到的jar包,按自己需求添加,
如果父類已經包含了,可以不用寫版本號 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
Entity
[ 微服務,一定要實現序列化 ]
package com.lee.cloud.entity;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@ToString
@Accessors(chain = true)
@NoArgsConstructor
public class Dept implements Serializable {
private static final long serialVersionUID = 5051248965243297270L;
private Long deptno; //主鍵
private String dname; //部門名稱
private String db_source;//來自那個數據庫,因爲微服務架構可以一個服務對應一個數據庫,同一個信息被存儲到不同數據庫
public Dept(String dname) {
this.dname = dname;
}
}
3、cloud-provider-dept-8001生產者
部門微服務提供者
new maven module
moduleName cloud--provider-dept-8001
parentProject cloud
groupId com.lee
artifactId cloud--provider-dept-8001
packaging jar
POM
<?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>cloud</artifactId>
<groupId>com.lee</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud--provider-dept-8001</artifactId>
<dependencies>
<!-- 引入自己定義的api通用包,可以使用Dept部門Entity -->
<dependency>
<groupId>com.lee</groupId>
<artifactId>cloud-api</artifactId>
<version>${project.version}</version>
</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>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- 修改後立即生效,熱部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
application.yml
server:
port: 8001
mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路徑
type-aliases-package: com.lee.cloud.entity # 所有Entity別名類所在包
mapper-locations:
- classpath:mybatis/mapper/**/*.xml # mapper映射文件
spring:
application:
name: cloud-dept
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 當前數據源操作類型
driver-class-name: org.gjt.mm.mysql.Driver # mysql驅動包
url: jdbc:mysql://localhost:3306/cloudDB01 # 數據庫名稱
username: root
password: 123456
dbcp2:
min-idle: 5 # 數據庫連接池的最小維持連接數
initial-size: 5 # 初始化連接數
max-total: 5 # 最大連接數
max-wait-millis: 200 # 等待連接獲取的最大超時時間
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="cacheEnabled" value="true"/><!-- 二級緩存開啓 -->
</settings>
</configuration>
mysql
DROP DATABASE IF EXISTS cloudDB01;
CREATE DATABASE cloudDB01 CHARACTER SET UTF8;
USE cloudDB01;
CREATE TABLE dept
(
deptno BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
dname VARCHAR(60),
db_source VARCHAR(60)
);
INSERT INTO dept(dname,db_source) VALUES('開發部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('人事部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('財務部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('市場部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('運維部',DATABASE());
SELECT * FROM dept;
接口:dao\mapper\service\controller\
DAO:
package com.lee.cloud.dao;
import com.lee.cloud.entity.Dept;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* springboot整合mybatis
* 第一種方法:在dao上加@Mapper
* 第二種方法:在啓動類上加@MapperScan
*/
@Mapper
public interface DeptDao {
public boolean addDept(Dept dept);
public Dept findById(Long id);
public List<Dept> findAll();
}
------------------------------------------------------------
MAPPER
<?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.lee.cloud.dao.DeptDao">
<select id="findById" resultType="Dept" parameterType="Long">
select deptno,dname,db_source from dept where deptno=#{deptno};
</select>
<select id="findAll" resultType="Dept">
select deptno,dname,db_source from dept;
</select>
<insert id="addDept" parameterType="Dept">
INSERT INTO dept(dname,db_source) VALUES(#{dname},DATABASE());
</insert>
</mapper>
----------------------------------------------------------------------
SERVICE
package com.lee.cloud.service;
import com.lee.cloud.entity.Dept;
import java.util.List;
public interface DeptService {
public boolean add(Dept dept);
public Dept get(Long id);
public List<Dept> list();
}
--------------------------------------------------------------------------
SERVICE IMPL
package com.lee.cloud.service.impl;
import com.lee.cloud.dao.DeptDao;
import com.lee.cloud.entity.Dept;
import com.lee.cloud.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptDao dao ;
@Override
public boolean add(Dept dept)
{
return dao.addDept(dept);
}
@Override
public Dept get(Long id)
{
return dao.findById(id);
}
@Override
public List<Dept> list()
{
return dao.findAll();
}
}
----------------------------------------------------------------------
CONTROLLER
package com.lee.cloud.controller;
import com.lee.cloud.entity.Dept;
import com.lee.cloud.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
public class DeptController {
@Autowired
private DeptService service;
@RequestMapping(value="/dept/add",method= RequestMethod.POST)
public boolean add(@RequestBody Dept dept)
{
return service.add(dept);
}
@RequestMapping(value="/dept/get/{id}",method=RequestMethod.GET)
public Dept get(@PathVariable("id") Long id)
{
return service.get(id);
}
@RequestMapping(value="/dept/list",method=RequestMethod.GET)
public List<Dept> list()
{
return service.list();
}
}
主啓動類APP
package com.lee.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DeptProvider8001_APP {
public static void main(String[] args) {
SpringApplication.run(DeptProvider8001_APP.class,args);
}
}
測試:
http://localhost:8001/dept/list
結果:
[{"deptno":1,"dname":"開發部","db_source":"clouddb01"},
{"deptno":2,"dname":"人事部","db_source":"clouddb01"},
{"deptno":3,"dname":"財務部","db_source":"clouddb01"},
{"deptno":4,"dname":"市場部","db_source":"clouddb01"},
{"deptno":5,"dname":"運維部","db_source":"clouddb01"}]
3、cloud-consumer-dept-80 消費者
部門微服務消費者
new maven module
moduleName cloud--consumer-dept-80
parentProject cloud
groupId com.lee
artifactId cloud--consumer-dept-80
packaging jar
POM
<?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>cloud</artifactId>
<groupId>com.lee</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-consumer-dept-80</artifactId>
<description>部門微服務消費者</description>
<dependencies>
<dependency><!-- 自己定義的api -->
<groupId>com.lee</groupId>
<artifactId>cloud-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 修改後立即生效,熱部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>
APPLICATION.YML
server:
port: 80
configBean配置類
package com.lee.cloud.cfgbean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
//配置類
@Configuration
public class ConfigBean {
//RestTemplate提供了多種便捷訪問遠程HTTP服務的方法
//是一種簡單便捷的訪問restful服務模板類,是spring提供的用於訪問Rest服務的客戶端模板工具集
//類似JDBCTemplate RedisTemplate等
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
RestTemplate提供了多種便捷訪問遠程HTTP服務的方法
是一種簡單便捷的訪問restful服務模板類,是spring提供的用於訪問Rest服務的客戶端模板工具集
類似JDBCTemplate RedisTemplate等
controller
package com.lee.cloud.controller;
import com.lee.cloud.entity.Dept;
import org.springframework.beans.factory.annotation.Autowired;
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;
import java.util.List;
@RestController
public class DeptController_Consumer {
private static final String REST_URL_PREFIX = "http://localhost:8001";
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value="/consumer/dept/add")
public boolean add(Dept dept)
{
return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add", dept, Boolean.class);
}
@RequestMapping(value="/consumer/dept/get/{id}")
public Dept get(@PathVariable("id") Long id)
{
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id, Dept.class);
}
@RequestMapping(value="/consumer/dept/list")
public List<Dept> list()
{
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list", List.class);
}
}
啓動類:
package com.lee.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DeptConsumer80_App {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer80_App.class,args);
}
}
測試:
1、啓動provider服務,再啓動consumer服務
2、http://localhost/consumer/dept/list
3、http://localhost/consumer/dept/get/1
4、http://localhost/consumer/dept/add?dname=風控部