为什么使用springcloud呢??
最开始我们用的都是单一架构(all in one),为什么会演变成垂直架构应用(vertical application)呢,由于我们最开始的用户本来就少,10几年前20年前貌似电脑没有多少人家有的把,网页也都是静态页面,访问量根本不用担心,而且所有业务都在同一里面,当我们修改了一个地方,哪怕仅仅是一个页面的一个汉字,整个系统都要重新部署修改,系统模块之间耦合度太高,慢慢的就想到能不能把系统各个模块分开呢,也就出现了垂直架构,但是使用着慢慢也发现,尽管界面+业务逻辑实现了逻辑的分离,但是应用不可能完全独立,大量的应用之间需要交互,耦合度还是比较高,而且用户也逐渐增多,部署在一个机器上承受不了这么大的访问量,这也就出现了SOA架构,SOA架构对系统又进行了粒度细化,将一个大的系统服务拆分成多个子服务,部署到不同机器上,通过rpc或者webservice实现模块之间的交互,而现在逐渐演变的微服务架构(microservice),则是将服务更加颗粒化,使之耦合度更低,因此微服务是现在的趋势,而springcloud则是微服务的一个代表。
eureka注册中心
由于上面我们所说的,将一个大的系统服务拆分成多个小的子系统,那么系统之间通信就比较困难,我们以前通过webservice啥的进行通信,这样我们就需要知道要调用的服务的ip还有端口号信息,而且例如我子服务a知道b服务的ip端口,但是当b服务的ip或者端口修改后,我们还需要修改子服务a的信息,当我们系统足够大,并且子服务足够多的时候,系统之间通信就变得非常乱,不好维护,而eureka则解决了这一问题,所有子服务都将自己的ip端口信息都注册给eureka,由eureka帮我们实现统一管理,比如服务a需要与服务b进行通信,服务a不需要知道b服务的ip及端口了,因为服务b已经将自己的信息注册到了eureka上了,我们只需要在eureka上查就可以了,当服务b信息修改了,服务b会自动提交给eureka最新的信息,服务a完全不受影响。
搭建项目结构
在此之前,我们可以先把简单的项目结构搭建起来,无非就是用maven创建多模块项目,不会的可以参考maven多模块搭建步骤这篇文章,完成后大致结构如下图所示:
maven_children_finish_jiegoutu1.png
由于demo_parent作为整个项目的父项目,作用:同一项目版本和公共依赖的引入,所以先将依赖在pom文件中引入。
1<?xml version="1.0" encoding="UTF-8"?>
2<project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 <modelVersion>4.0.0</modelVersion>
6 <groupId>com.lytw13</groupId>
7 <artifactId>demo_parent</artifactId>
8 <packaging>pom</packaging>
9 <version>1.0-SNAPSHOT</version>
10 <modules>
11 <module>../demo_api</module>
12 <module>../demo_sys</module>
13 <module>../demo_configuration</module>
14 <module>../demo_web</module>
15 </modules>
16 <!-- 统一项目版本信息 -->
17 <properties>
18 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
19 <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
20 <java.version>11</java.version>
21 <maven.compiler.source>11</maven.compiler.source>
22 <maven.compiler.target>11</maven.compiler.target>
23 <spring-boot-version>2.1.9.RELEASE</spring-boot-version>
24 <spring-cloud.version>Greenwich.SR3</spring-cloud.version>
25 <project.version>1.0-SNAPSHOT</project.version>
26 </properties>
27 <dependencyManagement>
28 <dependencies>
29 <!-- springboot -->
30 <dependency>
31 <groupId>org.springframework.boot</groupId>
32 <artifactId>spring-boot-dependencies</artifactId>
33 <version>${spring-boot-version}</version>
34 <type>pom</type>
35 <scope>import</scope>
36 </dependency>
37 <!-- springcloud -->
38 <dependency>
39 <groupId>org.springframework.cloud</groupId>
40 <artifactId>spring-cloud-dependencies</artifactId>
41 <version>${spring-cloud.version}</version>
42 <type>pom</type>
43 <scope>import</scope>
44 </dependency>
45 </dependencies>
46 </dependencyManagement>
47 <dependencies>
48 <!-- web -->
49 <dependency>
50 <groupId>org.springframework.boot</groupId>
51 <artifactId>spring-boot-starter-web</artifactId>
52 </dependency>
53 <!-- 集成了测试相关依赖,例如junit -->
54 <dependency>
55 <groupId>org.springframework.boot</groupId>
56 <artifactId>spring-boot-starter-test</artifactId>
57 <scope>test</scope>
58 </dependency>
59 <!--监控信息展示-->
60 <dependency>
61 <groupId>org.springframework.boot</groupId>
62 <artifactId>spring-boot-starter-actuator</artifactId>
63 </dependency>
64 <!--json-->
65 <dependency>
66 <groupId>com.alibaba</groupId>
67 <artifactId>fastjson</artifactId>
68 <version>1.2.62</version>
69 </dependency>
70 <!-- email-->
71 <dependency>
72 <groupId>org.springframework.boot</groupId>
73 <artifactId>spring-boot-starter-mail</artifactId>
74 </dependency>
75 </dependencies>
76</project>
复制代码
eureka注册中心搭建步骤
由上面的结构图可以看出,eureka_parent是所有项目的父项目,而demo_configuration则又是demo_eureka,demo_config、demo_zuul的父项目,所以可以将这3个子项目的依赖放在demo_configuration中。
1<?xml version="1.0" encoding="UTF-8"?> 2<project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <parent> 6 <artifactId>demo_parent</artifactId> 7 <groupId>com.lytw13</groupId> 8 <version>1.0-SNAPSHOT</version> 9 </parent> 10 <modelVersion>4.0.0</modelVersion> 11 <artifactId>demo_configuration</artifactId> 12 <packaging>pom</packaging> 13 <modules> 14 <module>../demo_eurekaServer</module> 15 <module>../demo_config</module> 16 <module>../demo_zuul</module> 17 </modules> 18 <dependencies> 19 <!-- eureka服务端 --> 20 <dependency> 21 <groupId>org.springframework.cloud</groupId> 22 <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> 23 </dependency> 24 </dependencies> 25</project> 复制代码
demo_eureka用于eureka注册中心相关的配置。
(1) 添加eureka主启动类
1package com.lytw13.demo;
2import org.springframework.boot.SpringApplication;
3import org.springframework.boot.autoconfigure.SpringBootApplication;
4import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
5
6@EnableEurekaServer
7@SpringBootApplication
8public class EurekaApplication {
9 public static void main(String[] args) {
10 SpringApplication.run(EurekaApplication.class,args);
11 }
12}
复制代码
(2) 新建eureka配置文件application.yml。
1server:
2 port: 6001
3
4spring:
5 application:
6 name: eureka
7eureka:
8 instance:
9 ip-address: true
10 instance-id: eureka01
11 client:
12 fetch-registry: false
13 register-with-eureka: false
14 service-url:
15 defaultZone: http://localhost:6001/eureka/
复制代码
- 启动eureka,测试是否成功。
(1) 启动项目。
springcloud_eureka_qidong.png
(2) 启动完成后,访问配置的路径localhost:端口号,查看是否启动成功。
springcloud_eureka_ceshi.png
服务注册到eureka
现在尽管我们有了eureka注册中心,但是没有任何服务,我们需要将我们项目中的服务注册到注册中心上,这样我们才能实现服务之前的通信。
这里以demo_sys_user用户服务为例,其他步骤类似。因为demo_sys_user是demo_sys的子模块,所以我们只需要将依赖添加到demo_sys上即可,这样demo_sys下的其他子模块也就可以同时使用,比如连接数据库的相关依赖,这样就实现了依赖的统一管理。
demo_sys POM文件
1<?xml version="1.0" encoding="UTF-8"?> 2<project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <parent> 6 <artifactId>demo_parent</artifactId> 7 <groupId>com.lytw13</groupId> 8 <version>1.0-SNAPSHOT</version> 9 </parent> 10 <modelVersion>4.0.0</modelVersion> 11 12 <artifactId>demo_sys</artifactId> 13 <packaging>pom</packaging> 14 <modules> 15 <module>../demo_sys_user</module> 16 <module>../demo_sys_role</module> 17 <module>../demo_sys_menu</module> 18 <module>../demo_sys_notice</module> 19 </modules> 20 <dependencies> 21 <!-- 自定义api --> 22 <dependency> 23 <groupId>com.lytw13</groupId> 24 <artifactId>demo_api</artifactId> 25 <version>1.0-SNAPSHOT</version> 26 </dependency> 27 <!-- eureka客户端 --> 28 <dependency> 29 <groupId>org.springframework.cloud</groupId> 30 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> 31 </dependency> 32 <!-- 数据库相关 --> 33 <dependency> 34 <groupId>mysql</groupId> 35 <artifactId>mysql-connector-java</artifactId> 36 </dependency> 37 <dependency> 38 <groupId>org.mybatis.spring.boot</groupId> 39 <artifactId>mybatis-spring-boot-starter</artifactId> 40 <version>2.1.1</version> 41 </dependency> 42 <dependency> 43 <groupId>com.alibaba</groupId> 44 <artifactId>druid-spring-boot-starter</artifactId> 45 <version>1.1.20</version> 46 </dependency> 47 </dependencies> 48</project> 复制代码
demo_sys_user添加主启动类
1package com.lytw13.demo; 2 3import org.springframework.boot.SpringApplication; 4import org.springframework.boot.autoconfigure.SpringBootApplication; 5import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 6 7@SpringBootApplication 8@EnableEurekaClient //开启eureka客户端 9public class UserApplication { 10 public static void main(String[] args) { 11 SpringApplication.run(UserApplication.class,args); 12 } 13} 复制代码
demo_sys_user yml配置文件
1server: 2 port: 7001 3 4spring: 5 application: 6 name: user 7 datasource: 8 driver-class-name: com.mysql.cj.jdbc.Driver 9 url: jdbc:mysql://localhost:3306/db_demo_sys?serverTimezone=Asia/Shanghai 10 username: root 11 password: 123456 12 type: com.alibaba.druid.pool.DruidDataSource 13 druid: 14 # 连接池的配置信息 15 # 初始化大小,最小,最大 16 initial-size: 5 17 min-idle: 5 18 maxActive: 20 19 # 配置获取连接等待超时的时间 20 maxWait: 60000 21 filters: stat,wall,slf4j 22 23mybatis: 24 mapper-locations: classpath:mapper/*.xml 25 config-location: classpath:mybatis/mybatis.xml 26 27 28 29info: 30 name: lytw13 31 web: lytw13.top 32eureka: 33 client: 34 service-url: 35 defaultZone: http://localhost:6001/eureka/ 36 fetch-registry: true 37 register-with-eureka: true 38 instance: 39 instance-id: user01 40 ip-address: true 41 42logging: 43 level: 44 com: 45 lytw13: 46 microservice: 47 dao: debug 复制代码
启动该项目,查看eureka上是否有了该服务。
springcloud_eureka_zhuce.png
可以看到user已经注册到了eureka上,其他服务注册相同,不再赘述。
eureka服务注册的大概结构如下:
springcloud_eureka_jiegoutu.png
尽管这样,还是需要修改一些内容,我们将服务注册到eureka上,不仅仅是为了注册到上面,而是为了让其他服务可以调用,而我们上面的项目结构图可以看到demo_api项目是为了将公共接口,实体类,工具类抽取出来,因此我们可以将userservice接口还有实体类工具类的创建到demo_api里,下面接口代码列在下面,实体类就不用了吧,方法的返回值BaseResult是自己封装好的,当然可以直接返回实体类或者list啥的,这里是为了统一返回结果,方便处理。UserService
1package com.lytw13.demo.service; 2 3import com.lytw13.demo.model.BaseResult; 4import org.springframework.web.bind.annotation.*; 5 6@RequestMapping(value = "/user") 7public interface UserService { 8 @GetMapping("/get/{id}") 9 public BaseResult get(@PathVariable("id") Integer id); 10 @GetMapping("/list") 11 public BaseResult list(); 12} 复制代码
BaseReuslt
1package com.lytw13.demo.model; 2 3import lombok.*; 4 5@AllArgsConstructor 6@NoArgsConstructor 7@Getter 8@Setter 9@ToString 10public class BaseResult { 11 private Integer resultCode; 12 private String resultMsg; 13 private Object resultData; 14} 复制代码
ResponseResult
1package com.lytw13.demo.utils; 2 3 4import com.lytw13.demo.model.BaseResult; 5 6public class ResponseResult { 7 public BaseResult setResult(Integer resultCode, String resultMsg, Object resultData){ 8 return new BaseResult(resultCode, resultMsg, resultData); 9 } 10 public BaseResult setResultSuccess(Object resultData) { 11 return new BaseResult(200,"success",resultData); 12 } 13 public BaseResult setResultFail(String msg) { 14 return new BaseResult(400,msg,null); 15 } 16} 复制代码
接着我们只需要编写demo_sys_user类了,具体无非也是实现上面的UserService接口,通过usermapper调用数据库,这里不再赘述了。编写完成后启动项目,通过application.yml中设置的端口访问方法,看看能否访问成功。
user_ceshi1.png user_ceshi2.png
以前我们通过ip加端口访问,可以通过spring中的自带的RestTemplete进行访问。
这里我们使用demo_web作为消费者,调用demo_sys_user服务。1package com.lytw13.demo.controller; 2 3import com.lytw13.demo.model.BaseResult; 4import org.springframework.beans.factory.annotation.Autowired; 5import org.springframework.web.bind.annotation.*; 6import org.springframework.web.client.RestTemplate; 7 8@RestController 9@RequestMapping("/user") 10public class UserController { 11 @Autowired 12 RestTemplate restTemplate; 13 @GetMapping("getUser") 14 public BaseResult getUser(Integer id) { 15 BaseResult baseResult = restTemplate.getForObject("http://localhost:7001/user/get/"+id, BaseResult.class); 16 return baseResult; 17 } 18} 复制代码
我们可以看到端口还有ip都是暴露的,这样肯定是不好的,因此我们就需要添加Ribbon来实现本地负载均衡,将上面的ip端口用在eureka注册中心的服务名来写。
1package com.lytw13.demo.controller; 2 3import com.lytw13.demo.model.BaseResult; 4import org.springframework.beans.factory.annotation.Autowired; 5import org.springframework.web.bind.annotation.*; 6import org.springframework.web.client.RestTemplate; 7 8@RestController 9@RequestMapping("/user") 10public class UserController { 11 @Autowired 12 RestTemplate restTemplate; 13 @GetMapping("getUser") 14 public BaseResult getUser(Integer id) { 15 BaseResult baseResult = restTemplate.getForObject("http://USER/user/get/"+id, BaseResult.class); 16 return baseResult; 17 } 18} 复制代码
eureka服务之间调用的大概结构如下:
springcloud_eureka_diaoyong_jiegoutu.png
作者:lytw1315
链接:https://juejin.im/post/5df46402e51d4557ea02ade2
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。