spring cloud的简单搭建及服务之间的两种调用方式

所有好走的路都是下坡路,等你意识到错了,已经回不了头。

Spring Cloud

SpringCloud是一套微服务开发一站式解决方案,它提供了微服务开发所需的很多功能组件,比如服务统一管理,配置统一管理,路由网关,断路器,事件总线,集群状态配置等等,而且springcloud与springboot无缝衔接,
配合springboot能够更轻松的搭配出一套架构平台。

微服务

微服务其实是一种架构的设计风格,并没有明确的技术绑定和架构概念。简单来说,微服务架构风格就是将原来的单一架构开发为一组小型服务(微服务)的方法,每个服务都运行在自己独立的进程中(服务间的隔离),服务间采用轻量级的通信机制(http,rpc-netty,webservice),这些服务按照业务拆分,并且独立部署(自动化部署),服务会有一个统一的管理中心管理(zookeeper,eureka, nacos),服务可以采用不同的语言开发,并且使用不同的存储技术(数据库垂直拆分)。

1、eureka注册中心的搭建

  1. 创建父工程

继承springboot,springcloud

  • pom文件:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <modules>
        <module>springclud_eureka</module>
        <module>springcloud_student</module>
        <module>springcloud_class</module>
        <module>springcloud_teacher</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.9.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.yuxi</groupId>
    <artifactId>springcloud_boot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springcloud_boot</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR5</spring-cloud.version>
    </properties>

  <!--  <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>-->

    <dependencyManagement>
        <dependencies>
            <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>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>-->

</project>

  1. 创建eureka微服务模块

创建一个maven工程,pom文件如下

<?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>springcloud_boot</artifactId>
        <groupId>com.yuxi</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springclud_eureka</artifactId>

    <dependencies>
        <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>
  1. 编写启动类,注意多了一个注解
package com.yuxi;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

/**
 * @author Administrator
 */
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class,args);
    }
}

  1. 配置文件application.yml
server:
  port: 20000
spring:
  application:
    # 配置为服务的名称,以后的监控中心可以看到
    name: EurekaService
eureka:
  client:
    service-url:
      defaultZone: http://localhost:20000/eureka
    #当前配置的是监控中心, 没有必要抓取服务
    fetch-registry: false
    # 是否自我注册
    register-with-eureka: false


2、eureka客户端student服务模块的搭建

  1. 创建一个Maven工程,继承springcloud_demo工程。
    pom文件如下:
<?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>springcloud_boot</artifactId>
        <groupId>com.yuxi</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud_student</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--让他可以注册到注册中心-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <!--服务之间的调用-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
    </dependencies>

    <!--打包插件-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
  1. 配置启动类
package com.yuxi;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

/**
 * @author Administrator
 *
 * @EnableEurekaClient  在使用spring cloud2.x之后的版本,该注解可以省略
 */
@SpringBootApplication
@EnableEurekaClient
public class StudentApplication {
    public static void main(String[] args) {
        SpringApplication.run(StudentApplication.class,args);
    }

    /**
     * 创建一个RestTemplate实例交给spring容器去管理,实现的是远程调用
     * @return 返回一个实例
     */
    @Bean
    @LoadBalanced
    public RestTemplate getRest(){
        return new RestTemplate();
    }

    /**
     * 配置的是负载均衡的策略,被调用方集群的时候可以用该算法来选择服务对象
     * @return
     */
    @Bean
    public IRule getRule(){
        return new RandomRule();
    }
}

  1. 配置application.yml文件
server:
  port: 8080
spring:
  application:
    # 不可以用下划线
    name: micro-Student
eureka:
  client:
    service-url:
      defaultZone: http://localhost:20000/eureka
  1. 编写微服务的功能接口(根据微服务本身的业务不同,编写不同的接口)
package com.yuxi.contorller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

@RestController
@RequestMapping("/stu")
public class StudentController {

    @Resource
    private RestTemplate restTemplate;

    /**
     * @ResponseBody ,将方法的返回值,放入response相应体中
     * @param id
     * @return
     */
    @RequestMapping("/name")
    public String getNameById(int id){

        String s = restTemplate.getForObject("http://micro-class/cla/clazz?id="+id,String.class);

        switch (id){
            case 1:
                return "zhangsan" + s;
            case 2:
                return "lisi" + s;
            default:
                return "hello";
        }
    }
}

3、服务的调用-Ribbon + RestTemplate(独立的组件)

  1. Ribbon

Ribbon是一个客户端的负载均衡器,用来进行springcloud之间微服务负载均衡调用

  1. 负载均衡的方式

1)客户端负载均衡
2)服务端负载均衡
2.1)网络4层负载
2.2)网络7层负载 - nginx

4、Ribbon+RestTemplate的使用(class微服务模块)

  1. 在创建一个班级的微服务,用于后续的调用
  2. 主动的调用方(学生服务 -> 班级服务,学生服务就是主动调用方)添加依赖:
<!-- 添加ribbon依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
  1. 在调用方声明RestTemplate组件
@Bean
@LoadBalanced//负载均衡
public RestTemplate getRest(){
    return new RestTemplate();
}
  1. 在调用方编写服务调用代码
  String s = restTemplate.getForObject("http://micro-class/cla/clazz?id="+id,String.class);
  1. 被调用方class微服务的pom文件(其中有的依赖用于后续的操作):
<?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>springcloud_boot</artifactId>
        <groupId>com.yuxi</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud_class</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
  1. class服务的启动类(@EnableFeignClients(basePackages = "com.yuxi.feign")注解用于后续的技术,目前不用)
package com.yuxi;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * @author Administrator
 */
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = "com.yuxi.feign")
public class ClassApplication {
    public static void main(String[] args) {
        SpringApplication.run(ClassApplication.class,args);
    }
}

  1. class模块的application.yml文件
server:
  port: 8081
spring:
  application:
    name: micro-class
eureka:
  client:
    service-url:
      defaultZone: http://localhost:20000/eureka

# 配置feign的超时和重连
# Feign自带超时和重试的功能,但是默认是关闭的。所以我们看到的超时和重试的效果,是底层Ribbon提供的。
# 如果开启了Feign的超时重试就会覆盖掉Ribbon的设置

ribbon:
  # 连接超时
  ConnectTimeout: 1000
  #读取超时
  ReadTimeout: 1000
  #配置ribbon的重连次数,默认是0
  MaxAutoRetries: 0
  #配置ribbon的下个服务的重试次数,默认是1
  MaxAutoRetriesNextServer: 0


#配置Feign的超时,一旦配置了Feign的超时,ribbon的重试和超时会全部失效
feign:
  client:
    config:
      MIRCO-TEACHER: # (可变选项,可以定位)可以针对不同的微服务配置不同的超时时间
        connectTimeout: 1000
        readTimeout: 6000
      MIRCO-STUDENT:
        connectTimeout: 1000
        readTimeout: 2000
  1. 编写class模块的数据接口(TeaFeign是以后用的,目前忽略)
package com.yuxi.controller;

import com.yuxi.feign.TeaFeign;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @author Administrator
 */
@RestController
@RequestMapping("/cla")
public class ClassController {

    @Resource
    private TeaFeign teaFeign;

    @RequestMapping("/clazz")
    public String getClass(int id){

//        借助feign接口远程调用教师服务
        String feignTea = teaFeign.getTea(id);

        switch (id){
            case 1:
                return "一班" + feignTea;
            case 2:
                return "二班" + feignTea;
            case 3:
                return "三班" + feignTea;
            default:
                return "没有";
        }
    }
}

5、 服务的调用-Feign(底层其实就是Ribbon)

  1. 为什么有了Ribbon还有用Feign?

Feign底层也调用了Ribbon,Feign其实本质上是Ribbon + Hystrix(豪猪)的集合体,因为Ribbon本身的写法不够面向对象,很多Java程序员对这种写法会很不习惯。

6、Feign的使用

在创建一个teacher微服务模块,以供后续的调用

  1. 调用方添加feign的依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  1. 在调用方(class模块)中编写一个feign接口:
package com.yuxi.feign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

/**
 *使用feign来调用服务
 * @author Administrator
 */
@FeignClient("micro-teacher")
public interface TeaFeign {

    /**
     * 调用教师模块的功能
     * @param id
     * @return
     */
    @RequestMapping(value = "/tea/gettea")
    String getTea(@RequestParam("id") int id);
}

  1. 在需要调用微服务的时候(class模块),注入改接口
    @Resource
    private TeaFeign teaFeign;

    @RequestMapping("/clazz")
    public String getClass(int id){

//        借助feign接口远程调用教师服务
        String feignTea = teaFeign.getTea(id);
        .
        .
        .
  1. 在调用方配置启动类注解(以上代码中有了)
@SpringBootApplication(scanBasePackages = "com.qf")
@EnableEurekaClient
//表示启动feign,而且这个注解需要找到Feign接口所在的包,默认去启动类所在包下找
//所有如果Feign接口没有在启动类的包下,就需要手动配置扫描
@EnableFeignClients(basePackages = "com.qf.feign")
public class ClassesApplication {

    public static void main(String[] args) {
        SpringApplication.run(ClassesApplication.class, args);
    }
}
  1. 编写被调用方启动类(teacher)
package com.yuxi;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

  1. 编写teacher模块的配置文件
server.port=8082
spring.application.name=micro-teacher
eureka.client.service-url.defaultZone=http://localhost:20000/eureka
  1. 编写teacher模块的数据接口
package com.yuxi.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author Administrator
 */
@RestController
@RequestMapping("/tea")
public class TeacherController {

    @RequestMapping("/gettea")
    public String getTea(@RequestParam(value = "id") int id) {

        /**
         * 测试feign的重连和超时
         */
        System.out.println("正在连接***********************************");

        try {
            Thread.sleep(5 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


//        正常执行功能代码
        switch (id) {
            case 1:
                return "王老师";
            case 2:
                return "李老师";
            case 3:
                return "赵老师";
            default:
                return "没有";
        }
    }
}

  1. teacher模块的pom文件
<?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>springcloud_boot</artifactId>
        <groupId>com.yuxi</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud_teacher</artifactId>


    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

总结

本次小demo创建了四个微服务,分别是作为注册中心的eureka,作为客户端的student,class,teacher四个。其中,student在调用class服务的时候用的是Ribbon + RestTemplate方式实现调用;class在调用teacher服务的时候用的是Feign,三个服务之间使用了两种不同的调用方式,在平时使用较多的是第二种调用方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值