狂神说Spring Cloud Netflix笔记-01(服务注册与发现)

Spring Cloud Netflix

  • 1、SpringCloud入门概述
    • 1.1 SpringCloud是什么
    • 1.2 SpringBoot与SpringCloud的关系
    • 1.3 Dubbo 和 SpringCloud技术选型
      • 1、分布式+服务治理Dubbo
      • 2、Dubbo 和 SpringCloud对比
    • 1.4 SpringCloud能干什么
    • 1.5 SpringCloud在哪下
  • 2、总体介绍
    • 2.1SpringCloud版本选择
  • 3、创建父工程
    • pom.xml
  • 4、pojo管理:springcloud-api
    • pom.xml
    • Dept.java
  • 5、服务提供者:springcloud-provider-dept-8001
      • pom.xml
      • DeptMapper
      • DeptService
      • DeptServiceImpl
      • DeptMapper.xml
      • mybatis-config.xml
      • application.yml
      • DeptController
      • 主启动类DeptProvider_8001
  • 6、服务消费者:springcloud-consumer-dept-80
      • pom.xml
      • ConfigBean
      • DeptConsumerController
      • application.yml
      • 主启动类DeptConsumer_80
  • 7、Eureka服务注册与发现
    • 7.1、什么是Eureka
    • 7.2、原理讲解
    • 7.3、springcloud-eureka-7001
      • pom.xml
      • application.yml
      • 主启动类:EurekaServer_7001
    • Eureka的自我保护机制
    • 7.4、8001服务注册与发现
      • pom.xml
      • application.yml
    • actuator完善监控信息
      • 服务发现

1、SpringCloud入门概述

1.1 SpringCloud是什么

springcloud官网: https://spring.io/projects/spring-cloud#learn

狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第1张图片
狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第2张图片

1.2 SpringBoot与SpringCloud的关系

狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第3张图片

1.3 Dubbo 和 SpringCloud技术选型

1、分布式+服务治理Dubbo

目前成熟的互联网架构:应用服务化拆分+消息中间件
狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第4张图片

2、Dubbo 和 SpringCloud对比

可以看一下社区活跃度

https://github.com/dubbo

https://github.com/springcloud

狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第5张图片
狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第6张图片
狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第7张图片

1.4 SpringCloud能干什么

狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第8张图片

1.5 SpringCloud在哪下

官网 : https://spring.io/projects/spring-cloud/
狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第9张图片
狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第10张图片

2、总体介绍

狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第11张图片
狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第12张图片

2.1SpringCloud版本选择

狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第13张图片

3、创建父工程

直接创建一个名为SpringCloud的Maven空项目即可

然后后面全部的项目都是父工程的一个子模块,并且都是maven的空项目

建立一个数据库:db01
狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第14张图片

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.0modelVersion>

    <groupId>com.wugroupId>
    <artifactId>SpringCloudartifactId>
    <version>1.0-SNAPSHOTversion>
   
    
    <packaging>pompackaging>

    
    <properties>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <maven.compiler.source>1.8maven.compiler.source>
        <maven.compiler.target>1.8maven.compiler.target>
        <junit.version>4.12junit.version>
        <lombok.version>1.18.16lombok.version>
        <log4j.version>1.2.17log4j.version>
        <logback-core.version>1.2.3logback-core.version>
        <mysql-connector-java.version>8.0.21mysql-connector-java.version>
        <druid.version>1.1.23druid.version>
        <mybatis-spring-boot-starter.version>2.1.4mybatis-spring-boot-starter.version>
        <spring-boot-dependencies.version>2.3.8.RELEASEspring-boot-dependencies.version>
        <spring-cloud-dependencies.version>Hoxton.SR9spring-cloud-dependencies.version>
    properties>

	
    <dependencyManagement>
        <dependencies>
            
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>${spring-cloud-dependencies.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
            
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-dependenciesartifactId>
                <version>${spring-boot-dependencies.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
            
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>${mysql-connector-java.version}version>
            dependency>
            
            <dependency>
                <groupId>com.alibabagroupId>
                <artifactId>druidartifactId>
                <version>${druid.version}version>
            dependency>
            
            <dependency>
                <groupId>org.mybatis.spring.bootgroupId>
                <artifactId>mybatis-spring-boot-starterartifactId>
                <version>${mybatis-spring-boot-starter.version}version>
            dependency>
            
            
            <dependency>
                <groupId>junitgroupId>
                <artifactId>junitartifactId>
                <version>${junit.version}version>
            dependency>
            
            <dependency>
                <groupId>org.projectlombokgroupId>
                <artifactId>lombokartifactId>
                <version>${lombok.version}version>
            dependency>
            
            <dependency>
                <groupId>log4jgroupId>
                <artifactId>log4jartifactId>
                <version>${log4j.version}version>
            dependency>
            <dependency>
                <groupId>ch.qos.logbackgroupId>
                <artifactId>logback-coreartifactId>
                <version>${logback-core.version}version>
            dependency>
        dependencies>
    dependencyManagement>
    <build>
        
    build>

project>

4、pojo管理:springcloud-api

现在这个api拆分出来只管pojo,这个微服务就写完了
狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第15张图片

pom.xml


<dependencies>
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
    dependency>
dependencies>  

Dept.java

@Data
@NoArgsConstructor
@Accessors(chain = true)  //链式写法
//所有的实体类务必实现序列化,通讯需求
public class Dept implements Serializable {//Dept,实体类 orm 类表关系映射
    private static final long serialVersionUID = 708560364349809174L;
    private Long deptno; //主键
    private String dname;

    //看下这个数据存在哪个数据库的字段~ 微服务 ,一个服务对应一个数据库
    //同一个信息可能存在不同的数据库
    private String db_source;

    public Dept(String dname) {
        this.dname = dname;
    }
}

5、服务提供者:springcloud-provider-dept-8001

狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第16张图片

pom.xml

<dependencies>
    
    <dependency>
        <groupId>com.wugroupId>
        <artifactId>springcloud-apiartifactId>
        <version>1.0-SNAPSHOTversion>
    dependency>
    
    <dependency>
        <groupId>junitgroupId>
        <artifactId>junitartifactId>
    dependency>
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
    dependency>
    <dependency>
        <groupId>com.alibabagroupId>
        <artifactId>druidartifactId>
    dependency>
    
    <dependency>
        <groupId>ch.qos.logbackgroupId>
        <artifactId>logback-coreartifactId>
    dependency>
    <dependency>
        <groupId>org.mybatis.spring.bootgroupId>
        <artifactId>mybatis-spring-boot-starterartifactId>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-testartifactId>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-jettyartifactId>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-devtoolsartifactId>
    dependency>
dependencies>

DeptMapper

@Mapper
@Repository
public interface DeptMapper {
    //添加部门
    boolean addDept(Dept dept);

    //根据ID查询部门
    Dept queryById(@Param("deptno") long id);

    //查询全部部门
    List<Dept> queryall();
}

DeptService

public interface DeptService {
    boolean addDept(Dept dept);

    Dept queryById(long id);

    List<Dept> queryall();

}

DeptServiceImpl

@Service
public class DeptServiceImpl implements DeptService {

    @Autowired
    private DeptMapper deptMapper;

    @Override
    public boolean addDept(Dept dept) {
        return deptMapper.addDept(dept);
    }

    @Override
    public Dept queryById(long id) {
        return deptMapper.queryById(id);
    }

    @Override
    public List<Dept> queryall() {
        return deptMapper.queryall();
    }
}

DeptMapper.xml




<mapper namespace="com.wu.springcloud.mapper.DeptMapper">
    <insert id="addDept" parameterType="Dept">
        insert into dept(dname,db_source)
        values (#{dname},DATABASE());
    insert>

    <select id="queryById" resultType="Dept" parameterType="Long">
        select * from dept where deptno = #{deptno};
    select>

    <select id="queryall" resultType="Dept">
        select * from dept;
    select>
mapper>

mybatis-config.xml




<configuration>
    <settings>
        
        <setting name="cacheEnabled" value="true"/>
    settings>
configuration>

application.yml

server:
  port: 8001

#mybatis配置
mybatis:
  type-aliases-package: com.wu.springcloud.pojo
  config-location: classpath:mybatis/mybatis-config.xml
  mapper-locations: classpath:mybatis/mapper/*.xml

#spring的配置
spring:
  application:
    name: springcloud-provider-dept  # 3个服务名称一致是前提
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource  #数据源
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/db01?useUnicode=true&characterEncoding=UTF-8&useSSL=true&serverTimezone=UTC
    username: root
    password: Wl123456

DeptController

//提供Restfull服务!!
@RestController
public class DeptController {

    @Autowired
    private DeptServiceImpl deptService;

    @PostMapping("/dept/add")
    public boolean addDept(Dept dept) {
        return deptService.addDept(dept);
    }


    @GetMapping("/dept/get/{id}")
    public Dept getDept(@PathVariable("id") Long id) {
        Dept dept = deptService.queryById(id);
        if (dept == null) {
            throw new RuntimeException("Fail");
        }
        return dept;
    }

    @GetMapping("/dept/list")
    public List<Dept> queryAll() {
        return deptService.queryall();
    }

}

主启动类DeptProvider_8001

//启动类
@SpringBootApplication
public class DeptProvider_8001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProvider_8001.class, args);
    }
}

最后启动项目访问Controller里面的接口测试即可,这个pojo类在别的项目里面,我们照样可以拿到,这就是微服务的简单拆分的一个小例子

6、服务消费者:springcloud-consumer-dept-80

狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第17张图片

pom.xml


<dependencies>
    <dependency>
        <groupId>com.wugroupId>
        <artifactId>springcloud-apiartifactId>
        <version>1.0-SNAPSHOTversion>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-devtoolsartifactId>
    dependency>
dependencies>

这里要用到 RestTemplate ,但是它的类中没有Bean,所以我们要把它注册到Bean中

ConfigBean

@Configuration
public class ConfigBean {  //@Configuration ... 相当于spring中的配置文件 applicationContext.xml文件
    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

DeptConsumerController

@Controller
public class DeptConsumerController {

    //消费者 : 不因该有service层
    //RestTemplate  有很多方法给我们直接调用  !  它的类中没有Bean所以要我们自己把它注册到Bean中
    //(url, 实体:Map, Class responseType)
    @Autowired
    private RestTemplate restTemplate;  //提供多种便捷访问远程http服务的方法,简单的restful服务模板

    private static final String REST_URL_PREFIX = "http://localhost:8001";

    @RequestMapping("/consumer/dept/get/{id}")
    @ResponseBody
    public Dept getDept(@PathVariable("id") Long id) {
        //service不在本项目中,所以要去远程项目获取
        //远程只能用  get 方式请求,那么这里也只能通过 get 方式获取
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id, Dept.class);
    }

    @RequestMapping("/consumer/dept/add")
    @ResponseBody
    public boolean add(Dept dept) {
        //远程只能用  post 方式请求,那么这里也只能通过 post 方式获取
        return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);
    }

    @RequestMapping("/consumer/dept/list")
    @ResponseBody
    public List<Dept> queryAll() {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);
    }

}

然后你会发现,原来远程的post请求直接在url是拒绝访问的,但是在这个里面可以访问,只是结果为null

application.yml

server:
  port: 80

主启动类DeptConsumer_80

@SpringBootApplication
public class DeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumer_80.class, args);
    }
}

最后启动服务提供者 springcloud-provider-dept-8001

然后启动服务消费者 springcloud-consumer-dept-80

通过服务消费者的url请求去获取服务提供者对应的请求,照样可以拿到

7、Eureka服务注册与发现

7.1、什么是Eureka

狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第18张图片

7.2、原理讲解

狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第19张图片

狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第20张图片
狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第21张图片
狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第22张图片
在这里插入图片描述
狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第23张图片

7.3、springcloud-eureka-7001

pom.xml


<dependencies>
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-eureka-serverartifactId>
        <version>1.4.7.RELEASEversion>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-devtoolsartifactId>
    dependency>
dependencies>

application.yml

server:
  port: 7001
  servlet:
    context-path: /eureka

#Eureka配置
eureka:
  instance:
    hostname: localhost # Eureka服务端实例的名字
  client:
    register-with-eureka: false  # 表示是否向Eureka注册中心注册自己
    fetch-registry: false #如果为false,则表示自己为注册中心
    service-url: # 监控页面地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

主启动类:EurekaServer_7001

@SpringBootApplication
@EnableEurekaServer //EnableEurekaServer表示服务端的启动类,可以接收别人注册进来
public class EurekaServer_7001 {
    public static void main(String[] args) {
        SpringApplication.run(ConfigEurekaServer_7001.class, args);
    }
}

启动之后访问 http://localhost:7001/
狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第24张图片

Eureka的自我保护机制

狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第25张图片

7.4、8001服务注册与发现

springcloud-provider-dept-8001

首先肯定是要导入对应的依赖

pom.xml


<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-eurekaartifactId>
    <version>1.4.7.RELEASEversion>
dependency>

然后在配置文件中添加对应的Eureka注册配置

application.yml

#eureka 的配置,服务注册到哪里
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/

最后在主启动类上添加注解

@EnableEurekaClient  //在服务启动后自动注册到Eureka中

启动springcloud-config-eureka-7001,启动完毕后再启动下面的服务

启动springcloud-provider-dept-8001,等一会再次访问 http://localhost:7001/

狂神说Spring Cloud Netflix笔记-01(服务注册与发现)_第26张图片

actuator完善监控信息

所以这个时候我们应该是少了什么东西,然后我们继续在 8001 里面添加依赖


<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-actuatorartifactId>
dependency>

重启8001项目再次点击服务状态信息,跳到了一个页面,但是里面什么都没有,这个时候我们就要配置一些信息了,这个信息只是在团队开发的时候别人会通过这个信息来了解这个服务是谁写的

现在我们在8001项目的配置文件中添加一些配置

#eureka 的配置,服务注册到哪里
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/
  instance:
    instance-id: springcloud-provider-dept8001  #修改Eureka上的默认的状态名字

#info配置(点击状态信息会返回的东西,可以百度)
info:
  app.name: wulei-springcloud    
  company.name: blog.wulei2921625957.com

然后你重启8001项目,再次点击项目状态信息会返回你在上面添加的信息

那如何通过代码来让别人发现自己呢?

服务发现

在8001项目的controller里面添加

import org.springframework.cloud.client.discovery.DiscoveryClient;

//获取一些配置的信息,得到一些具体微服务
@Autowired
private DiscoveryClient client;

//注册进来的微服务~ ,获取一些信息
@GetMapping("/dept/discovery")
public Object discovery() {
    //获取微服务列表的清单
    List<String> services = client.getServices();
    System.out.println("discovery=>services:" + services);

    //得到一个具体的微服务信息,通过具体的微服务ID applicationName
    List<ServiceInstance> instances = client.getInstances("SPRINGCLOUD-PROVIDER-DEPT");
    for (ServiceInstance instance : instances) {
        System.out.println(
            instance.getHost() + "\t" +
            instance.getPort() + "\t" +
            instance.getUri() + "\t" +
            instance.getServiceId()
        );
    }
    return instances;
}

然后在8001项目主启动类上添加服务发现注解即可

这个注解我试了一下,不加也可以访问上面的接口返回信息

@EnableDiscoveryClient //服务发现

重启8001项目并访问 http://localhost:8001/dept/discovery

在这里插入图片描述

你可能感兴趣的:(SpringCloud,分布式)