Maison >Java >javaDidacticiel >Explication détaillée du déploiement du microservice de SpringCloud
Cet article vous apporte une explication détaillée du déploiement du microservice de Spring Cloud. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il vous sera utile.
L'une des caractéristiques des microservices est qu'ils comportent de nombreuses petites granularités (fonctions uniques, comme la gestion des utilisateurs, la gestion des envois SMS, la gestion des envois email, la gestion des fichiers, etc.) et peuvent être déployés, étendu et exécuté de manière indépendante Une petite application peut être appelée une API, qui est un fournisseur de services. Les API peuvent s'appeler entre elles, mais la plupart d'entre elles sont appelées par des applications. Par exemple, le système de gestion des étudiants est orienté utilisateur et constitue un ensemble de nombreuses fonctions. Il doit appeler de nombreuses API pour exécuter des fonctions commerciales, c'est pourquoi ce système de gestion des étudiants. Cela peut être appelé une application.
Le développement traditionnel d'une seule application est d'intégrer les codes de l'API et de l'application ensemble et de les exécuter dans le même processus. Correspondant au Web Java, en termes simples, ils sont tous packagés. Déployé dans une guerre et couru dans un matou. Chaque API et application d'un microservice a son propre processus, c'est-à-dire qu'elle a son propre Tomcat. Si une certaine API raccroche, cela n'affectera pas le fonctionnement des autres API et applications.
L'API est exposée dans le style restfull, donc lorsque l'application (api) appelle l'api, elle prend la forme de http:// ip:port Communiquer. La question se pose alors : si de nombreuses applications appellent une certaine API, si l'adresse IP ou le port de l'API change, et si l'adresse IP, le port et d'autres informations de l'API sont écrites dans le fichier de configuration, devons-nous en informer chaque application ? , indiquant que l'adresse et le port de cette API ont changé et que l'application doit être modifiée, recompilée et déployée (ce n'est qu'un exemple. Dans des situations réelles, certaines entreprises peuvent écrire des fichiers de configuration ou des bases de données pour configurer des constantes). C'est trop gênant. Si l'adresse et le port de l'API changent, ce serait formidable si l'application pouvait apprendre le changement à temps. Un autre inconvénient est qu’il est impossible de voir visuellement si l’API est en panne.
Ainsi, si vous ajoutez un centre de gestion de services entre l'application et l'API, l'API est comme les informations d'enregistrement du centre de gestion de services. L'application obtient les informations de l'API du centre de gestion de services. identifiant Lorsque l'API change, avertissez le centre de gestion des services, et le centre de gestion des services informe l'application ou l'application concernée pour obtenir régulièrement les dernières informations sur l'API du centre de gestion des services. En même temps, le centre de gestion des services a une stabilité et une fiabilité élevées. .
eureka est pour un tel centre de gestion de services. Ce qui suit est une image que j'ai dessinée en fonction de ma propre compréhension.
Ce qui suit est le schéma d'architecture officiel
1 .Application Service est équivalent au fournisseur de services/api
2.Application Client est équivalent au service consumer/app
3.Faire un appel à distance consiste en fait à réaliser l'utilisation de services/tels que httpClient , restTemplate
4.us-east-1 Service de cluster Eureka
5.us-east-1c, us-east-1d, us-east-1e sont des eureka spécifiques
Eureka :
est une application de servlet pure, qui doit être intégrée dans un package de guerre et déployée
est utilisé Le framework Jersey implémente sa propre interface HTTP RESTful
La synchronisation entre pairs et l'enregistrement des services sont tous implémentés via le protocole HTTP
Les tâches planifiées (envoi de Heartbeat, nettoyage programmé des services expirés, synchronisation des nœuds, etc.) sont implémentées via le Timer fourni avec le JDK
Le cache mémoire est implémenté à l'aide du package guava de Google
Les fonctions similaires à eureka incluent zookeeper, etcd, etc. Spring Boot a intégré Eureka, nous pouvons donc configurer l'environnement, le déployer et l'exécuter comme Spring Boot.
J'ai appris à utiliser Eclipse sous Windows 10.
Préparation.
Modifiez le fichier hosts et ajoutez (emplacement : C:WindowsSystem32driversetc) à la fin
127.0.0.1 01.eureka.server 127.0.0.1 02.eureka.server 127.0.0.1 03.eureka.server
Créez un projet maven ordinaire eureka-server sous Eclipse.
pom.xml
<project 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>com.fei.springcloud</groupid> <artifactid>springcloud-eureka-server</artifactid> <version>0.0.1-SNAPSHOT</version> <description>eureka服务端</description> <!-- 依赖仓库 设置从aliyun仓库下载 --> <repositories> <repository> <id>alimaven</id> <url>http://maven.aliyun.com/nexus/content/repositories/central/</url> <snapshots> <enabled>true</enabled> </snapshots> <releases> <enabled>true</enabled> </releases> </repository> </repositories> <!-- 插件依赖仓库 --> <pluginrepositories> <pluginrepository> <id>alimaven</id> <url>http://maven.aliyun.com/nexus/content/repositories/central/</url> <snapshots> <enabled>true</enabled> </snapshots> <releases> <enabled>true</enabled> </releases> </pluginrepository> </pluginrepositories> <properties> <!-- 文件拷贝时的编码 --> <project.build.sourceencoding>UTF-8</project.build.sourceencoding> <project.reporting.outputencoding>UTF-8</project.reporting.outputencoding> <!-- 编译时的编码 --> <maven.compiler.encoding>UTF-8</maven.compiler.encoding> <java.version>1.8</java.version> <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>1.5.2.RELEASE</version> <relativepath></relativepath> </parent> <dependencies> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-starter-eureka-server</artifactid> </dependency> </dependencies> <dependencymanagement> <dependencies> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-dependencies</artifactid> <version>Dalston.RELEASE</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>
Démarrer la classe Application.java
package com.fei.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
Notez l'annotation : @EnableEurekaServer, indiquant qu'il s'agit du service serveur
Fichier de configuration application.properties
logging.config=classpath:logback.xml logging.path=d:/logs ##tomcat set### # eureka的默认端口是8761 server.port=8081 server.session-timeout=60 ########### spring.application.name=eureka-server-01 ####下面2个一定要false,因为这程序是要作为服务端 但是jar中存在eureka-client.jar,所以要false,否则启动会报错的 #是否注册到eureka eureka.client.register-with-eureka=false #是否获取注册信息 eureka.client.fetch-registry=false #为了便于测试,取消eureka的保护模式,如果启动的话, 比如api提供者关闭了,但是eureka仍然保留信息 eureka.server.enable-self-preservation=false #服务名称 eureka.instance.hostname=01.server.eureka #eureka的服务地址,/eureka是固定的 eureka.client.serviceUrl.defaultZone=http://02. server.eureka:8082/eureka/,http://03.server.eureka:8083/eureka/
Remarque : Pour la configuration de eureka.client.serviceUrl.defaultZone, s'il vaut 01, renseignez les adresses et ports de 02 et 03 s'il s'agit de 02 ; , remplissez les adresses 01 et 03 et le port, c'est-à-dire que les trois services eureka 01, 02 et 03 peuvent synchroniser les données entre eux s'il s'agit de 01->02->03->01. , puis lorsque les informations d'enregistrement du fournisseur d'API atteignent 01, 01 Les données seront synchronisées avec 02, mais 02 ne seront pas synchronisées avec 03 et 01 ne seront pas synchronisées avec 03, ce qui signifie qu'il manque des données pour 03. Regardez le code source. Les informations d'enregistrement du service ne seront pas diffusées deux fois. Voir PeerAwareInstanceRegistryImpl.java
.
启动01 eureka,然后修改application.properties,变为02 eureka的配置
logging.config=classpath:logback.xml logging.path=d:/logs ##tomcat set### # eureka的默认端口是8761 server.port=8082 server.session-timeout=60 ########### spring.application.name=eureka-server-02 ####下面2个一定要false,因为这程序是要作为服务端, 但是jar中存在eureka-client.jar,所以要false,否则启动会报错的 #是否注册到eureka eureka.client.register-with-eureka=false #是否获取注册信息 eureka.client.fetch-registry=false #为了便于测试,取消eureka的保护模式,如果启动的话, 比如api提供者关闭了,但是eureka仍然保留信息 eureka.server.enable-self-preservation=false #服务名称 eureka.instance.hostname=02.server.eureka #eureka的服务地址,/eureka是固定的 eureka.client.serviceUrl.defaultZone=http://01.server. eureka:8081/eureka/,http://03.server.eureka:8083/eureka/
然后执行启动类,03也是一样的操作。
浏览器访问http://01.server.eureka:8081/(或者http://02.server.eureka:8082/,或者http://03.server.eureka:8083/)看到
api提供者
创建个普通的maven项目eureka-api,该api是个用户服务提供者。采取spring boot开发模式
pom.xml
<project> <modelversion>4.0.0</modelversion> <groupid>com.fei.springcloud</groupid> <artifactid>springcloud-eureka-server</artifactid> <version>0.0.1-SNAPSHOT</version> <description>eureka服务端</description> <!-- 依赖仓库 设置从aliyun仓库下载 --> <repositories> <repository> <id>alimaven</id> <url>http://maven.aliyun.com/nexus/content/repositories/central/</url> <snapshots> <enabled>true</enabled> </snapshots> <releases> <enabled>true</enabled> </releases> </repository> </repositories> <!-- 插件依赖仓库 --> <pluginrepositories> <id>alimaven</id> <url>http://maven.aliyun.com/nexus/content/repositories/central/</url> <snapshots> <enabled>true</enabled> </snapshots> <releases> <enabled>true</enabled> </releases> </pluginrepositories> <properties> <!-- 文件拷贝时的编码 --> <project.build.sourceencoding>UTF-8</project.build.sourceencoding> <project.reporting.outputencoding>UTF-8</project.reporting.outputencoding> <!-- 编译时的编码 --> <maven.compiler.encoding>UTF-8</maven.compiler.encoding> <java.version>1.8</java.version> <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>1.5.2.RELEASE</version> <relativepath></relativepath> </parent> <dependencies> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-starter-eureka</artifactid> </dependency> </dependencies> <dependencymanagement> <dependencies> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-dependencies</artifactid> <version>Dalston.RELEASE</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>
它和eureka 服务端,有个依赖是不一样的。
application.properties
logging.config=classpath:logback.xml logging.path=d:/logs ##tomcat set### # eureka的默认端口是8761 server.port=9081 server.session-timeout=60 ########### spring.application.name=api-user-server #像eureka服务注册信息时,使用ip地址,默认使用hostname eureka.instance.preferIpAddress=true #服务的instance-id默认默认值是${spring.cloud.client.hostname :${spring.aplication.name} :${spring.application.instance_id:${server.port}} , #也就是机器主机名:应用名称:应用端口 eureka.instance.instance-id=${spring.cloud.client.ipAddress}:${server.port} #eureka的服务地址 eureka.client.serviceUrl.defaultZone=http://01.server.eureka:8081/eureka/
Application.java
package com.fei.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @EnableEurekaClient @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
@EnableEurekaClient,不管是消费者还是提供者,对应eureka server来说都是客户端client
写个普通的controller,UserProvider.java.提供个根据id获取用户信息的接口
package com.fei.springcloud.provider; import javax.servlet.http.HttpServletRequest; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/user") public class UserProvider { @GetMapping(value="/find/{id}") public String find(@PathVariable("id") String id,HttpServletRequest request){ //实际项目中,这里可以使用JSONObject,返回json字符串 //为了便于测试消费者app的负载均衡,返回服务端端口 String s = "张三"+" 服务端端口:"+request.getLocalPort(); return s; } }
执行Application.java,将application.properties的端口修改为9082,再次执行
浏览器访问http://01.server.eureka:8081/
Application就是文件中定义的spring.application.name=api-user-server,它会自动转为大写
如果想免费学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java进阶群:478030634,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。
在Spring Cloud Netflix中,使用Ribbon实现客户端负载均衡,使用Feign实现声明式HTTP客户端调用——即写得像本地函数调用一样.
ribbo负载均衡的app消费者
创建个普通的maven项目eureka-app-ribbo.
pom.xml
<project 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>com.fei.springcloud</groupid> <artifactid>springcloud-eureka-app-ribbo</artifactid> <version>0.0.1-SNAPSHOT</version> <description>eureka消费者ribbo</description> <!-- 依赖仓库 设置从aliyun仓库下载 --> <repositories> <repository> <id>alimaven</id> <url>http://maven.aliyun.com/nexus/content/repositories/central/</url> <snapshots> <enabled>true</enabled> </snapshots> <releases> <enabled>true</enabled> </releases> </repository> </repositories> <!-- 插件依赖仓库 --> <pluginrepositories> <pluginrepository> <id>alimaven</id> <url>http://maven.aliyun.com/nexus/content/repositories/central/</url> <snapshots> <enabled>true</enabled> </snapshots> <releases> <enabled>true</enabled> </releases> </pluginrepository> </pluginrepositories> <properties> <!-- 文件拷贝时的编码 --> <project.build.sourceencoding>UTF-8</project.build.sourceencoding> <project.reporting.outputencoding>UTF-8</project.reporting.outputencoding> <!-- 编译时的编码 --> <maven.compiler.encoding>UTF-8</maven.compiler.encoding> <java.version>1.8</java.version> <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>1.5.2.RELEASE</version> <relativepath></relativepath> </parent> <dependencies> <!-- 客户端负载均衡 --> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-starter-ribbon</artifactid> </dependency> <!-- eureka客户端 --> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-starter-eureka</artifactid> </dependency> <!-- spring boot实现Java Web服务 --> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency> </dependencies> <dependencymanagement> <dependencies> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-dependencies</artifactid> <version>Dalston.RELEASE</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>
application.properties
logging.config=classpath:logback.xml logging.path=d:/logs ##tomcat set### # eureka的默认端口是8761 server.port=7081 server.session-timeout=60 ########### spring.application.name=app-user #像eureka服务注册信息时,使用ip地址,默认使用hostname eureka.instance.preferIpAddress=true #服务的instance-id默认默认值是${spring.cloud.client.hostname}${spring.application.name} :${spring.application.instance_id:${server.port}} , #也就是机器主机名:应用名称:应用端口 eureka.instance.instance-id=${spring.cloud.client.ipAddress}:${server.port} #eureka的服务地址 eureka.client.serviceUrl.defaultZone=http://01.server.eureka: 8081/eureka/,http://02.server.eureka:8082/eureka/, http://03.server.eureka:8083/eureka/
UserController.java
logging.config=classpath:logback.xml logging.path=d:/logs ##tomcat set### # eureka的默认端口是8761 server.port=7081 server.session-timeout=60 ########### spring.application.name=app-user #像eureka服务注册信息时,使用ip地址,默认使用hostname eureka.instance.preferIpAddress=true #服务的instance-id默认默认值是${spring.cloud.client.hostname} :${spring.application.name}:${spring.application.instance_id:${server.port}} , #也就是机器主机名:应用名称:应用端口 eureka.instance.instance-id=${spring.cloud.client.ipAddress}:${server.port} #eureka的服务地址 eureka.client.serviceUrl.defaultZone=http://01.server.eureka:8081/eureka/ ,http://02.server.eureka:8082/eureka/,http://03.server.eureka:8083/eureka/
使用restTemplate需要自己拼接url
启动类Application.java
package com.fei.springcloud; 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; @EnableEurekaClient @SpringBootApplication public class Application { @Bean //定义REST客户端,RestTemplate实例 @LoadBalanced //开启负债均衡的能力 RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
eureka服务
浏览器访问http://127.0.0.1:7081/user/find
看到信息“张三 服务端端口:9081”,刷新浏览器看到“张三 服务端端口:9082”,说明的确是有负载均衡。
但是访问外网的时候,http://127.0.0.1:7081/user/test,也就是域名不在eureka注册过的,就不行了。
以后再研究下如何解决。
feign的app消费者
feign可以写个接口,加上相关的注解,调用的时候,会自动拼接url,调用者就像调用本地接口一样的操作。
Feign也用到ribbon,当你使用@ FeignClient,ribbon自动被应用。
像ribbo创建个项目,或者直接在ribbo项目修改都OK。
pom.xml 把ribbo的依赖修改为feign
<project 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>com.fei.springcloud</groupid> <artifactid>springcloud-eureka-app-feign</artifactid> <version>0.0.1-SNAPSHOT</version> <description>eureka消费者feign</description> <!-- 依赖仓库 设置从aliyun仓库下载 --> <repositories> <repository> <id>alimaven</id> <url>http://maven.aliyun.com/nexus/content /repositories/central/</url> <snapshots> <enabled>true</enabled> </snapshots> <releases> <enabled>true</enabled> </releases> </repository> </repositories> <!-- 插件依赖仓库 --> <pluginrepositories> <pluginrepository> <id>alimaven</id> <url>http://maven.aliyun.com/nexus/content/repositories/central/</url> <snapshots> <enabled>true</enabled> </snapshots> <releases> <enabled>true</enabled> </releases> </pluginrepository> </pluginrepositories> <properties> <!-- 文件拷贝时的编码 --> <project.build.sourceencoding>UTF-8</project.build.sourceencoding> <project.reporting.outputencoding>UTF-8</project.reporting.outputencoding> <!-- 编译时的编码 --> <maven.compiler.encoding>UTF-8</maven.compiler.encoding> <java.version>1.8</java.version> <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>1.5.2.RELEASE</version> <relativepath></relativepath> </parent> <dependencies> <!-- Feign实现声明式HTTP客户端 --> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-starter-feign</artifactid> </dependency> <!-- eureka客户端 --> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-starter-eureka</artifactid> </dependency> <!-- spring boot实现Java Web服务 --> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency> </dependencies> <dependencymanagement> <dependencies> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-dependencies</artifactid> <version>Dalston.RELEASE</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>
application.properties和上面一样
logging.config=classpath:logback.xml logging.path=d:/logs ##tomcat set### # eureka的默认端口是8761 server.port=7081 server.session-timeout=60 ########### spring.application.name=app-user #像eureka服务注册信息时,使用ip地址,默认使用hostname eureka.instance.preferIpAddress=true #服务的instance-id默认默认值是${spring.cloud.client.hostname} :${spring.application.name}:${spring.application.instance_id:${server.port}} , #也就是机器主机名:应用名称:应用端口 eureka.instance.instance-id=${spring.cloud.client.ipAddress}:${server.port} #eureka的服务地址 eureka.client.serviceUrl.defaultZone=http://01.server.eureka 8081/eureka/,http://02.server.eureka:8082/eureka/, http://03.server.eureka:8083/eureka/
增加个UserService.java接口类
package com.fei.springcloud.service; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @FeignClient("API-USER-SERVER") public interface UserService { @GetMapping(value="/user/find/{id}") String find(@PathVariable("id") String id); } UserController.java package com.fei.springcloud.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.fei.springcloud.service.UserService; @Controller @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @GetMapping(value = "/find") @ResponseBody public String find() { //url中对应api提供者的名称,全大写 String s = userService.find("123"); return s; } }
浏览器访问http://127.0.0.1:7081/user/find,得到信息“张三 服务端端口:9081”,刷新,得到“张三 服务端端口:9082”,Feign也用到ribbon,当你使用@ FeignClient,ribbon自动被应用。所以也会负载均衡
ribbo负载均衡策略选择
AvailabilityFilteringRule:过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值) | 使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态
RandomRule:随机选择一个server
BestAvailabl:选择一个最小的并发请求的server,逐个考察Server,如果Server被tripped了,则忽略
RoundRobinRule:roundRobin方式轮询选择, 轮询index,选择index对应位置的server
WeightedResponseTimeRule:根据响应时间分配一个weight(权重),响应时间越长,weight越小,被选中的可能性越低
RetryRule:对选定的负载均衡策略机上重试机制,在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server
ZoneAvoidanceRule:复合判断server所在区域的性能和server的可用性选择server
ResponseTimeWeightedRule:作用同WeightedResponseTimeRule,二者作用是一样的,ResponseTimeWeightedRule后来改名为WeightedResponseTimeRule
在app消费者的application.properties配置文件中加入
#ribbo负载均衡策略配置,默认是依次轮询 API-USER-SERVER.ribbon.NFLoadBalancerRuleClassName=com. netflix.loadbalancer.RandomRule
其中API-USER-SERVER是api服务提供者的服务名称,也就是说,可以给每个不同的api服务提供者配置不同的复制均衡策略,验证就不贴图了
在上面的例子中,ribbon的负载均衡是在消费端完成的。流程是这样的:提供者服务A集群,启动2个进程A1,A2,都注册到eureka,app消费端根据api服务者名称获取到A1,A2的具体连接地址,ribbon就对A1,A2进行负载均衡。
缺点:
1) 如果所有的app消费端的配置策略不好,导致绝大部分的请求都到A1,那A1的压力就大了。也就是说负载策略不是有api提供者所控制的了(这里就不说A1,A2所在的服务器哪个性能更好了,因为如果app/api都是在Docker中运行,k8s负责资源调配的话,可以认为每个服务的进程所在的docker配置是一样的,比如A服务对应的A1,A2系统环境是一致的,B服务对应的B1,B2,B3系统环境是一致的,只是所对应的宿主机服务器估计不一样而已)。
2)如果api提供者需要开放给第三方公司的时候,总不能把A1,A2告诉第三方吧,说我们这A服务集群了,有A1,A2,你随意吧。
我们实际项目中的做法,都是每个提供者服务都有自己的nginx管理自己的集群,然后把nginx的域名提供给app消费者即可。之所以每个服务提供者都有自己的nginx,是因为docker被k8s管控的时候,ip都是变化的,需要更新到nginx中。如果A,B都共用一个nginx,那A重构建部署的时候,A1,A2的ip变化了,需要更新到nginx中去,那如果导致nginx出现问题了,岂不是影响到B的使用了,所以A,B都有自己的nginx。那spring cloud没有解决方案了吗?有。spring cloud集成了zuul,zuul服务网关,不但提供了和nginx一样的反向代理功能,还提供了负载均衡、监控、过滤等功能。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!