打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
SpringCloud微服务部署

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

    eureka的作用

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


       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就是为了这样的一个服务管理中心,下面是我根据自己的理解画的一张图。


  下面这张是官方的架构图


  • Application Service 相当于服务提供者/api
  • Application Client 相当于服务消费者/app
  • Make Remote Call,其实就是实现服务的使用/比如httpClient,restTemplate
  • us-east-1 Eureka 集群服务
  • 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:\Windows\System32\drivers\etc)

[plain] view plain copy
  1. 127.0.0.1 01.eureka.server  
  2. 127.0.0.1 02.eureka.server  
  3. 127.0.0.1 03.eureka.server  

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

    pom.xml

[html] view plain copy
  1. <project xmlns='http://maven.apache.org/POM/4.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'  
  2.     xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd'>  
  3.     <modelVersion>4.0.0</modelVersion>  
  4.     <groupId>com.fei.springcloud</groupId>  
  5.     <artifactId>springcloud-eureka-server</artifactId>  
  6.     <version>0.0.1-SNAPSHOT</version>  
  7.     <description>eureka服务端</description>  
  8.   
  9.     <!-- 依赖仓库 设置从aliyun仓库下载 -->  
  10.     <repositories>  
  11.         <repository>  
  12.             <id>alimaven</id>  
  13.             <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>  
  14.             <snapshots>  
  15.                 <enabled>true</enabled>  
  16.             </snapshots>  
  17.             <releases>  
  18.                 <enabled>true</enabled>  
  19.             </releases>  
  20.         </repository>  
  21.     </repositories>  
  22.     <!-- 插件依赖仓库 -->  
  23.     <pluginRepositories>  
  24.         <pluginRepository>  
  25.             <id>alimaven</id>  
  26.             <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>  
  27.             <snapshots>  
  28.                 <enabled>true</enabled>  
  29.             </snapshots>  
  30.             <releases>  
  31.                 <enabled>true</enabled>  
  32.             </releases>  
  33.         </pluginRepository>  
  34.     </pluginRepositories>  
  35.   
  36.     <properties>  
  37.   
  38.         <!-- 文件拷贝时的编码 -->  
  39.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  40.         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>  
  41.         <!-- 编译时的编码 -->  
  42.         <maven.compiler.encoding>UTF-8</maven.compiler.encoding>  
  43.   
  44.         <java.version>1.8</java.version>  
  45.         <maven.compiler.source>1.8</maven.compiler.source>  
  46.         <maven.compiler.target>1.8</maven.compiler.target>  
  47.   
  48.     </properties>  
  49.   
  50.     <parent>  
  51.         <groupId>org.springframework.boot</groupId>  
  52.         <artifactId>spring-boot-starter-parent</artifactId>  
  53.         <version>1.5.2.RELEASE</version>  
  54.         <relativePath />  
  55.   
  56.     </parent>  
  57.   
  58.     <dependencies>  
  59.   
  60.         <dependency>  
  61.             <groupId>org.springframework.cloud</groupId>  
  62.             <artifactId>spring-cloud-starter-eureka-server</artifactId>  
  63.         </dependency>  
  64.   
  65.     </dependencies>  
  66.   
  67.     <dependencyManagement>  
  68.         <dependencies>  
  69.             <dependency>  
  70.                 <groupId>org.springframework.cloud</groupId>  
  71.                 <artifactId>spring-cloud-dependencies</artifactId>  
  72.                 <version>Dalston.RELEASE</version>  
  73.                 <type>pom</type>  
  74.                 <scope>import</scope><!-- 这个不能丢 -->  
  75.             </dependency>  
  76.   
  77.         </dependencies>  
  78.     </dependencyManagement>  
  79.   
  80.     <build>  
  81.         <plugins>  
  82.             <plugin>  
  83.                 <groupId>org.springframework.boot</groupId>  
  84.                 <artifactId>spring-boot-maven-plugin</artifactId>  
  85.             </plugin>  
  86.         </plugins>  
  87.     </build>  
  88.   
  89. </project>  

启动类Application.java

[java] view plain copy
  1. package com.fei.springcloud;  
  2.   
  3. import org.springframework.boot.SpringApplication;  
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;  
  5. import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;  
  6.   
  7. @EnableEurekaServer    
  8. @SpringBootApplication  
  9. public class Application {  
  10.   
  11.     public static void main(String[] args) {  
  12.   
  13.         SpringApplication.run(Application.class, args);  
  14.     }  
  15. }  
注意注解:@EnableEurekaServer,表明这是server服务


配置文件application.properties

[plain] view plain copy
  1. logging.config=classpath:logback.xml  
  2. logging.path=d:/logs  
  3.   
  4. ##tomcat set###  
  5.   
  6. # eureka的默认端口是8761  
  7. server.port=8081  
  8. server.session-timeout=60  
  9. ###########  
  10.   
  11. spring.application.name=eureka-server-01  
  12.   
  13. ####下面2个一定要false,因为这程序是要作为服务端,但是jar中存在eureka-client.jar,所以要false,否则启动会报错的  
  14. #是否注册到eureka  
  15. eureka.client.register-with-eureka=false  
  16. #是否获取注册信息  
  17. eureka.client.fetch-registry=false  
  18.   
  19. #为了便于测试,取消eureka的保护模式,如果启动的话,比如api提供者关闭了,但是eureka仍然保留信息  
  20. eureka.server.enable-self-preservation=false  
  21. #服务名称  
  22. eureka.instance.hostname=01.server.eureka  
  23. #eureka的服务地址,/eureka是固定的  
  24. 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


     启动01 eureka,然后修改application.properties,变为02 eureka的配置

[plain] view plain copy
  1. logging.config=classpath:logback.xml  
  2. logging.path=d:/logs  
  3.   
  4. ##tomcat set###  
  5.   
  6. # eureka的默认端口是8761  
  7. server.port=8082  
  8. server.session-timeout=60  
  9. ###########  
  10.   
  11. spring.application.name=eureka-server-02  
  12.   
  13. ####下面2个一定要false,因为这程序是要作为服务端,但是jar中存在eureka-client.jar,所以要false,否则启动会报错的  
  14. #是否注册到eureka  
  15. eureka.client.register-with-eureka=false  
  16. #是否获取注册信息  
  17. eureka.client.fetch-registry=false  
  18.   
  19. #为了便于测试,取消eureka的保护模式,如果启动的话,比如api提供者关闭了,但是eureka仍然保留信息  
  20. eureka.server.enable-self-preservation=false  
  21. #服务名称  
  22. eureka.instance.hostname=02.server.eureka  
  23. #eureka的服务地址,/eureka是固定的  
  24. 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

[html] view plain copy
  1. <project xmlns='http://maven.apache.org/POM/4.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'  
  2.     xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd'>  
  3.     <modelVersion>4.0.0</modelVersion>  
  4.     <groupId>com.fei.springcloud</groupId>  
  5.     <artifactId>springcloud-eureka-server</artifactId>  
  6.     <version>0.0.1-SNAPSHOT</version>  
  7.     <description>eureka服务端</description>  
  8.   
  9.     <!-- 依赖仓库 设置从aliyun仓库下载 -->  
  10.     <repositories>  
  11.         <repository>  
  12.             <id>alimaven</id>  
  13.             <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>  
  14.             <snapshots>  
  15.                 <enabled>true</enabled>  
  16.             </snapshots>  
  17.             <releases>  
  18.                 <enabled>true</enabled>  
  19.             </releases>  
  20.         </repository>  
  21.     </repositories>  
  22.     <!-- 插件依赖仓库 -->  
  23.     <pluginRepositories>  
  24.         <pluginRepository>  
  25.             <id>alimaven</id>  
  26.             <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>  
  27.             <snapshots>  
  28.                 <enabled>true</enabled>  
  29.             </snapshots>  
  30.             <releases>  
  31.                 <enabled>true</enabled>  
  32.             </releases>  
  33.         </pluginRepository>  
  34.     </pluginRepositories>  
  35.   
  36.     <properties>  
  37.   
  38.         <!-- 文件拷贝时的编码 -->  
  39.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  40.         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>  
  41.         <!-- 编译时的编码 -->  
  42.         <maven.compiler.encoding>UTF-8</maven.compiler.encoding>  
  43.   
  44.         <java.version>1.8</java.version>  
  45.         <maven.compiler.source>1.8</maven.compiler.source>  
  46.         <maven.compiler.target>1.8</maven.compiler.target>  
  47.   
  48.     </properties>  
  49.   
  50.     <parent>  
  51.         <groupId>org.springframework.boot</groupId>  
  52.         <artifactId>spring-boot-starter-parent</artifactId>  
  53.         <version>1.5.2.RELEASE</version>  
  54.         <relativePath />  
  55.   
  56.     </parent>  
  57.   
  58.     <dependencies>  
  59.   
  60.         <dependency>  
  61.             <groupId>org.springframework.cloud</groupId>  
  62.             <artifactId>spring-cloud-starter-eureka</artifactId>  
  63.         </dependency>  
  64.   
  65.     </dependencies>  
  66.   
  67.     <dependencyManagement>  
  68.         <dependencies>  
  69.             <dependency>  
  70.                 <groupId>org.springframework.cloud</groupId>  
  71.                 <artifactId>spring-cloud-dependencies</artifactId>  
  72.                 <version>Dalston.RELEASE</version>  
  73.                 <type>pom</type>  
  74.                 <scope>import</scope><!-- 这个不能丢 -->  
  75.             </dependency>  
  76.   
  77.         </dependencies>  
  78.     </dependencyManagement>  
  79.   
  80.     <build>  
  81.         <plugins>  
  82.             <plugin>  
  83.                 <groupId>org.springframework.boot</groupId>  
  84.                 <artifactId>spring-boot-maven-plugin</artifactId>  
  85.             </plugin>  
  86.         </plugins>  
  87.     </build>  
  88.   
  89. </project>  
它和eureka 服务端,有个依赖是不一样的。

application.properties

[plain] view plain copy
  1. logging.config=classpath:logback.xml  
  2. logging.path=d:/logs  
  3.   
  4. ##tomcat set###  
  5.   
  6. # eureka的默认端口是8761  
  7. server.port=9081  
  8. server.session-timeout=60  
  9. ###########  
  10.   
  11. spring.application.name=api-user-server  
  12.   
  13. #像eureka服务注册信息时,使用ip地址,默认使用hostname  
  14. eureka.instance.preferIpAddress=true  
  15. #服务的instance-id默认默认值是${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}} ,  
  16. #也就是机器主机名:应用名称:应用端口  
  17. eureka.instance.instance-id=${spring.cloud.client.ipAddress}:${server.port}  
  18. #eureka的服务地址  
  19. eureka.client.serviceUrl.defaultZone=http://01.server.eureka:8081/eureka/  

Application.java

[java] view plain copy
  1. package com.fei.springcloud;  
  2.   
  3. import org.springframework.boot.SpringApplication;  
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;  
  5. import org.springframework.cloud.netflix.eureka.EnableEurekaClient;  
  6.   
  7. @EnableEurekaClient   
  8. @SpringBootApplication  
  9. public class Application {  
  10.   
  11.     public static void main(String[] args) {  
  12.   
  13.         SpringApplication.run(Application.class, args);  
  14.     }  
  15. }  
@EnableEurekaClient,不管是消费者还是提供者,对应eureka server来说都是客户端client

写个普通的controller,UserProvider.java.提供个根据id获取用户信息的接口

[java] view plain copy
  1. package com.fei.springcloud.provider;  
  2.   
  3. import javax.servlet.http.HttpServletRequest;  
  4.   
  5. import org.springframework.web.bind.annotation.GetMapping;  
  6. import org.springframework.web.bind.annotation.PathVariable;  
  7. import org.springframework.web.bind.annotation.RequestMapping;  
  8. import org.springframework.web.bind.annotation.RestController;  
  9.   
  10. @RestController  
  11. @RequestMapping('/user')  
  12. public class UserProvider {  
  13.   
  14.     @GetMapping(value='/find/{id}')  
  15.     public String find(@PathVariable('id') String id,HttpServletRequest request){  
  16.         //实际项目中,这里可以使用JSONObject,返回json字符串  
  17.         //为了便于测试消费者app的负载均衡,返回服务端端口  
  18.         String s = '张三' '     服务端端口:' request.getLocalPort();  
  19.           
  20.         return s;  
  21.     }  
  22. }  

执行Application.java,将application.properties的端口修改为9082,再次执行

浏览器访问http://01.server.eureka:8081/


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

 app消费者

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

   ribbo负载均衡的app消费者

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


pom.xml

[html] view plain copy
  1. <project xmlns='http://maven.apache.org/POM/4.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'  
  2.     xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd'>  
  3.     <modelVersion>4.0.0</modelVersion>  
  4.     <groupId>com.fei.springcloud</groupId>  
  5.     <artifactId>springcloud-eureka-app-ribbo</artifactId>  
  6.     <version>0.0.1-SNAPSHOT</version>  
  7.     <description>eureka消费者ribbo</description>  
  8.   
  9.     <!-- 依赖仓库 设置从aliyun仓库下载 -->  
  10.     <repositories>  
  11.         <repository>  
  12.             <id>alimaven</id>  
  13.             <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>  
  14.             <snapshots>  
  15.                 <enabled>true</enabled>  
  16.             </snapshots>  
  17.             <releases>  
  18.                 <enabled>true</enabled>  
  19.             </releases>  
  20.         </repository>  
  21.     </repositories>  
  22.     <!-- 插件依赖仓库 -->  
  23.     <pluginRepositories>  
  24.         <pluginRepository>  
  25.             <id>alimaven</id>  
  26.             <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>  
  27.             <snapshots>  
  28.                 <enabled>true</enabled>  
  29.             </snapshots>  
  30.             <releases>  
  31.                 <enabled>true</enabled>  
  32.             </releases>  
  33.         </pluginRepository>  
  34.     </pluginRepositories>  
  35.   
  36.     <properties>  
  37.   
  38.         <!-- 文件拷贝时的编码 -->  
  39.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  40.         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>  
  41.         <!-- 编译时的编码 -->  
  42.         <maven.compiler.encoding>UTF-8</maven.compiler.encoding>  
  43.   
  44.         <java.version>1.8</java.version>  
  45.         <maven.compiler.source>1.8</maven.compiler.source>  
  46.         <maven.compiler.target>1.8</maven.compiler.target>  
  47.   
  48.     </properties>  
  49.   
  50.     <parent>  
  51.         <groupId>org.springframework.boot</groupId>  
  52.         <artifactId>spring-boot-starter-parent</artifactId>  
  53.         <version>1.5.2.RELEASE</version>  
  54.         <relativePath />  
  55.   
  56.     </parent>  
  57.   
  58.     <dependencies>  
  59.   
  60.         <!-- 客户端负载均衡 -->  
  61.         <dependency>  
  62.             <groupId>org.springframework.cloud</groupId>  
  63.             <artifactId>spring-cloud-starter-ribbon</artifactId>  
  64.         </dependency>  
  65.   
  66.         <!-- eureka客户端 -->  
  67.         <dependency>  
  68.             <groupId>org.springframework.cloud</groupId>  
  69.             <artifactId>spring-cloud-starter-eureka</artifactId>  
  70.         </dependency>  
  71.   
  72.         <!-- spring boot实现Java Web服务 -->  
  73.         <dependency>  
  74.             <groupId>org.springframework.boot</groupId>  
  75.             <artifactId>spring-boot-starter-web</artifactId>  
  76.         </dependency>  
  77.   
  78.     </dependencies>  
  79.   
  80.     <dependencyManagement>  
  81.         <dependencies>  
  82.             <dependency>  
  83.                 <groupId>org.springframework.cloud</groupId>  
  84.                 <artifactId>spring-cloud-dependencies</artifactId>  
  85.                 <version>Dalston.RELEASE</version>  
  86.                 <type>pom</type>  
  87.                 <scope>import</scope><!-- 这个不能丢 -->  
  88.             </dependency>  
  89.   
  90.         </dependencies>  
  91.     </dependencyManagement>  
  92.   
  93.     <build>  
  94.         <plugins>  
  95.             <plugin>  
  96.                 <groupId>org.springframework.boot</groupId>  
  97.                 <artifactId>spring-boot-maven-plugin</artifactId>  
  98.             </plugin>  
  99.         </plugins>  
  100.     </build>  
  101.   
  102. </project>  
application.properties
[plain] view plain copy
  1. logging.config=classpath:logback.xml  
  2. logging.path=d:/logs  
  3.   
  4. ##tomcat set###  
  5.   
  6. # eureka的默认端口是8761  
  7. server.port=7081  
  8. server.session-timeout=60  
  9. ###########  
  10.   
  11. spring.application.name=app-user  
  12.   
  13. #像eureka服务注册信息时,使用ip地址,默认使用hostname  
  14. eureka.instance.preferIpAddress=true  
  15. #服务的instance-id默认默认值是${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}} ,  
  16. #也就是机器主机名:应用名称:应用端口  
  17. eureka.instance.instance-id=${spring.cloud.client.ipAddress}:${server.port}  
  18. #eureka的服务地址  
  19. eureka.client.serviceUrl.defaultZone=http://01.server.eureka:8081/eureka/,http://02.server.eureka:8082/eureka/,http://03.server.eureka:8083/eureka/  

UserController.java
[java] view plain copy
  1. package com.fei.springcloud.controller;  
  2.   
  3. import org.springframework.beans.factory.annotation.Autowired;  
  4. import org.springframework.stereotype.Controller;  
  5. import org.springframework.web.bind.annotation.GetMapping;  
  6. import org.springframework.web.bind.annotation.RequestMapping;  
  7. import org.springframework.web.bind.annotation.ResponseBody;  
  8. import org.springframework.web.client.RestTemplate;  
  9.   
  10. @Controller  
  11. @RequestMapping('/user')  
  12. public class UserController {  
  13.   
  14.     @Autowired  
  15.     private RestTemplate restTemplate;  
  16.   
  17.     @GetMapping(value = '/find')  
  18.     @ResponseBody  
  19.     public String find() {  
  20.         //url中对应api提供者的名称,全大写  
  21.         String s = restTemplate.getForEntity('http://API-USER-SERVER/user/find/123', String.class).getBody();  
  22.         return s;  
  23.     }  
  24.       
  25.     /** 
  26.      * 测试下外网,也就是如果域名是外网的,不在eureka注册服务中的,会怎样 
  27.      * @return 
  28.      */  
  29.     @GetMapping(value = '/test')  
  30.     @ResponseBody  
  31.     public String test() {  
  32.         //url中对应api提供者的名称,全大写  
  33.         return restTemplate.getForEntity('http://www.baidu.com/', String.class).getBody();  
  34.     }  
  35. }  
使用restTemplate需要自己拼接url
启动类Application.java
[java] view plain copy
  1. package com.fei.springcloud;  
  2.   
  3. import org.springframework.boot.SpringApplication;  
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;  
  5. import org.springframework.cloud.client.loadbalancer.LoadBalanced;  
  6. import org.springframework.cloud.netflix.eureka.EnableEurekaClient;  
  7. import org.springframework.context.annotation.Bean;  
  8. import org.springframework.web.client.RestTemplate;  
  9.   
  10. @EnableEurekaClient   
  11. @SpringBootApplication  
  12. public class Application {  
  13.   
  14.     @Bean //定义REST客户端,RestTemplate实例  
  15.     @LoadBalanced //开启负债均衡的能力  
  16.     RestTemplate restTemplate() {  
  17.         return new RestTemplate();  
  18.     }  
  19.       
  20.     public static void main(String[] args) {  
  21.   
  22.         SpringApplication.run(Application.class, args);  
  23.     }  
  24. }  
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

[html] view plain copy
  1. <project xmlns='http://maven.apache.org/POM/4.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'  
  2.     xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd'>  
  3.     <modelVersion>4.0.0</modelVersion>  
  4.     <groupId>com.fei.springcloud</groupId>  
  5.     <artifactId>springcloud-eureka-app-feign</artifactId>  
  6.     <version>0.0.1-SNAPSHOT</version>  
  7.     <description>eureka消费者feign</description>  
  8.   
  9.     <!-- 依赖仓库 设置从aliyun仓库下载 -->  
  10.     <repositories>  
  11.         <repository>  
  12.             <id>alimaven</id>  
  13.             <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>  
  14.             <snapshots>  
  15.                 <enabled>true</enabled>  
  16.             </snapshots>  
  17.             <releases>  
  18.                 <enabled>true</enabled>  
  19.             </releases>  
  20.         </repository>  
  21.     </repositories>  
  22.     <!-- 插件依赖仓库 -->  
  23.     <pluginRepositories>  
  24.         <pluginRepository>  
  25.             <id>alimaven</id>  
  26.             <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>  
  27.             <snapshots>  
  28.                 <enabled>true</enabled>  
  29.             </snapshots>  
  30.             <releases>  
  31.                 <enabled>true</enabled>  
  32.             </releases>  
  33.         </pluginRepository>  
  34.     </pluginRepositories>  
  35.   
  36.     <properties>  
  37.   
  38.         <!-- 文件拷贝时的编码 -->  
  39.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  40.         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>  
  41.         <!-- 编译时的编码 -->  
  42.         <maven.compiler.encoding>UTF-8</maven.compiler.encoding>  
  43.   
  44.         <java.version>1.8</java.version>  
  45.         <maven.compiler.source>1.8</maven.compiler.source>  
  46.         <maven.compiler.target>1.8</maven.compiler.target>  
  47.   
  48.     </properties>  
  49.   
  50.     <parent>  
  51.         <groupId>org.springframework.boot</groupId>  
  52.         <artifactId>spring-boot-starter-parent</artifactId>  
  53.         <version>1.5.2.RELEASE</version>  
  54.         <relativePath />  
  55.   
  56.     </parent>  
  57.   
  58.     <dependencies>  
  59.   
  60.         <!-- Feign实现声明式HTTP客户端 -->  
  61.         <dependency>  
  62.             <groupId>org.springframework.cloud</groupId>  
  63.             <artifactId>spring-cloud-starter-feign</artifactId>  
  64.         </dependency>  
  65.   
  66.         <!-- eureka客户端 -->  
  67.         <dependency>  
  68.             <groupId>org.springframework.cloud</groupId>  
  69.             <artifactId>spring-cloud-starter-eureka</artifactId>  
  70.         </dependency>  
  71.   
  72.         <!-- spring boot实现Java Web服务 -->  
  73.         <dependency>  
  74.             <groupId>org.springframework.boot</groupId>  
  75.             <artifactId>spring-boot-starter-web</artifactId>  
  76.         </dependency>  
  77.   
  78.     </dependencies>  
  79.   
  80.     <dependencyManagement>  
  81.         <dependencies>  
  82.             <dependency>  
  83.                 <groupId>org.springframework.cloud</groupId>  
  84.                 <artifactId>spring-cloud-dependencies</artifactId>  
  85.                 <version>Dalston.RELEASE</version>  
  86.                 <type>pom</type>  
  87.                 <scope>import</scope><!-- 这个不能丢 -->  
  88.             </dependency>  
  89.   
  90.         </dependencies>  
  91.     </dependencyManagement>  
  92.   
  93.     <build>  
  94.         <plugins>  
  95.             <plugin>  
  96.                 <groupId>org.springframework.boot</groupId>  
  97.                 <artifactId>spring-boot-maven-plugin</artifactId>  
  98.             </plugin>  
  99.         </plugins>  
  100.     </build>  
  101.   
  102. </project>  

application.properties和上面一样
[plain] view plain copy
  1. logging.config=classpath:logback.xml  
  2. logging.path=d:/logs  
  3.   
  4. ##tomcat set###  
  5.   
  6. # eureka的默认端口是8761  
  7. server.port=7081  
  8. server.session-timeout=60  
  9. ###########  
  10.   
  11. spring.application.name=app-user  
  12.   
  13. #像eureka服务注册信息时,使用ip地址,默认使用hostname  
  14. eureka.instance.preferIpAddress=true  
  15. #服务的instance-id默认默认值是${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}} ,  
  16. #也就是机器主机名:应用名称:应用端口  
  17. eureka.instance.instance-id=${spring.cloud.client.ipAddress}:${server.port}  
  18. #eureka的服务地址  
  19. eureka.client.serviceUrl.defaultZone=http://01.server.eureka:8081/eureka/,http://02.server.eureka:8082/eureka/,http://03.server.eureka:8083/eureka/  

增加个UserService.java接口类
[java] view plain copy
  1. package com.fei.springcloud.service;  
  2.   
  3. import org.springframework.cloud.netflix.feign.FeignClient;  
  4. import org.springframework.web.bind.annotation.GetMapping;  
  5. import org.springframework.web.bind.annotation.PathVariable;  
  6.   
  7. @FeignClient('API-USER-SERVER')  
  8. public interface UserService {  
  9.   
  10.     @GetMapping(value='/user/find/{id}')  
  11.     String find(@PathVariable('id') String id);  
  12. }  
UserController.java
[java] view plain copy
  1. package com.fei.springcloud.controller;  
  2.   
  3. import org.springframework.beans.factory.annotation.Autowired;  
  4. import org.springframework.stereotype.Controller;  
  5. import org.springframework.web.bind.annotation.GetMapping;  
  6. import org.springframework.web.bind.annotation.RequestMapping;  
  7. import org.springframework.web.bind.annotation.ResponseBody;  
  8.   
  9. import com.fei.springcloud.service.UserService;  
  10.   
  11. @Controller  
  12. @RequestMapping('/user')  
  13. public class UserController {  
  14.   
  15.     @Autowired  
  16.     private UserService userService;  
  17.   
  18.     @GetMapping(value = '/find')  
  19.     @ResponseBody  
  20.     public String find() {  
  21.         //url中对应api提供者的名称,全大写  
  22.         String s = userService.find('123');  
  23.         return s;  
  24.     }  
  25.       
  26.     
  27. }  

浏览器访问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配置文件中加入

[plain] view plain copy
  1. #ribbo负载均衡策略配置,默认是依次轮询  
  2. 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一样的反向代理功能,还提供了负载均衡、监控、过滤等功能,在后面学习zuul的时候,我们再学习。


   docker k8s实现的devOps平台(paas平台),构建好镜像后,部署的时候,k8s负责调控资源,将docker分配到不同的节点服务器,同时将docker的ip相关信息更新到nginx。这是自动化的,不需要开发人员手动操作docker,nginx配置。

版权声明: http://blog.csdn.net/dream_broken/article/details/76148513
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
从零搭建 Spring Cloud 服务(超级详细)
史上最简单的SpringCloud教程 | 第十一篇: docker部署spring cloud项目
springcloud(第三篇)springcloud eureka 服务注册与发现
使用Spring Cloud Eureka实现服务注册与发现
SpringCloud 第十九章:Spring Cloud 组件 Docker 化
Spring Cloud 升级最新 Finchley 版本,踩了所有的坑!
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服