本指南指导您使用Netflix Ribbon为微服务应用程序提供客户端负载平衡的过程。
| Spring Cloud Netflix Ribbon现在已弃用。要查看当前推荐的客户端负载平衡方法的演示,请检查这个指导。 |
你会建立
您将构建一个微服务应用程序,它使用Netflix Ribbon和Spring Cloud Netflix在调用另一个微服务时提供客户端负载平衡。
你需要什么
大约15分钟
最喜欢的文本编辑器或IDE
JDK 1.8或晚
你也可以直接将代码导入你的IDE中:
如何完成本指南
构建与它
构建与它
首先,您设置了基本构建脚本。您可以使用Spring构建应用程序时使用您喜欢的任何构建系统,但您需要使用的代码Gradle和Maven包含在这里。如果你对其中任何一个都不熟悉,请查阅用Gradle建立Java项目或使用Maven构建Java项目。
创建目录结构
在您选择的项目目录中,创建以下子目录结构;例如,使用mkdir - p src /主/ java /你好ON * NIX系统:
└─生物化学课堂─生物化学课堂─生物化学课堂─生物化学课堂─生物化学课堂─生物化学课堂─生物化学课堂─生物化学课堂─生物化学课堂─
创建一个Gradle构建文件
下面是初始的Gradle构建文件。
问好/ build.gradle
buildscript {springbootversion ='2.3.7.release'}存储库{mavencentral()}依赖关系{classpath(“org.springframework.boot:spring-boot-gradle-plugin:$ {springbootversion}”)}应用插件:'java' apply plugin: 'eclipse' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' bootJar { baseName = 'say-hello' version = '0.0.1-SNAPSHOT' } sourceCompatibility = 11 targetCompatibility = 11 repositories { mavenCentral() } dependencies { compile('org.springframework.boot:spring-boot-starter-web') testCompile('org.springframework.boot:spring-boot-starter-test') } eclipse { classpath { containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER') containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8' } }
用户/ build.gradle
buildscript {springbootversion ='2.3.7.release'}存储库{mavencentral()}依赖关系{classpath(“org.springframework.boot:spring-boot-gradle-plugin:$ {springbootversion}”)}应用插件:'java'应用插件:'eclipse'应用插件:'org.springframework.boot'应用插件:'io.spring.dependency-management'bootjar {basename ='用户'版本='0.0.1-snapshot'} oourcecompatibility =11 TargetCompatibility = 11存储库{MavencEntral()}依赖关系{Compile('org.springframework.cloud:spring-cloud-starter-netflix-ribbon')编译('org.springframework.boot:spring-boot-starter-web')testcompile('org.springframework.boot:spring-boot-starter-test')} decessency management {imports {mavenbom“org.springframework.cloud:sspring-cloud-depenceencies:hoxton.sr9”}} eclipse {classpath {containers.remove('org.eclipse.jdt.launching.jre_container')容器'org.eclipse.jdt.launching.jre_container / org.eclipse.jdt.internal.debug.ui.launcher.standardvmtepe / javase-1.8'}}
的Spring Boot gradle插件提供许多方便的功能:
它收集类路径上的所有jar,并构建一个可运行的“über-jar”,这使得执行和传输服务更加方便。
它搜索
Public static void main()方法标记为可运行类。它提供内置的依赖关系解析器来设置匹配的版本号弹簧引导依赖性。您可以覆盖您希望的任何版本,但它将默认为Boot所选择的版本集。
与Maven构建
与Maven构建
首先,您设置了基本构建脚本。您可以使用Spring构建应用程序时使用您喜欢的任何构建系统,但您需要使用的代码Maven包含在这里。如果您不熟悉Maven,请参阅使用Maven构建Java项目。
创建目录结构
在您选择的项目目录中,创建以下子目录结构;例如,使用mkdir - p src /主/ java /你好ON * NIX系统:
└─生物化学课堂─生物化学课堂─生物化学课堂─生物化学课堂─生物化学课堂─生物化学课堂─生物化学课堂─生物化学课堂─生物化学课堂─
问好/ pom.xml
< ?xml version = " 1.0 " encoding = " utf - 8 " ?> <项目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 > < groupId >你好< / groupId > < artifactId >问好< / artifactId > <版本> 0.0.1-SNAPSHOT > < /版本< package >jar package > say-hello 用于Spring Boot的Demo项目 org.springframework. jar description> 启动< / groupId > < artifactId > spring-boot-starter-parent < / artifactId > <版本> 2.3.7。版本< / > < relativePath / > < !> UTF-8 UTF-8UTF-8UTF-811 sourceEncoding > < java.version > < / java。版本> 。 spring-boot-start -test test spring-boot-maven-plugin< artifactId>
用户/ pom.xml
< ?xml version = " 1.0 " encoding = " utf - 8 " ?> <项目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 > < groupId >你好< / groupId > < artifactId >用户< / artifactId > <版本> 0.0.1-SNAPSHOT > < /版本< package >jar package > user 用于Spring Boot的Demo项目 org.springframework. exe 启动< / groupId > < artifactId > spring-boot-starter-parent < / artifactId > <版本> 2.3.7。版本< / > < relativePath / > < !> UTF-8 UTF-8UTF-8UTF-811 sourceEncoding > < java.version > < / java。版本> spring-cloud-starter-netflix-ribbon 依赖> <依赖> 。 spring-boot-start -test test 云< / groupId > < artifactId > spring-cloud-dependencies < / artifactId > <版本>霍克顿。SR9 pom import org.springframework。spring-boot-maven-plugin< artifactId>
的春靴Maven插件提供许多方便的功能:
它收集类路径上的所有jar,并构建一个可运行的“über-jar”,这使得执行和传输服务更加方便。
它搜索
Public static void main()方法标记为可运行类。它提供内置的依赖关系解析器来设置匹配的版本号弹簧引导依赖性。您可以覆盖您希望的任何版本,但它将默认为Boot所选择的版本集。
用IDE构建
用IDE构建
阅读如何将本指南直接导入春天工具套件。
在中阅读如何使用本指南intellij想法。
编写服务器服务
我们的“服务器”服务被称为Hello。从端点访问可访问的终点将返回随机问候语(三个静态列表)/问候。
在src / main / java /你好,创建文件SayHelloApplication.java。它应该如下所示:
问好/ src / main / java / hello / SayHelloApplication.java
包你好;进口org.springframework.boot.SpringApplication;进口org.springframework.boot.autoconfigure.SpringBootApplication;进口org.springframework.web.bind.annotation.RestController;进口org.springframework.web.bind.annotation.RequestMapping;进口org.slf4j.Logger;进口org.slf4j.LoggerFactory;进口java.util。*;@RestController @SpringBootApplication公共类SayHelloApplication{私有静态Logger log = LoggerFactory.getLogger(SayHelloApplication.class);@RequestMapping(value = "/greeting") public String greet() {log.info("Access /greeting"); List greetings = Arrays.asList("Hi there", "Greetings", "Salutations"); Random rand = new Random(); int randomNum = rand.nextInt(greetings.size()); return greetings.get(randomNum); } @RequestMapping(value = "/") public String home() { log.info("Access /"); return "Hi!"; } public static void main(String[] args) { SpringApplication.run(SayHelloApplication.class, args); } }
的@RestController注释提供了与我们正在使用的相同的效果@ controller和@ResponseBody在一起。它标志着SayHelloApplication作为控制器类(这是什么@ controllerdo)并确保从类的返回值@RequestMapping方法将自动从原始类型自动转换并直接写入响应机构(这是什么@ResponseBody做)。我们有一个@RequestMapping方法/问候然后是根路径/。(我们将在使用Ribbon时使用第二种方法。)
我们将在客户服务应用程序旁边本地运行此应用程序的多个实例,因此创建目录src / main /资源,创建文件application.yml然后在该文件中设置默认值server.port。(我们也会指示应用程序的其他实例在其他端口上运行,这样当我们运行Say Hello实例时,就不会与客户端发生冲突。)当我们在这个文件中,我们将设置spring.application.name也为我们的服务。
问好/ src / main /资源/ application.yml
服务器:端口:8090
来自客户端服务的访问
User应用程序将是用户看到的。它将调用Say Hello应用程序来获得问候,然后在用户访问端点时将其发送给用户/你好。
在User应用程序目录下src / main / java /你好,添加文件UserApplication.java:
用户/ src / main / java / hello / UserApplication.java
包你好;进口org.springframework.boot.SpringApplication;进口org.springframework.boot.autoconfigure.SpringBootApplication;进口org.springframework.beans.factory.annotation.Autowired;进口org.springframework.context.annotation.Bean;进口org.springframework.web.bind.annotation.RequestMapping;进口org.springframework.web.bind.annotation.RequestParam;进口org.springframework.web.bind.annotation.RestController;进口org.springframework.web.client.RestTemplate;@springbootapplication @restcontroller公共类userapplication {@bean resttemplate resttemplate(){return new resttemplate(); } @Autowired RestTemplate restTemplate; @RequestMapping("/hi") public String hi(@RequestParam(value="name", defaultValue="Artaban") String name) { String greeting = this.restTemplate.getForObject("http://localhost:8090/greeting", String.class); return String.format("%s, %s!", greeting, name); } public static void main(String[] args) { SpringApplication.run(UserApplication.class, args); } }
为了从Say Hello获得问候,我们使用Spring 's创建RestTemplate模板类。创建RestTemplate当我们提供Say Hello服务的URL时,向它发出一个HTTP GET请求,并将结果作为字符串。(有关使用Spring使用RESTful服务的更多信息,请参见使用RESTful Web服务指南)。
添加spring.application.name和server.port属性src / main /资源/ application.properties或src / main /资源/ application.yml:
用户/ src / main /资源/ application.yml
Spring: application: name: user server: port: 8888
跨服务器实例的负载平衡
现在我们可以访问/你好在用户服务上,看到友好的问候语:
$ curl http://localhost:8888/hi你好,Artaban!$ curl http://localhost:8888/hi?name=Orontes致敬,Orontes!
要从单个硬编码的服务器URL转移到负载均衡的解决方案,让我们设置Ribbon。在application.yml文件下用户/ src / main /资源/,添加以下属性:
用户/ src / main /资源/ application.yml
例如:ribbon: eureka: enabled: false listOfServers: localhost:8090,localhost:9092,localhost:9999 ServerListRefreshInterval: 15000
这将配置Ribbon上的属性客户端。Spring Cloud Netflix创建一个ApplicationContext对于我们应用程序中的每个Ribbon客户端名称。它用于为客户端提供一组用于Ribbon组件实例的bean,包括:
一个
IClientConfig,它存储客户端或负载均衡器的配置,一个
ILoadBalancer,代表软件负载均衡器,一个
服务器列表,它定义了如何获取可供选择的服务器列表,一个
IRule,描述负载均衡策略,以及一个
管路,它表示服务器的周期性ping是如何执行的。
在上面的例子中,客户机被命名说“你好”。我们设置的属性是eureka.enabled.(我们开始。假),listOfServers,ServerListRefreshInterval。Ribbon中的负载均衡器通常从Netflix的Eureka服务注册表中获取服务器列表。(见服务注册和发现关于在Spring Cloud中使用Eureka服务注册的信息指南。)对于我们这里的简单目的,我们跳过Eureka,所以我们设置ribbon.eureka.enabled财产假而是给丝带静态listOfServers。ServerListRefreshInterval是Ribbon服务列表的刷新间隔,以毫秒为单位。
在我们的userApplication.类,开关创建RestTemplate使用Ribbon客户端获取Say Hello的服务器地址:
用户/ src / main / java / hello / UserApplication.java
包你好;进口org.springframework.boot.SpringApplication;进口org.springframework.boot.autoconfigure.SpringBootApplication;进口org.springframework.beans.factory.annotation.Autowired;进口org.springframework.context.annotation.Bean;进口org.springframework.web.bind.annotation.RequestMapping;进口org.springframework.web.bind.annotation.RequestParam;进口org.springframework.web.bind.annotation.RestController;进口org.springframework.web.client.RestTemplate;进口org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.ribbon.RibbonClient; @SpringBootApplication @RestController @RibbonClient(name = "say-hello", configuration = SayHelloConfiguration.class) public class UserApplication { @LoadBalanced @Bean RestTemplate restTemplate(){ return new RestTemplate(); } @Autowired RestTemplate restTemplate; @RequestMapping("/hi") public String hi(@RequestParam(value="name", defaultValue="Artaban") String name) { String greeting = this.restTemplate.getForObject("http://say-hello/greeting", String.class); return String.format("%s, %s!", greeting, name); } public static void main(String[] args) { SpringApplication.run(UserApplication.class, args); } }
我们已经做了一些其他相关的改变userApplication.类。我们的创建RestTemplate现在还标记为loadbalance;这告诉Spring Cloud我们想要利用它的负载平衡支持(在本例中是由Ribbon提供的)。类是用@RibbonClient,我们给出的名字我们的客户(说“你好”),然后是另一个类,其中包含extra配置为那个客户。
我们需要创建那个类。添加一个新文件,SayHelloConfiguration.java,在用户/ src / main / java /你好目录:
用户/ src / main / java / hello / SayHelloConfiguration.java
包你好;进口org.springframework.beans.factory.annotation.Autowired;进口org.springframework.context.annotation.Bean;进口com.netflix.client.config.IClientConfig;进口com.netflix.loadbalancer.IPing;进口com.netflix.loadbalancer.IRule;进口com.netflix.loadbalancer.PingUrl;进口com.netflix.loadbalancer.AvailabilityFilteringRule;public class SayHelloConfiguration {@Autowired IClientConfig ribbonClientConfig;@Bean public IPing ribbonPing(IClientConfig config){返回新的PingUrl(); } @Bean public IRule ribbonRule(IClientConfig config) { return new AvailabilityFilteringRule(); } }
通过创建我们自己的同名bean,我们可以覆盖Spring Cloud Netflix提供给我们的任何与缎带相关的bean。这里,我们重写管路和IRule由默认负载均衡器使用。默认的管路是一个无操作(它实际上不会ping服务器实例,而是总是报告它们是稳定的),以及默认的IRule是一个Zoneavoidancerule.(这避免了Amazon EC2区域,那里有最多的故障服务器,因此在我们的本地环境中尝试可能有点困难)。
我们的管路是一个Pingurl.,它将ping一个URL来检查每个服务器的状态。的方法映射到/路径;这意味着当Ribbon ping一个正在运行的Say Hello服务器时,它将得到一个HTTP 200响应。的IRule我们准备好了可用性5.,将使用Ribbon内置的断路器功能过滤掉任何处于“开路”状态的服务器:如果ping无法连接到给定的服务器,或者服务器读取失败,Ribbon将认为该服务器“死亡”,直到它开始正常响应。
|
的 这种方法确实意味着我们的功能区配置将成为主要应用上下文的一部分,因此共享所有用户应用程序中的Ribbon客户机。在一个普通的应用程序中,您可以通过使Ribbon bean远离主应用程序上下文来避免这种情况(例如,在这个例子中,您可以将 |
尝试一下
运行Hello服务,使用任意一个Gradle:
美元。/ gradlew bootRun
或Maven:
美元mvn spring-boot:运行
在端口9092和9999上运行其他实例,同样使用任意一个Gradle:
$ SERVER_PORT=9092 ./gradlew bootRun ./gradlew
或Maven:
$ SERVER_PORT=9999 mvn spring-boot:运行
然后启动User服务。访问localhost:8888 / hi然后查看Say Hello服务实例。你可以看到Ribbon的ping每15秒到达一次:
2016-03-09 21:13:22.115 INFO 90046——[nio-8090-exec-1]你好。SayHelloApplication: Access /2016-03-09 21:13:22.629 INFO 90046 --- [nio-8090-exec-3] hello.SayHelloApplication : Access /
你对User服务的请求应该会导致对Say Hello的调用以轮询的形式分布在运行的实例中:
2016-03-09 21:15:28.915 INFO 90046——[nio-8090-exec-7]你好。访问/问候语
现在关闭一个发布的Hello Server实例。一旦功能区击中了实例并将其视为下降,您应该看到请求开始在其余实例上平衡。
总结
恭喜!您刚刚开发了一个Spring应用程序,该应用程序执行客户端负载均衡,以便调用其他应用程序。
想写新的指南或贡献现有的一个?看看我们的贡献的指导方针。
| 所有指南发布时都附带了代码的ASLv2许可,以及归属,NoDerivatives创作共用许可的写作。 |