为什么使用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多模块搭建步骤这篇文章,完成后大致结构如下图所示:
SpringCloud之服务注册与发现Eureka(一) - 图1maven_children_finish_jiegoutu1.png
由于demo_parent作为整个项目的父项目,作用:同一项目版本和公共依赖的引入,所以先将依赖在pom文件中引入。

  1. 1<?xml version="1.0" encoding="UTF-8"?>
  2. 2<project xmlns="http://maven.apache.org/POM/4.0.0"
  3. 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. 5 <modelVersion>4.0.0</modelVersion>
  6. 6 <groupId>com.lytw13</groupId>
  7. 7 <artifactId>demo_parent</artifactId>
  8. 8 <packaging>pom</packaging>
  9. 9 <version>1.0-SNAPSHOT</version>
  10. 10 <modules>
  11. 11 <module>../demo_api</module>
  12. 12 <module>../demo_sys</module>
  13. 13 <module>../demo_configuration</module>
  14. 14 <module>../demo_web</module>
  15. 15 </modules>
  16. 16 <!-- 统一项目版本信息 -->
  17. 17 <properties>
  18. 18 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  19. 19 <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
  20. 20 <java.version>11</java.version>
  21. 21 <maven.compiler.source>11</maven.compiler.source>
  22. 22 <maven.compiler.target>11</maven.compiler.target>
  23. 23 <spring-boot-version>2.1.9.RELEASE</spring-boot-version>
  24. 24 <spring-cloud.version>Greenwich.SR3</spring-cloud.version>
  25. 25 <project.version>1.0-SNAPSHOT</project.version>
  26. 26 </properties>
  27. 27 <dependencyManagement>
  28. 28 <dependencies>
  29. 29 <!-- springboot -->
  30. 30 <dependency>
  31. 31 <groupId>org.springframework.boot</groupId>
  32. 32 <artifactId>spring-boot-dependencies</artifactId>
  33. 33 <version>${spring-boot-version}</version>
  34. 34 <type>pom</type>
  35. 35 <scope>import</scope>
  36. 36 </dependency>
  37. 37 <!-- springcloud -->
  38. 38 <dependency>
  39. 39 <groupId>org.springframework.cloud</groupId>
  40. 40 <artifactId>spring-cloud-dependencies</artifactId>
  41. 41 <version>${spring-cloud.version}</version>
  42. 42 <type>pom</type>
  43. 43 <scope>import</scope>
  44. 44 </dependency>
  45. 45 </dependencies>
  46. 46 </dependencyManagement>
  47. 47 <dependencies>
  48. 48 <!-- web -->
  49. 49 <dependency>
  50. 50 <groupId>org.springframework.boot</groupId>
  51. 51 <artifactId>spring-boot-starter-web</artifactId>
  52. 52 </dependency>
  53. 53 <!-- 集成了测试相关依赖,例如junit -->
  54. 54 <dependency>
  55. 55 <groupId>org.springframework.boot</groupId>
  56. 56 <artifactId>spring-boot-starter-test</artifactId>
  57. 57 <scope>test</scope>
  58. 58 </dependency>
  59. 59 <!--监控信息展示-->
  60. 60 <dependency>
  61. 61 <groupId>org.springframework.boot</groupId>
  62. 62 <artifactId>spring-boot-starter-actuator</artifactId>
  63. 63 </dependency>
  64. 64 <!--json-->
  65. 65 <dependency>
  66. 66 <groupId>com.alibaba</groupId>
  67. 67 <artifactId>fastjson</artifactId>
  68. 68 <version>1.2.62</version>
  69. 69 </dependency>
  70. 70 <!-- email-->
  71. 71 <dependency>
  72. 72 <groupId>org.springframework.boot</groupId>
  73. 73 <artifactId>spring-boot-starter-mail</artifactId>
  74. 74 </dependency>
  75. 75 </dependencies>
  76. 76</project>
  77. 复制代码

eureka注册中心搭建步骤

  1. 由上面的结构图可以看出,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>
    复制代码
    
  2. 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/    
复制代码
  1. 启动eureka,测试是否成功。

(1) 启动项目。
SpringCloud之服务注册与发现Eureka(一) - 图2springcloud_eureka_qidong.png
(2) 启动完成后,访问配置的路径localhost:端口号,查看是否启动成功。
SpringCloud之服务注册与发现Eureka(一) - 图3springcloud_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(一) - 图4springcloud_eureka_zhuce.png
    可以看到user已经注册到了eureka上,其他服务注册相同,不再赘述。
    eureka服务注册的大概结构如下:
    SpringCloud之服务注册与发现Eureka(一) - 图5springcloud_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中设置的端口访问方法,看看能否访问成功。
    SpringCloud之服务注册与发现Eureka(一) - 图6user_ceshi1.png SpringCloud之服务注册与发现Eureka(一) - 图7user_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(一) - 图8springcloud_eureka_diaoyong_jiegoutu.png
    作者:lytw1315
    链接:https://juejin.im/post/5df46402e51d4557ea02ade2
    来源:掘金
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。