目录
eureka的作用
eureka集群搭建
app消费者
负载均衡策略在消费端配置的缺点
首页 Java java教程 SpringCloud的微服务部署详解

SpringCloud的微服务部署详解

Oct 27, 2018 am 11:56 AM
docker java mysql spring springcloud

本篇文章给大家带来的内容是关于SpringCloud的微服务部署详解,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

微服务的其中一个特点就是有许许多的粒度小(功能单一,比如用户管理,短信发送管理,邮件发送管理,文件管理等)、能独立部署、扩展、运行的小应用,可以称为api,也就是服务提供者。api之间可以相互调用,但更多的是供app调用,比如学生管理系统,它是面向用户的,是许许多多功能的集合体,它需要调用许多api完成业务功能,所以这学生管理系统可以称为app。

eureka的作用

传统的单体应用开发,就是将api和app的代码全部集成在一起,在同一个进程中运行,对应java web通俗的说就是全部打包在一个war中部署在一个tomcat中运行。而微服务的每个api,app都拥有自己的进程,也就是都有自己的tomcat,某个api挂了,不影响其他api和app运行。

2562732344-5bd3112355e87_articlex.png

api是采取restfull风格暴漏出去的,所以app(api)调用api时,采取http://ip:端口这形式进行通讯。那么问题来了,如果有很多app都调用了某个api,如果api的ip或端口发生了更改,如果app中对api的ip和端口等信息是写在配置文件的,难道要通知每个app,说这个api的地址和端口变了,app要进行修改重新编译部署(这是举例子而已,实际情况有些企业对常量的配置可能写配置文件,也可能写数据库)。这太麻烦了,如果api的地址和端口有发生变化,app能及时获知自行变更,那就好了。还有个弊端,就是api是否挂了,也没法直观观察到。

所以,如果在app和api之间增加个服务管理中心,api像服务管理中心注册信息,app从服务管理中心获取api的信息,api有个唯一标识,api有变更的时候通知服务管理中心,服务管理中心通知相关的app或者app定时从服务管理中心获取最新的api信息,同时服务管理中心具有很高的稳定性、可靠性。

eureka就是为了这样的一个服务管理中心,下面是我根据自己的理解画的一张图。

3691603079-5bd311461110a_articlex.png

下面这张是官方的架构图

2743013935-5bd31154d98e6_articlex.png

1.Application Service 相当于服务提供者/api

2.Application Client 相当于服务消费者/app

3.Make Remote Call,其实就是实现服务的使用/比如httpClient,restTemplate

4.us-east-1 Eureka 集群服务

5.us-east-1c、us-east-1d、us-east-1e 就是具体的某个eureka

Eureka:

  1. 是纯正的 servlet 应用,需构建成war包部署

  2. 使用了 Jersey 框架实现自身的 RESTful HTTP接口

  3. peer之间的同步与服务的注册全部通过 HTTP 协议实现

  4. 定时任务(发送心跳、定时清理过期服务、节点同步等)通过 JDK 自带的 Timer 实现

  5. 内存缓存使用Google的guava包实现

eureka集群搭建

和eureka类似功能的有zookeeper,etcd等。spring boot已经集成了eureka,所以我们可以像spring boot那样搭建环境,部署运行。

我是在window10下使用eclipse学习的。

准备工作。

在修改hosts文件,在最后面加上(位置:C:WindowsSystem32driversetc)

127.0.0.1 01.eureka.server 
127.0.0.1 02.eureka.server 
127.0.0.1 03.eureka.server
登录后复制

eclipse下创建个普通的maven项目eureka-server。

pom.xml

 <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>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 /> 
</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>
登录后复制

启动类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); 
} 
}
登录后复制

注意注解:@EnableEurekaServer,表明这是server服务

配置文件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/
登录后复制

注意:eureka.client.serviceUrl.defaultZone的配置,如果是01,则填写02、03的地址和端口;如果是02,则填写01、03的地址和端口,也就是说让01,02,03这3个eureka服务能相互间同步数据,如果是01->02->03->01,则api提供者注册信息到01时,01会同步数据到02,但02不会同步到03,01也不会同步到03,也就是说03缺数据了。看源码,服务的注册信息不会被二次传播,看PeerAwareInstanceRegistryImpl.java

2362280564-5bd3156de3fb6_articlex.png

启动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/)看到

1478557485-5bd3165f391c5_articlex.png

api提供者

创建个普通的maven项目eureka-api,该api是个用户服务提供者。采取spring boot开发模式

2022850817-5bd3166f5e3d2_articlex.png

pom.xml

<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>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> 
</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 /> 
</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/

1193354954-5bd318beb3fe5_articlex.png

Application就是文件中定义的spring.application.name=api-user-server,它会自动转为大写

如果想免费学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java进阶群:478030634,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

app消费者

在Spring Cloud Netflix中,使用Ribbon实现客户端负载均衡,使用Feign实现声明式HTTP客户端调用——即写得像本地函数调用一样.

797474213-5bd318d468bdf_articlex.png

ribbo负载均衡的app消费者

创建个普通的maven项目eureka-app-ribbo.

pom.xml

<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>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 /> 
</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服务

1624583235-5bd31b7e3c83e_articlex.png

浏览器访问http://127.0.0.1:7081/user/find

看到信息“张三 服务端端口:9081”,刷新浏览器看到“张三 服务端端口:9082”,说明的确是有负载均衡。

但是访问外网的时候,http://127.0.0.1:7081/user/test,也就是域名不在eureka注册过的,就不行了。

671479369-5bd31b9792490_articlex.png

以后再研究下如何解决。

feign的app消费者

feign可以写个接口,加上相关的注解,调用的时候,会自动拼接url,调用者就像调用本地接口一样的操作。

Feign也用到ribbon,当你使用@ FeignClient,ribbon自动被应用。

像ribbo创建个项目,或者直接在ribbo项目修改都OK。

pom.xml 把ribbo的依赖修改为feign

<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>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 /> 
 </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负载均衡策略选择

3340723967-5bd31f2d830c8_articlex.png

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一样的反向代理功能,还提供了负载均衡、监控、过滤等功能。

以上是SpringCloud的微服务部署详解的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

docker怎么更新镜像 docker怎么更新镜像 Apr 15, 2025 pm 12:03 PM

更新 Docker 镜像的步骤如下:拉取最新镜像标记新镜像为特定标签删除旧镜像(可选)重新启动容器(如果需要)

docker内的文件怎么拷贝到外面 docker内的文件怎么拷贝到外面 Apr 15, 2025 pm 12:12 PM

Docker 中将文件拷贝到外部主机的方法:使用 docker cp 命令:执行 docker cp [选项] &lt;容器路径&gt; &lt;主机路径&gt;。使用数据卷:在主机上创建目录,在创建容器时使用 -v 参数挂载该目录到容器内,实现文件双向同步。

docker怎么退出容器 docker怎么退出容器 Apr 15, 2025 pm 12:15 PM

退出 Docker 容器的四种方法:容器终端中使用 Ctrl D 快捷键容器终端中输入 exit 命令宿主机终端中使用 docker stop &lt;container_name&gt; 命令宿主机终端中使用 docker kill &lt;container_name&gt; 命令(强制退出)

docker怎么重启 docker怎么重启 Apr 15, 2025 pm 12:06 PM

重启 Docker 容器的方法:获取容器 ID(docker ps);停止容器(docker stop &lt;container_id&gt;);启动容器(docker start &lt;container_id&gt;);验证重启成功(docker ps)。其他方法:Docker Compose(docker-compose restart)或 Docker API(参考 Docker 文档)。

docker desktop怎么用 docker desktop怎么用 Apr 15, 2025 am 11:45 AM

如何使用 Docker Desktop?Docker Desktop 是一款工具,用于在本地机器上运行 Docker 容器。其使用步骤包括:1. 安装 Docker Desktop;2. 启动 Docker Desktop;3. 创建 Docker 镜像(使用 Dockerfile);4. 构建 Docker 镜像(使用 docker build);5. 运行 Docker 容器(使用 docker run)。

docker容器名称怎么查 docker容器名称怎么查 Apr 15, 2025 pm 12:21 PM

可以通过以下步骤查询 Docker 容器名称:列出所有容器(docker ps)。筛选容器列表(使用 grep 命令)。获取容器名称(位于 "NAMES" 列中)。

怎么看docker进程 怎么看docker进程 Apr 15, 2025 am 11:48 AM

Docker 进程查看方法:1. Docker CLI 命令:docker ps;2. Systemd CLI 命令:systemctl status docker;3. Docker Compose CLI 命令:docker-compose ps;4. Process Explorer(Windows);5. /proc 目录(Linux)。

docker怎么启动mysql docker怎么启动mysql Apr 15, 2025 pm 12:09 PM

在 Docker 中启动 MySQL 的过程包含以下步骤:拉取 MySQL 镜像创建并启动容器,设置根用户密码并映射端口验证连接创建数据库和用户授予对数据库的所有权限

See all articles