目录
前言
Spring Cloud 是一套完整的微服务解决方案,基于 Spring Boot 框架,准确的说,它不是一个框架,而是一个大的容器,它将市面上较好的微服务框架集成进来,从而简化了开发者的代码量。
和Dubbo的比较
springcloud的介绍
spring cloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等。它运行环境简单,可以在开发人员的电脑上跑。
目前,国内使用 Spring Cloud 技术的公司并不多见,不是因为 Spring Cloud 不好,主要原因有以下几点:
- Spring Cloud 中文文档较少,出现问题网上没有太多的解决方案。
- 国内创业型公司技术老大大多是阿里系员工,而阿里系多采用 Dubbo 来构建微服务架构。
- 大型公司基本都有自己的分布式解决方案,而中小型公司的架构很多用不上微服务,所以没有采用 Spring Cloud 的必要性。
其主要优点有:
- 集大成者,Spring Cloud 包含了微服务架构的方方面面。
- 约定优于配置,基于注解,没有配置文件。
- 轻量级组件,Spring Cloud 整合的组件大多比较轻量级,且都是各自领域的佼佼者。
- 开发简便,Spring Cloud 对各个组件进行了大量的封装,从而简化了开发。
- 开发灵活,Spring Cloud 的组件都是解耦的,开发人员可以灵活按需选择组件。
springcloud的maven父容器创建
在创建一个快速的maven项目
选择好maven仓库后加入下面;
配置总的一个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.liwangwang</groupId>
<artifactId>springcloud</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<!--
起到依赖版本控制的作用
父工程是一个maven项目,一般创建方式即可,父工程的主要用途是锁定pom依赖包版本。
-->
<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>
<druid.version>1.1.10</druid.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Edgware.SR4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.13.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
springcloude的公共模块创建
提醒一下,我们本次使用的是对象关系映射框架jpa。
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--保持使用版本的一致1.0-SNAPSHOT-->
<parent>
<groupId>com.liwangwang</groupId>
<artifactId>springcloud</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>microservice-common</artifactId>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--处理web请求-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--test测试的包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--使用的数据库关系映射框架是jpa-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--使用的是mysql数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
暂时我们所用到的实体类
Student实体类
package com.liwangwang.microservicecommon.entity;
import javax.persistence.*;
import java.io.Serializable;
@Entity
@Table(name="t_springcloud_student")
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private Integer id;
@Column(length=50)
private String name;
@Column(length=50)
private String grade;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGrade() {
return grade;
}
public void setGrade(String grade) {
this.grade = grade;
}
}
Eureka的服务注册中心(server)
创建一个springboot模块
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--保持使用版本的一致1.0-SNAPSHOT-->
<parent>
<groupId>com.liwangwang</groupId>
<artifactId>springcloud</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>microservice-eureka-server-2001</artifactId>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- eureka是一个服务注册,服务发现框架基于rset的服务,这个是服务注册中心-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 修改后立即生效,热部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
yml文件
server:
port: 2001
context-path: /
eureka:
instance:
hostname: localhost #eureka注册中心实例名称
client:
register-with-eureka: false #false 由于该应用为注册中心,所以设置为false,代表不向注册中心注册自己。
fetch-registry: false #false 由于注册中心的职责就是维护服务实例,它并不需要去检索服务,所以也设置为false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置与Eureka注册中心交互的地址,查询服务和注册服务用到
开启Eureka服务@EnableEurekaServer
package com.liwangwang.microserviceeurekaserver2001;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class MicroserviceEurekaServer2001Application {
public static void main(String[] args) {
SpringApplication.run(MicroserviceEurekaServer2001Application.class, args);
}
}
Eureka的服务注册(client)
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--保持使用版本的一致1.0-SNAPSHOT-->
<parent>
<groupId>com.liwangwang</groupId>
<artifactId>springcloud</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>microservice-student-provider-1001</artifactId>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--相当于全局的一个依赖关系,这个导入能确保整个项目使用的包版本一致
比如全局中的: spring-cloud-dependencies
spring-boot-dependencies
druid-spring-boot-starter
-->
<dependency>
<groupId>com.liwangwang</groupId>
<artifactId>microservice-common</artifactId>
</dependency>
<!--处理web请求-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--test测试的包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--使用的数据库关系映射框架是jpa-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--使用的是mysql数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--使用tomcat-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<!--druid数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!-- 修改后立即生效,热部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!--需要引入公共模块的实体类等(在导入的时候出现)-->
<dependency>
<groupId>com.liwangwang</groupId>
<artifactId>microservice-common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<!--添加注册中心Eureka相关配置,就是说这个是客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!-- actuator监控引入,点击后的追责 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
yml文件
server:
port: 1001
context-path: /
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/context?useUnicode=true&characterEncoding=utf8
username: root
password: 123
jpa:
hibernate:
ddl-auto: update
show-sql: true
eureka:
instance:
hostname: localhost #eureka客户端主机实例名称
appname: microservice-student #客户端服务名
instance-id: microservice-student:1001 #客户端实例名称
prefer-ip-address: true #显示IP
client:
service-url:
defaultZone: http://localhost:2001/eureka #把服务注册到eureka注册中心
info:
groupId: com.liwangwang.springcloud
artifactId: microservice-student-provider-1001
version: 1.0-SNAPSHOT
userName: http://liwangwang.com
phone: 123456
开启Eureka客户端服务@EnableEurekaClient
package com.liwangwang.microservicestudentprovider1001;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EntityScan("com.liwangwang.*.*")
@EnableEurekaClient
@SpringBootApplication
public class MicroserviceStudentProvider1001Application {
public static void main(String[] args) {
SpringApplication.run(MicroserviceStudentProvider1001Application.class, args);
}
}
重点文件:Controller文件
package com.liwangwang.microservicestudentprovider1001.controller;
import com.liwangwang.microservicecommon.entity.Student;
import com.liwangwang.microservicestudentprovider1001.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/student")
public class StudentProviderController {
@Autowired
private StudentService studentService;
@PostMapping(value="/save")
public boolean save(Student student){
try{
studentService.save(student);
return true;
}catch(Exception e){
return false;
}
}
@GetMapping(value="/list")
public List<Student> list(){
return studentService.list();
}
@GetMapping(value="/get/{id}")
public Student get(@PathVariable("id") Integer id){
return studentService.findById(id);
}
@GetMapping(value="/delete/{id}")
public boolean delete(@PathVariable("id") Integer id){
try{
studentService.delete(id);
return true;
}catch(Exception e){
return false;
}
}
}
消费者
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--保持使用版本的一致1.0-SNAPSHOT-->
<parent>
<groupId>com.liwangwang</groupId>
<artifactId>springcloud</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>microservice-student-consumer-80</artifactId>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--相当于全局的一个依赖关系,这个导入能确保整个项目使用的包版本一致
比如全局中的: spring-cloud-dependencies
spring-boot-dependencies
druid-spring-boot-starter
-->
<dependency>
<groupId>com.liwangwang</groupId>
<artifactId>microservice-common</artifactId>
</dependency>
<!--处理web请求-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--test测试的包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--使用的数据库关系映射框架是jpa-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--使用的是mysql数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--使用tomcat-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<!-- 修改后立即生效,热部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!--需要引入公共模块的实体类等(在导入的时候出现)-->
<dependency>
<groupId>com.liwangwang</groupId>
<artifactId>microservice-common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
yml文件
server:
port: 80
context-path: /
因为这个模块不需要用到数据源的使用,所以就忽略报错就行
package com.liwangwang.microservicestudentconsumer80;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class MicroserviceStudentConsumer80Application {
public static void main(String[] args) {
SpringApplication.run(MicroserviceStudentConsumer80Application.class, args);
}
}
重点文件:StudentConsumerController
package com.liwangwang.microservicestudentconsumer80.controller;
import com.liwangwang.microservicecommon.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@RestController
@RequestMapping("/student")
public class StudentConsumerController {
private final static String SERVER_IP_PORT = "http://localhost:1001";
@Autowired
private RestTemplate restTemplate;
@PostMapping(value="/save")
private boolean save(Student student){
return restTemplate.postForObject(SERVER_IP_PORT+"/student/save", student, Boolean.class);
}
@GetMapping(value="/list")
public List<Student> list(){
return restTemplate.getForObject(SERVER_IP_PORT+"/student/list", List.class);
}
@GetMapping(value="/get/{id}")
public Student get(@PathVariable("id") Integer id){
return restTemplate.getForObject(SERVER_IP_PORT+"/student/get/"+id, Student.class);
}
@GetMapping(value="/delete/{id}")
public boolean delete(@PathVariable("id") Integer id){
try{
restTemplate.getForObject(SERVER_IP_PORT+"/student/delete/"+id, Boolean.class);
return true;
}catch(Exception e){
return false;
}
}
}
测试
开启服务提供者模块和消费者模块
http://localhost/student/list (从消费者访问)
http://localhost:1001/student/list (从服务提供者直接访问)
服务注册中心
http://localhost:2001/
点击后的效果
后记
在我们的本次的项目案例中我们能得到的资料可知道
一、聊一下
我们以前都是使用的都是单机项目,笼统的说就是所有的东西都在一个整体项目中, 那么两者之间有什么区别呢?
以前的单机项目的优点有开发简便,部署方便,硬要说缺点的话就是对于分布式项目来说的话耦合度就太高了,每个人都是开发一个同一个项目,使用的文件都可能有所差异,所以在开发过程中开发人员可能空间距离就不易太远了(更好讨论)。那么分布式项目优点就在于它里面的每个模块都可以分为不同的子项目,那么对于耦合度的话就大大的解耦了。而且在每个子项目中每个写子项目的人都可以用自己不同的插件和文件格式,这个的自由度就非常高了,缺点就在于难部署,配置文件会麻烦一点。
二、子项目结构
简单的说下本次结构:common(公共模块)
consumer(消费者)
Eureka Server(服务注册中心)[Eureka服务端]
provider(服务提供者)[Eureka客户端]
1、父容器:所有的子项目都放到里面
2、common(公共模块): 所有的一些工具类和实体类都放到里面,调用还是可以调用到
3、consumer(消费者): 所有的配置没多少,就是用来模拟客户端的,但是要注意要加上忽略数据源的配置,否则会报错
4、provider(服务提供者)[Eureka客户端]: 所有的服务请求都再次进行一个处理,同时当在Eureka服务端注册过后就可以被其管理。
5、Eureka Server(服务注册中心)[Eureka服务端]: 服务注册中心,可以管理所有注册在内的服务子项目。
Run Dashboard的一个配置