• Spring cloud 框架 --- Eureka 心得


    spring boot      1.5.9.RELEASE

    spring cloud    Dalston.SR1

    1.前言

    (1)接触了spring cloud 框架 ,首先要知道Eureka是什么。

        Eureka是spring cloud框架的 注册服务中心  ,可以有多个注册服务中心存在, 多个注册中心通过相互注册来同步服务注册信息。

    (2)有什么用处?

        是为了分布式运算做配合工作,让不同的服务器可以相互通信,以微服务的方式各自处理专门的业务,其实就是http的访问,向指定服务器传入参数,让其把处理结果返回过来,但是因为服务提供者的访问路径不稳定,即ip等因素不稳定,可能会变化,却又不想让服务消费者改变调用代码,因此引入一个中间层 eureka ,统一管理所有服务的访问接口,这样消费者只需要向注册中心获取服务列表,知道服务名字【名字一般不会变】,那么就不需要关心ip是否变化,动态注入参数即可。

        不仅是分布式 计算用到 服务清单 ,集群 也可以用到 ,用于做负载均衡 ,提高处理效率。

    (3)功能本质是什么?

        原本不使用 服务注册中心,其实也是可以在Java 访问http 请求的 ,但是前提需要知道每个服务 的 ip地址/域名 ,还需要请求路径 和参数格式,蛋疼的是 ,ip地址/域名容易改动,当需要调用非常多的服务时候,还得手动修改,很麻烦,且容易出错,

    所以才用 eureka 服务注册中心来统一管理 ip地址/域名 ,使用其他东西来替代 ,于是选择了 application name  应用名 ,每个spring boot 工程都有一个应用名 ,一般不会随意改动 ,访问路径和参数格式一般也不会改动 ,因此,这样可以让服务消费端调用

    服务提供者的接口代码稳定起来 ,即便服务提供者ip/域名有变化 ,消费者也不需要改动代码,该吃吃该喝喝 , 只需要提供者改动注册列表信息即可,因此,本质还是 http请求。

        

    2.心得

    (1)spring cloud 框架分 3类角色  :服务消费者  、 服务提供者  、注册中心 。

    (2)服务提供者提供服务,向消费者暴露http请求接口【服务提供者也可以是服务消费者】,需要向服务注册中心注册信息 ,即在服务列表添加这个提供者服务的ip等信息;

    (3)服务消费者则向服务注册中心获取服务列表 ,通过注册列表知道服务名字,即可获取并调用服务提供者的接口,这样就不需要知道服务提供者的具体ip信息了,ip信息由服务注册中心统一管理,因此,服务消费者只需要知道eureka 服务中心ip地址或者域名即可获取服务列表信息后使用服务接口。

    (4)服务提供者需要知道 eureka 服务中心ip地址或者域名 ,向最少一个eureka 服务中心注册信息 ,可以多个同时注册。

    注册中心可以互相注册,也可以不注册,但是为了保持服务列表的同步性,也就是CAP定理的 AP高可用性,服务注册中心一般是设置相互注册,

    因此需要知道每个注册中心的ip地址/域名,

    (5)spring cloud 引入了 eureka 的好处就是不再需要关注提供者的ip信息了 ,因为提供者的ip信息容易变动 ,现在提供者的信息由服务注册中心统一管理,ip信息不容易变动,因此只需要关注注册中心的ip即可  ,因为 注册中心相互注册信息同步,只要有一个没有坏,都不影响服务使用,

    3.目录结构

    使用maven多模块 ,在一个maven项目了添加多个maven子项目,使用spring boot 框架,

     4.eureka 注册中心配置

    新建3个工程,

    microservicecloud-eureka-7001 、
    microservicecloud-eureka-7002 、
    microservicecloud-eureka-7003

     配置基本一样,

     pom.xml文件导入依赖

    <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>
    
        <parent>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>microservicecloud</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </parent>
    
        <artifactId>microservicecloud-eureka-7001</artifactId>
    
        <dependencies>
            <!--eureka-server服务端 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka-server</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>
    View Code

    在启动的主函数加入注解 

    //用于标记为服务注册中心端

    @EnableEurekaServer // EurekaServer服务器端启动类,接受其它微服务注册进来

     在application.yml配置文件设置属性

    server: 
      port: 7001
     
    eureka: 
      instance:
        hostname: eureka7001.com #eureka服务端的实例名称(这里使用了虚拟主机映射,修改hosts文件即可实现)
      client: 
        register-with-eureka: false     #false表示不向注册中心注册自己。
        fetch-registry: false     #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
        service-url: 
          #单机 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
          #设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址(单机)。
          defaultZone: http://localhost:7002/eureka/,http://localhost:7003/eureka/
    
     
    
     
    View Code

    如果想不向其他服务注册中心同步自己的服务列表信息,则需要将

    service-url: 
    #单机 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
    #设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址(单机)。
    defaultZone: http://localhost:7002/eureka/,http://localhost:7003/eureka/

    这一段删除,否则最少需要注册一个,不然会报错,启动不了【可以将自己的地址写上去】

    到了现在,可以启动这个子项目了,【我把7002端口的也启动了,其他端口的注册中心与7001的配置基本一样,只是需要注册的ip地址不同】

    浏览器输入 网址 http://localhost:7001/  ,这是eureka 控制面板,可以显示服务注册情况

    当前还没服务提供者注册,所以显示无服务实例可用

    5.eureka 服务提供者配置

    其实所谓的服务提供者,其实是在以前web项目的基础上,添加了向服务注册中心注册该项目的ip访问信息,其他的业务spring boot该怎么做还是老样子,不影响内部业务,这样即便自己项目修改IP,也不会影响到服务消费者的使用,还可以为负载均衡做相应的配合,因为有服务列表的存在,做集群 则很方便。

    新建了3个子工程,端口号不同

    分别是

    microservicecloud-provider-dept-8001
    microservicecloud-provider-dept-8002
    microservicecloud-provider-dept-8003

    配置类似,这里展示8001端口的

    启动类添加注解

    //用于标记为客户端
    @EnableEurekaClient //本服务启动后会自动注册进eureka服务中,
    //用于标记发现服务
    @EnableDiscoveryClient //服务发现,可以是其他注册中心,不仅仅是eureka,但是服务提供者需要使用这个
    
    

     pom.xml添加依赖

    <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>
    
        <parent>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>microservicecloud</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </parent>
    
        <artifactId>microservicecloud-provider-dept-8001</artifactId>
    
        <dependencies>
            <!-- 引入自己定义的api通用包,可以使用Dept部门Entity -->
            <dependency>
                <groupId>com.atguigu.springcloud</groupId>
                <artifactId>microservicecloud-api</artifactId>
                <version>${project.version}</version>
            </dependency>
            <!-- actuator监控信息完善 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <!-- 将微服务provider侧注册进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>
            <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>
            </dependency>
        </dependencies>
    
    </project>
    View Code

     application.yml文件

    server:
      port: 8001
    
    mybatis:
      config-location: classpath:mybatis/mybatis.cfg.xml        # mybatis配置文件所在路径
      type-aliases-package: com.atguigu.springcloud.entities    # 所有Entity别名类所在包
      mapper-locations:
        - classpath:mybatis/mapper/**/*.xml                       # mapper映射文件
    
    spring:
      application:
        name: microservicecloud-dept1 # 应用名称
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource            # 当前数据源操作类型
        driver-class-name: org.gjt.mm.mysql.Driver              # mysql驱动包
        url: jdbc:mysql://localhost:3306/clinic?characterEncoding=utf-8        # 数据库名称
        username: root
        password: mysql
        dbcp2:
          min-idle: 5                                           # 数据库连接池的最小维持连接数
          initial-size: 5                                       # 初始化连接数
          max-total: 5                                          # 最大连接数
          max-wait-millis: 200                                  # 等待连接获取的最大超时时间
    
    eureka:
      client: #客户端注册进eureka服务列表内
        service-url:
          #            defaultZone: http://localhost:7002/eureka
          #       将该service注册到集群eureka中
          #       defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
    
          #    应该写 eureka 注册中心服务器的地址 ,如果有域名可以写域名,否则报错无法连接
          defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/
      instance:
        instance-id: microservicecloud-dept8001   # 在eureka中显示对应的服务名字  , 在列Status 下面显示
        prefer-ip-address: true     #在eureka中下边的访问路径可以显示IP地址
    
    info: # 在eureka列Status中可以点击info链接,显示有值。链接后的内容就是在这里配置的
      app.name: java3y-microservicecloudn你可以看到我吗
      company.name: www.java3y.com
      build.artifactId: $project.artifactId$
      build.version: $project.version$
    View Code

    启动后,即可自动向服务注册中心注册该工程的ip信息  ,

     浏览器查看7001 端口的eureka控制面板

    再查看7002端口的

    都有显示注册的服务实例信息的ip

     直接浏览器用localhost调用

    现在知道了ip,可以用ip调用

    ok,完美运行,不影响服务提供者的路径访问的同时还在注册中心注册了信息列表,

    6.eureka 服务消费者配置

    服务消费者有多种方式调用服务,现在解释最简单的方法

    使用restTemplate访问restful接口
    非常的简单粗暴无脑。 (url, requestMap,
    * ResponseBean.class)这三个参数分别代表 REST请求地址、请求参数、HTTP响应转换被转换成的对象类型。

    目录结构

    restTemplate调用例子

    package com.atguigu.springcloud.controller;
    
    import com.atguigu.springcloud.entities.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";
        //这个MICROSERVICECLOUD-DEPT1 其实是该服务提供者的application name 应用名称 ,因此,需要知道服务的应用名字,因此应用名字不应该改变
        private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-DEPT1";
    
        /**
         * 使用 使用restTemplate访问restful接口非常的简单粗暴无脑。 (url, requestMap,
         * ResponseBean.class)这三个参数分别代表 REST请求地址、请求参数、HTTP响应转换被转换成的对象类型。
         */
        @Autowired
        private RestTemplate restTemplate;
    
        @RequestMapping(value = "/consumer/dept/add")
        public boolean add(Dept dept) {
            //使用restTemplate 直接调用 ,postForObject 是post请求方式 ,getForObject是get请求方式,根据服务提供者的接口选择,这个是需要提前知道服务提供者的接口格式的
            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);
        }
    
        @SuppressWarnings("unchecked")
        @RequestMapping(value = "/consumer/dept/list")
        public List<Dept> list() {
            return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);
        }
    
        // 测试@EnableDiscoveryClient,消费端可以调用服务发现
        @RequestMapping(value = "/consumer/dept/discovery")
        public Object discovery() {
            System.out.println("查看服务列表");
            Object obj = restTemplate.getForObject(REST_URL_PREFIX + "/dept/discovery", Object.class);
            System.out.println(obj.toString());
            return obj;
        }
    
    }
    View Code

    其实就是直接由Java直接访问服务提供者的http网址,网址接口、参数都必须符合该要求,说白了就是个网址请求,只是不需要域名、不需要ip地址,只需要知道该服务工程的application name 即应用名,不可出错,

    否则访问失败,因为 服务消费者 自动去服务注册中心获取服务列表,根据应用名 获取对应的ip地址 ,再自动拼接后访问 ,虽然消费者不需要知道ip地址,但是仍需要知道调用的服务应用名 和 各个请求的操作路径和参数格式

    才可以正确远程调用服务。

    还需要提前在pom.xml导入依赖,

    <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>
    
        <parent>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>microservicecloud</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </parent>
    
        <artifactId>microservicecloud-consumer-dept-80</artifactId>
        <description>部门微服务消费者</description>
    
        <dependencies>
            <dependency><!-- 自己定义的api -->
                <groupId>com.atguigu.springcloud</groupId>
                <artifactId>microservicecloud-api</artifactId>
                <version>${project.version}</version>
            </dependency>
            <!-- Ribbon相关 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-ribbon</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
            </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>
    View Code

    //启动类需要添加注解

    //用于标记为客户端
    @EnableEurekaClient

     application.yml文件

    server:
      port: 80
      
      
    eureka:
      client:
        register-with-eureka: false  # 当前微服务不注册到eureka中(消费端)
        service-url: 
          defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/
    View Code

    测试:

    浏览器输入 http://localhost/consumer/dept/discovery  ,返回的结果就是远程调用端口8001 一个服务处理返回的结果 

    消费者后台调用逻辑 

    控制台打印

     //看看8001端口服务提供者是在怎么处理的

    ----------------------------------------------------------------------

    参考博文原址:  https://www.zhihu.com/question/283286745/answer/763040709

  • 相关阅读:
    领域驱动设计概念(Domain-driven Design), Flower(响应式微服务框架)
    主流RPC框架通讯协议实现原理与源码解析
    响应式微服务框架Flower——快速上手
    netty源码-server端绑定端口流程
    ubuntu 20.04版本更新软件源为国内源(清华、网易、阿里云等等)
    ubuntu20.04源码安装nginx
    docker环境下Java获取cpu核心数不准确,实际上是宿主机的cpu核心数
    利用docker快速搭建创建开发环境
    mac配置python环境
    Apache Maven-创建项目
  • 原文地址:https://www.cnblogs.com/c2g5201314/p/12877948.html
Copyright © 2020-2023  润新知