转载请注明来源
https://blog.csdn.net/SingingFisher/article/details/88660952
1、前言
大家好,我是脚气哥!作为一个只会ctrl c、crl v的菜逼,我将带领众多菜逼一起学习SpringCloud!
项目地址:https://gitee.com/SiningFish/zed ,大家可以前往查看。如果觉得讲的知识有帮助,希望可以给我点个star哦。
推荐图书
- 《Spring Cloud微服务架构开发实战》
- 《Spring Cloud与Docker微服务架构实战》
2、项目简介
项目结构参考了pig项目,不过pig文档收费,我实在是舍不得为了一个文档出600多块钱,有这闲钱我直接多买几本书不是美滋滋。这也是我写这篇教程的原因之一,记录一下自己学习SpringCloud的历程,也希望可以帮助到其他人,毕竟,一个小白来学习SpringCloud本身就是一脸懵逼,再去看一个没有文档的大项目,那更是懵逼2。
作为一名LOL最强王者5选手,我选择以我32%胜率的、最喜欢的英雄 劫 --zed 来给我们的项目命名。
无形装逼,最为致命! ----影流之主·劫
2.1 项目主要依赖
依赖 | 版本 |
---|---|
SpringBoot | 2.1.3.RELEASE |
SpringCloud | Greenwich.SR1 |
2.2 开发工具
IDEA
2.3 面向谁
由于我刚学SpringCloud的时候,也就只会一点Spring,AOP都不懂什么意思,SpringBoot也就知道怎么创建项目,所以这篇教程还是比较简单的,面向和我一样的小白菜逼。
3、知识点与注意点
3.1 eureka注册中心
- eureka注册中心,作为eureka的服务器,它通过hashmap维护了注册到它上面的微服务们。
- 可以把它想象成一个映射表,记录了微服务的名称和具体URL地址,微服务可以通过这个信息来互相调用。
- 如果没有注册中心,当然也能互相调用,不过想象一下,2个微服务互相调用,就要记住彼此的url,100个呢?1000个呢?这么多不得把人烦死,干什么程序员,回去卖馒头不一样能赚钱。。。
- 它通过各种机制,例如心跳检测、自我保护等等保障了运行。具体可以买书看,或者上网查。
3.2 服务提供者
- 提供服务的微服务,通过注册到eureka上给服务消费者使用
3.3 服务消费者
- 消费服务的微服务
3.3 提供者与消费者的联系
- 一个微服务可以同时作为消费者和提供者存在。例如B消费A,同时B提供给C消费。
- 服务提供者必须注册到eureka服务器上,而消费者则不一定需要,就像eureka服务器本身一样,如果不做eureka集群,那么eureka本身是不需要注册到eureka上的
3.4 负载均衡
- 很好理解,一个user服务,可以失效无法服务,多开几个user服务,端口不同,甚至是ip不同,那么一个坏了其他的仍然可以提供服务。
4、创建项目
你可以直接把我的gitee上代码clone下来,也可以自己创建。本文档对应a1分支,下载直接用https://gitee.com/SiningFish/zed/tree/a1/
,然后用IDEA打开就可以了。下面将以直接自己创建的方式来讲解。
4.1创建父工程
直接IDEA创建一个普通的maven项目(建议刚学习不要选啥杂七杂八乱七八糟的依赖,缺啥自己填啥吧),我这里命名为zed。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.origin</groupId>
<artifactId>zed</artifactId>
<version>1.0-SNAPSHOT</version>
<name>${project.artifactId}</name>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<spring-boot.version>2.1.3.RELEASE</spring-boot.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
<spring-cloud-ribbon.version>1.3.2.RELEASE</spring-cloud-ribbon.version>
<mybatis-spring.version>1.3.2</mybatis-spring.version>
</properties>
<dependencies>
<!--eureka客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!--springboot 测试依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>${project.name}</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<target>${maven.compiler.target}</target>
<source>${maven.compiler.source}</source>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<finalName>${project.build.finalName}</finalName>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
稍微讲一下吧。
- 所有子模块需要公用的或者常用的依赖项版本都在父pom文件中定义,方便以后统一调整
- 两个plugin一个是maven编译插件,一个是springboot插件,没啥好说的。
dependencyManagement
中定义了springboot和springcloud的通用依赖,这样dependencies
以及子模块中的dependencies
中的依赖项,如果在spring-boot-dependencies
和spring-cloud-dependencies
已经有了的,就不用再指定版本了,不在的仍然要指定版本。- 由于每个模块都是一个eureka客户端,所有这个父pom中定义了
spring-cloud-starter-netflix-eureka-client
依赖项。 lombok
是一个非常好用的简化代码插件和依赖,除了在pom中声明它的依赖,还要在IDEA中安装一下lombok插件,具体网上搜一下,是很简单的。lombok稍微去网上查一下用法,也是非常简单的,举例来说,你原本写个bean要写它的构造函数,现在你只要在类前面加个lombok的@AllArgsConstructor
注解,就不需要写构造函数了,到时候编译的时候会自动生成。比如,我的一个类,源码是这样的:
@RestController
@RequestMapping("/auth")
@AllArgsConstructor
public class AuthController {
private UserService userService;
//......
}
没有构造函数。它编译之后就成了这样:
@RestController
@RequestMapping({"/auth"})
public class AuthController {
private UserService userService;
public AuthController(UserService userService) {
this.userService = userService;
}
//......
}
很流弊对吧,由于构造函数自动注入,甚至UserService
都不要@Autowired
了。
4.2 创建eureka服务器
直接在zed项目上右键,创建一个新的普通maven模块zed-eureka就好了。
4.2.1 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>zed</artifactId>
<groupId>com.origin</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>zed-eureka</artifactId>
<packaging>jar</packaging>
<description>eureka注册服务中心</description>
<dependencies>
<!--eureka注册服务中心-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
真简单啊,到时候maven导入依赖之后,zed-eureka
除了有父pom中定义的那些依赖之外,还有spring-cloud-starter-netflix-eureka-server
这个依赖,说明它是一个eureka服务器。
4.2.2 bootstrap.yml
文件
server:
port: 8762 #端口号
spring:
application:
name: zed-eureka # 应用名
eureka:
instance:
hostname: ${spring.application.name}
# hostname名,通常是localhost或者主机地址,这里直接用的zed-eureka,是因为后面要配置hosts文件,具体后面再看
prefer-ip-address: true # 以IP注册到eureka服务器上(因为eureka服务器自己也同时是个eureka客户端)
client:
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ # eureka服务器地址
register-with-eureka: false #不需要注册到eureka的可用服务列表里面,只需要简单的注册上就可以了
fetch-registry: false # 不需要从eureka服务器上拉取可用服务列表,因为本身它就有了
server:
eviction-interval-timer-in-ms: 4000 #40秒钟踢出关闭的微服务
enable-self-preservation: false #关闭eureka自我保护
4.2.3 主程序
@EnableEurekaServer
@SpringBootApplication
public class ZedEurekaApplication {
public static void main(String args[]){
SpringApplication.run(ZedEurekaApplication.class, args);
}
}
更加简单了,只不过是在原本的@SpringBootApplication
启动注解上又加了一个@EnableEurekaServer
注解,表示它是一个eureka服务器。现在已经可以直接运行eureka服务器了,运行完毕之后浏览器访问localhost:8762(端口号在bootstrap.yml
中配置的),看到如下画面说明eureka服务器成功:
4.3 创建服务提供者
直接在zed项目上右键,创建一个新的普通maven模块zed-service-user就好了。
4.2.1 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>zed</artifactId>
<groupId>com.origin</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>zed-service-user</artifactId>
<packaging>jar</packaging>
<description>zed 用户服务</description>
<dependencies>
<!--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>
<version>${mybatis-spring.version}</version>
</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>
加了mybatis的依赖以及mysql的驱动包。
4.2.2 bootstrap.yml
文件
server:
port: 20000
spring:
application:
name: zed-service-user
eureka:
instance:
hostname: ${spring.application.name}
prefer-ip-address: true
instance-id: ${eureka.instance.hostname}:${server.port}
client:
service-url:
defaultZone: http://zed-eureka:8762/eureka/
4.2.3 application.yml
文件
#mybatis配置
mybatis:
mapper-locations: classpath:mapper/*.xml
#数据库配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/zed?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
username: root
password: root
配置了数据库信息以及mybatis的映射文件地址信息。
bootstrap.yml将会先于application.yml加载,就目前而言这样分成两个配置文件是多余的,不过后面用处就大了。
4.2.4 其他通用代码
代码太多了我就不贴了,贴了占篇幅太大,而且都是些通用的东西,大家直接拷贝我的源码下来对照着看就好了。无非也就是些增删改查的东西。我直接讲一下目录结构就好了。
common
:统一定义的常量类Constant
:接口,里面放的是controller返回值的自定义码。比如Integer SUCCESS=1
定义了成功返回时的自定义码Message
: 接口,定义了返回的消息,如"登录成功!"
controller
:控制器UserController
: 用户实体类相关控制器
domain
:实体类User
:用户类
dto
:数据传输对象UserDto
:User
对应的dtoResult
:封装的统一返回对象,包含了自定义返回码code
,消息msg
,值data
三个属性。到时候就不用这个controller返回User,那个controller返回Student了,全部弄成统一的,你看了也舒服,前端看了也舒服,大家都美滋滋的,省的成天提心吊胆,担心自己写的接口太烂了,被前端打。
mapper
:mybatis实体类对应的mapperUserMapper
:User
对应的mapper
service
:UserService
和UserServiceImpl
:用户Service
resources/mapper/UserMapper.xml
:mapper对应的xml文件resources/application.xml
:已说明resources/banner.txt
:横幅resources/bootstrap.yml
:已说明
4.2.5 主程序
@EnableEurekaClient
@SpringBootApplication
@MapperScan("com.origin.zed.service.user.mapper") //指定mybatis的mapper接口地址
public class ZedUserServiceApplication {
public static void main(String args[]){
SpringApplication.run(ZedUserServiceApplication.class, args);
}
}
4.3 创建服务消费者
直接在zed项目上右键,创建一个新的普通maven模块zed-service-consumer就好了。
4.3.1 pom.xml
文件
不再累述了,只是添加了一个
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>${spring-cloud-ribbon.version}</version>
</dependency>
ribbon依赖。由于父pom中的spring-cloud-dependencies
没有ribbon,所以需要在父pom中指定ribbon的版本
<spring-cloud-ribbon.version>1.3.2.RELEASE</spring-cloud-ribbon.version>
ribbon可以用来做负载均衡,到时候可以开多个服务提供者,服务消费者调用服务提供者时,将轮流访问各个服务提供者的实例。
4.3.2 bootstrap.yml
文件
不再累述,实在是简单
4.3.3 其他通用代码
common
和dto
:同服务提供者中的定义,可以直接写在一个子模块中,然后其他需要用到的子模块都依赖一下这个模块。现在暂时无所谓的ConsumereConfig
:定义了用来调用服务提供者的RestTemplate
bean
@Configuration
public class ConsumerConfig {
@LoadBalanced //使用负载均衡
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
ConsumerController
:控制器,本身没有任何值得讲的点,注意一下通过RestTemplate
调用zed-service-user
服务的方法:
@RestController
@RequestMapping("/consumer")
@AllArgsConstructor
public class ConsumerController {
private RestTemplate restTemplate;
@GetMapping("/user/{id}")
public Result queryById(@PathVariable("id") Long id){
return restTemplate.getForEntity("http://ZED-SERVICE-USER/user/{id}", Result.class, id).getBody();
}
}
其中的
restTemplate.getForEntity(
"http://ZED-SERVICE-USER/user/{id}",
//ZED-SERVICE-USER为user服务在eureka上注册名的大写,可以通过访问eureka的/apps API查看(http://localhost:8762/eureka/apps)
Result.class, //返回类型的class
id) //参数
.getBody();
4.3.4 主程序
@EnableEurekaClient
@SpringBootApplication
public class ZedConsumerServiceApplication {
public static void main(String args[]){
SpringApplication.run(ZedConsumerServiceApplication.class, args);
}
}
平淡无奇。
5、数据库
5.1 导入
导入db目录下的zed.sql文件。数据库端口为默认的3306,用户名密码均为root。当然这都是可以随便更改的,只要项目中配置文件对应就好了。
5.2 表
5.2.1 zed_user 用户信息表
其他的暂时不需要
6、运行
6.1 运行
- 运行eureka服务器
- 运行服务提供者
zed-service-user
- 修改一下
zed-service-user
中bootstrap.xml
文件中定义的server.port
端口号,再次运行一个zed-service-user
实例。再运行100个也无所谓,运行两个就能看到负载均衡的效果了。 - 运行服务消费者
zed-service-consumer
6.2 eureka界面
可以看到ZED-SERVICE-USER
启动了两个实例。
7、测试
7.1 直接访问ZED-SERVICE-USER
7.2 通过ZED-SERVICE-CONSUMER多次访问
- 第一次
- 第二次
7.3 结论
多次访问可以看到,消费者是轮流调用生产者的不同实例的,做到了负载均衡。
8、欢迎提问
转载请注明来源
https://blog.csdn.net/SingingFisher/article/details/88660952