您的位置:首页 > 编程语言 > Java开发

Java后端爱上SpringCloud 第二节:内部负载均衡 Ribbon和Feign

2018-12-22 20:33 495 查看

Java后端爱上SpringCloud 第一节:内部负载均衡 Ribbon和Feign


PS:为什么说是内部负载均衡?因为Ribbon和Feign都是在SpringClodu服务间的调用做的,之后会讲到在外部请求做负载均衡。至于负载均衡是啥,大家可以自行搜索一下,老规矩先贴一些连接,让大家明确概念,在进行实现。
这里先简单的贴一下负载均衡的概念:

负载均衡:英文名称为Load Balance, 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。

一些链接

Ribbon和Feign的区别和比较

Ribbon Feign
软负载 软负载
支持TCP,HTTP,UPU 支持HTTP
支持容错 支持容错
和RestTemplate结合起来实现负载均衡 简单的HTTP生命调用

当前架构

之前有个工程起名为spring-first,太low了,我把它改名为My-Cloud-First虽然也很low。贴一下现在的架构图:


下面开始实现正题。

创建My-Spring-Ribbon

创建一个My-Spring-Ribbon工程。
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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.hyn</groupId>
<artifactId>My-Spring-Ribbon</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>My-Spring-Ribbon</name>
<description>Demo project for Spring Boot</description>

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

<dependencies>
<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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</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-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</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>

<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
</project>

注册到Eureka上面:

spring:
application:
name: spring-boot-ribbo
server:
port: 8765
# tag::configuration-eureka[]

management:
endpoints:
web:
exposure:
include: "*"  #<2>
endpoint:
health:
show-details: ALWAYS
# end::configuration-eureka[]
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/

记得在启动类上加上:@EnableEurekaClient
写一个controller:RibbonControler

package com.hyn.cloud.ribbon.controler;

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

@RestController
@RequestMapping("/ribbon")
public class RibbonControler {

@RequestMapping(value = "/name",method=RequestMethod.GET)
@ResponseBody
public String ribbon(@RequestParam String name){
String respResult="I am ribbon,My name is "+name;
return respResult;
}
}

依次启动Eureka,Admin,Ribbon,测试一下:http://127.0.0.1:8765/ribbon/name?name=hyn

创建My-Spring-Feign

创建一个My-Spring-Feign工程。
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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.hyn</groupId>
<artifactId>My-Spring-Feign</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>My-Cloud-Feign</name>
<description>Demo project for Spring Boot</description>

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

<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</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>
<scope>test</scope>
</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-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</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>

<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>

</project>

注册到Eureka上面:

spring:
application:
name: spring-boot-feign
server:
port: 8763
# tag::configuration-eureka[]

management:
endpoints:
web:
exposure:
include: "*"  #<2>
endpoint:
health:
show-details: ALWAYS
# end::configuration-eureka[]
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/

记得在启动类上加上:@EnableEurekaClient
写一个controller:RibbonControler

package com.hyn.cloud.feign.controler;

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

@RestController
@RequestMapping("/feign")
public class FeignControler {

@RequestMapping(value = "/name",method=RequestMethod.GET)
@ResponseBody
public String feign(@RequestParam String name){
String respResult="I am feign,My name is "+name;
return respResult;
}
}

依次启动Feign,测试一下:http://127.0.0.1:8763/feign/name?name=hyn

现在可以看到,在SpringBootAdmin上如下结构:

Ribbon调用

说明一下RestTemplate:

  • RestTemplate是Spring提供的用于访问Rest服务的客户端。
  • RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。
  • 调用RestTemplate的默认构造函数,RestTemplate对象在底层通过使用java.net包下的实现创建HTTP 请求,可以通过使用ClientHttpRequestFactory指定不同的HTTP请求方式。
  • ClientHttpRequestFactory接口主要提供了两种实现方式,一种是SimpleClientHttpRequestFactory,使用J2SE提供的方式(既java.net包提供的方式)创建底层的Http请求连接,还有一种方式是使用HttpComponentsClientHttpRequestFactory方式,底层使用HttpClient访问远程的Http服务,使用HttpClient可以配置连接池和证书等信息。

启动类修改:

package com.hyn.cloud.ribbon;

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.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class MyCloudRibbonApplication {

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

/**
* Spring提供的用于访问Rest服务的客户端
* @return
*/
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}

controller 类修改

package com.hyn.cloud.ribbon.controler;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("/ribbon")
public class RibbonControler {

/**
* 注入RestTemplate
*/
@Autowired
RestTemplate restTemplate;

@RequestMapping(value = "/name",method=RequestMethod.GET)
@ResponseBody
public String ribbon(@RequestParam String name){
String respResult="I am ribbon,My name is "+name;
String url="http://SPRING-BOOT-FEIGN/feign/name?name=";
return restTemplate.getForObject(url+respResult, String.class);
}
}

在调用一下:

可以看到通过Ribbon去调用了Feign,虽然栗子举的有些生硬。哈哈哈哈

Feign调用

启动类修改:

package com.hyn.cloud.feign;

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

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients //开启spring cloud feign的支持
public class MyCloudFeignApplication {

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

controller修改:

package com.hyn.cloud.feign.controler;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.hyn.cloud.feign.service.FeignService;

@RestController
@RequestMapping("/feign")
public class FeignControler {

@Autowired
FeignService feignService;

@RequestMapping(value = "/name",method=RequestMethod.GET)
public String feign(@RequestParam String name){
return feignService.getName(name);
}
}

添加一个service:

package com.hyn.cloud.feign.service;

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

@FeignClient(value = "SPRING-BOOT-RIBBO")
public interface FeignService {

@RequestMapping(value = "/ribbon/name",method = RequestMethod.GET)
String getName(@RequestParam("name")String name);

}

然后我掉了一下http://127.0.0.1:8763/feign/name?name=hyn,然后feign去调了ribbon,ribbon又去调了feign,然后就没有然后了,会报一大堆错,没有仔细分析。
这里我们在ribbon项目Controller里面再添加一个Request,

package com.hyn.cloud.ribbon.controler;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("/ribbon")
public class RibbonControler {

/**
* 注入RestTemplate
*/
@Autowired
RestTemplate restTemplate;

@RequestMapping(value = "/name",method=RequestMethod.GET)
@ResponseBody
public String ribbon(@RequestParam String name){
String respResult="I am ribbon,My name is "+name;
String url="http://SPRING-BOOT-FEIGN/feign/name?name=";
return restTemplate.getForObject(url+respResult, String.class);
}

@RequestMapping(value = "/name2",method=RequestMethod.GET)
@ResponseBody
public String ribbon2(@RequestParam String name){
String respResult="I am ribbon,My name2 is "+name;
return respResult;
}

}

修改FeignService调用的url

package com.hyn.cloud.feign.service;

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

@FeignClient(value = "SPRING-BOOT-RIBBO")
public interface FeignService {

@RequestMapping(value = "/ribbon/name2",method = RequestMethod.GET)
String getName(@RequestParam("name")String name);

}

然后请求feign项目:


可以看到feign工程去调用了ribbon工程的name2的controller

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐