Spring Cloud 入门教程2、服务消费者(Ribbon)

孤街浪徒 提交于 2019-12-01 06:03:59

一、前言

1、什么是Ribbon

Ribbon是Netflix开源的实现了负载均衡等功能的RPC客户端。
支持HTTP、TCP、UDP协议,且有一定的容错、缓存等机制

Spring Cloud基于Ribbon封装了Spring Cloud Ribbon,方便结合Eureka、Consul等服务治理框架使用。Ribbon的主要作用是:从服务器端拿到对应服务列表后以负载均衡的方式访问对应服务。

从这张图上来说,Ribbon主要是从Eureka拿到服务列表之后,以负载均衡的策略选择其中一台发起调用。

2、本篇环境信息

框架 版本
Spring Boot 2.0.0.RELEASE
Spring Cloud Finchley.BUILD-SNAPSHOT
JDK 1.8.x

3、准备工作

  • Eureka服务端搭建

参考:https://ken.io/note/spring-cloud-eureka-quickstart

  • 服务提供者搭建

参考:https://ken.io/note/spring-cloud-eureka-quickstart

说明
GroupId io.ken.springcloud.testservice
ArtifactId testservice

pom.xml、启动类(App.java)保持不变

二、服务提供者准备

1、配置Eureka地址

  • application.yml 配置
server:    port: 8602    spring:    application:      name: testservice    eureka:    client:      serviceUrl:        defaultZone: http://localhost:8800/eureka/    app:    ip: localhost  

2、DTO准备

  • 创建共用的ResponseDTO:Result.java
package io.ken.springcloud.testservice.model;    public class Result {        private int code;        private String message;        private Object content;        private String serviceName;        private String host;        public int getCode() {          return code;      }        public void setCode(int code) {          this.code = code;      }        public String getMessage() {          return message;      }        public void setMessage(String message) {          this.message = message;      }        public Object getContent() {          return content;      }        public void setContent(Object content) {          this.content = content;      }        public String getServiceName() {          return serviceName;      }        public void setServiceName(String serviceName) {          this.serviceName = serviceName;      }        public String getHost() {          return host;      }        public void setHost(String host) {          this.host = host;      }  }  
  • 创建Plus.java用作加法运算RequestDTO
package io.ken.springcloud.testservice.model;    public class Plus {        private int numA;        private int numB;        public int getNumA() {          return numA;      }        public void setNumA(int numA) {          this.numA = numA;      }        public int getNumB() {          return numB;      }        public void setNumB(int numB) {          this.numB = numB;      }  }  

3、编写服务入口

  • 创建服务入口 TestController.java
package io.ken.springcloud.testservice.controller;    import io.ken.springcloud.testservice.model.Plus;  import io.ken.springcloud.testservice.model.Result;  import org.springframework.beans.factory.annotation.Value;  import org.springframework.web.bind.annotation.RequestMapping;  import org.springframework.web.bind.annotation.RestController;    @RestController  public class TestController {        @Value("${spring.application.name}")      private String serviceName;        @Value("${app.ip}")      private String address;        @Value("${server.port}")      private String port;        @RequestMapping("/")      public Object index() {          Result result = new Result();          result.setServiceName(serviceName);          result.setHost(String.format("%s:%s", address, port));          result.setMessage("hello");          return result;      }        @RequestMapping("/plus")      public Object plus(Plus plus) {          Result result = new Result();          result.setServiceName(serviceName);          result.setHost(String.format("%s:%s", address, port));          result.setMessage("success");          result.setContent(plus.getNumA() + plus.getNumB());          return result;      }    }  

4、访问测试

  • 启动TestService

分别以端口8602,8603启动testservice。
此时testservice等于是在Eureka Server注册了两个实例

分别访问 http://localhost:8602,http://localhost:8603

将会看到以下信息:

# http://localhost:8602  {    "code": 0,    "message": "success",    "content": 0,    "serviceName": "testservice",    "host": "localhost:8062"  }    # http://localhost:8603  {    "code": 0,    "message": "success",    "content": 0,    "serviceName": "testservice",    "host": "localhost:8063"  }  

三、服务消费者搭建(Ribbon)

1、创建Ribbon项目

  • 创建一个Spring Boot工程

使用maven-archtype-quickstart模板创建项目

说明
GroupId io.ken.springcloud.ribbonclient
ArtifactId ribbonclient
  • 在pom.xml加入相关依赖
<?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">      <modelVersion>4.0.0</modelVersion>        <groupId>io.ken.springcloud.ribbonclient</groupId>      <artifactId>ribbonclient</artifactId>      <version>1.0-SNAPSHOT</version>        <name>ribbonclient</name>      <url>http://ken.io</url>        <properties>          <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>          <maven.compiler.source>1.8</maven.compiler.source>          <maven.compiler.target>1.8</maven.compiler.target>      </properties>        <parent>          <groupId>org.springframework.boot</groupId>          <artifactId>spring-boot-starter-parent</artifactId>          <version>2.0.0.RELEASE</version>      </parent>        <dependencyManagement>          <dependencies>              <dependency>                  <groupId>org.springframework.cloud</groupId>                  <artifactId>spring-cloud-dependencies</artifactId>                  <version>Finchley.BUILD-SNAPSHOT</version>                  <type>pom</type>                  <scope>import</scope>              </dependency>          </dependencies>      </dependencyManagement>        <dependencies>            <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.boot</groupId>              <artifactId>spring-boot-starter-web</artifactId>          </dependency>            <dependency>              <groupId>junit</groupId>              <artifactId>junit</artifactId>              <version>4.11</version>              <scope>test</scope>          </dependency>        </dependencies>        <repositories>          <repository>              <id>spring-snapshots</id>              <name>Spring Snapshots</name>              <url>https://repo.spring.io/libs-snapshot</url>              <snapshots>                  <enabled>true</enabled>              </snapshots>          </repository>      </repositories>        <build>          <finalName>ribbonclient</finalName>      </build>    </project>  

2、配置Ribbon启动类

  • 配置启动类

修改\src\main\java\io\ken\springcloud\eurekaserver\App.java
基于Spring Boot创建启动类,添加上 @EnableDiscoveryClient 注解

并且向程序的ioc注入一个bean: restTemplate,并通过@LoadBalanced注解表明这个restRemplate开启负载均衡的功能。

package io.ken.springcloud.ribbonclient;    import org.springframework.boot.SpringApplication;  import org.springframework.boot.autoconfigure.SpringBootApplication;  import org.springframework.cloud.client.discovery.EnableDiscoveryClient;  import org.springframework.cloud.client.loadbalancer.LoadBalanced;  import org.springframework.context.annotation.Bean;  import org.springframework.web.client.RestTemplate;    @EnableDiscoveryClient  @SpringBootApplication  public class App {        public static void main(String[] args) {          SpringApplication.run(App.class, args);      }        @Bean      @LoadBalanced      public RestTemplate restTemplate() {          return new RestTemplate();      }  }  

3、编写Eureka服务访问

  • 创建TestService.java

TestService作为访问testservice的代理服务类,通过RestTemplate访问远程testservice,Ribbon会负责把servicename替换成实际要访问的host

package io.ken.springcloud.ribbonclient.service;    import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.stereotype.Service;  import org.springframework.web.client.RestTemplate;    @Service  public class TestService {        @Autowired      private RestTemplate restTemplate;        public Object index() {          return restTemplate.getForObject("http://testservice", String.class);      }        public Object plus(int numA, int numB) {          String url = String.format("http://testservice/plus?numA=%s&numB=%s", numA, numB);          return restTemplate.getForObject(url, String.class);      }  }  

4、编写服务入口

  • 创建TestController

TestController作为访问服务testservice的入口

package io.ken.springcloud.ribbonclient.controller;    import io.ken.springcloud.ribbonclient.service.TestService;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.web.bind.annotation.RequestMapping;  import org.springframework.web.bind.annotation.RequestParam;  import org.springframework.web.bind.annotation.RestController;    @RestController  public class TestController {        @Autowired      private TestService testService;        @RequestMapping("/")      public Object index() {          return "ribbon client";      }        @RequestMapping("/ti")      public Object ti() {          return testService.index();      }        @RequestMapping("/plus")      public Object plus(@RequestParam("numa") int numA, @RequestParam("numb") int numB) {          return testService.plus(numA, numB);      }  }  

5、配置Eureka Client

在\src\main下创建文件夹resources文件夹并设置为Resources Root

在resources文件夹下创建application.yml文件并配置Eureka Client

server:    port: 8604    spring:    application:      name: ribbonclient    eureka:    client:      serviceUrl:        defaultZone: http://localhost:8800/eureka/  

6、服务访问/消费测试

RibonClient项目启动后,访问 http://localhost:8604/ti
会交替显示以下内容

{    "code": 0,    "message": "hello",    "content": null,    "serviceName": "testservice",    "host": "localhost:8602"  }    {    "code": 0,    "message": "hello",    "content": null,    "serviceName": "testservice",    "host": "localhost:8603"  }  

四、备注

  • 本篇示例代码

https://github.com/ken-io/springcloud-course/tree/master/chapter-02

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!