SpringCloud微服務部署

微服務的其中一個特色就是有許許多的粒度小(功能單一,好比用戶管理,短信發送管理,郵件發送管理,文件管理等)、能獨立部署、擴展、運行的小應用,能夠稱爲api,也就是服務提供者。api之間能夠相互調用,但更多的是供app調用,好比學生管理系統,它是面向用戶的,是許許多多功能的集合體,它須要調用許多api完成業務功能,因此這學生管理系統能夠稱爲app。java

eureka的做用

傳統的單體應用開發,就是將api和app的代碼所有集成在一塊兒,在同一個進程中運行,對應java web通俗的說就是所有打包在一個war中部署在一個tomcat中運行。而微服務的每一個api,app都擁有本身的進程,也就是都有本身的tomcat,某個api掛了,不影響其餘api和app運行。nginx

clipboard.png

api是採起restfull風格暴漏出去的,因此app(api)調用api時,採起http://ip:端口這形式進行通信。那麼問題來了,若是有不少app都調用了某個api,若是api的ip或端口發生了更改,若是app中對api的ip和端口等信息是寫在配置文件的,難道要通知每一個app,說這個api的地址和端口變了,app要進行修改從新編譯部署(這是舉例子而已,實際狀況有些企業對常量的配置可能寫配置文件,也可能寫數據庫)。這太麻煩了,若是api的地址和端口有發生變化,app能及時獲知自行變動,那就行了。還有個弊端,就是api是否掛了,也無法直觀觀察到。web

因此,若是在app和api之間增長個服務管理中心,api像服務管理中心註冊信息,app從服務管理中心獲取api的信息,api有個惟一標識,api有變動的時候通知服務管理中心,服務管理中心通知相關的app或者app定時從服務管理中心獲取最新的api信息,同時服務管理中心具備很高的穩定性、可靠性。spring

eureka就是爲了這樣的一個服務管理中心,下面是我根據本身的理解畫的一張圖。docker

clipboard.png

下面這張是官方的架構圖數據庫

clipboard.png

1.Application Service 至關於服務提供者/apiapache

2.Application Client 至關於服務消費者/appjson

3.Make Remote Call,其實就是實現服務的使用/好比httpClient,restTemplate後端

4.us-east-1 Eureka 集羣服務api

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,則填寫0二、03的地址和端口;若是是02,則填寫0一、03的地址和端口,也就是說讓01,02,03這3個eureka服務能相互間同步數據,若是是01->02->03->01,則api提供者註冊信息到01時,01會同步數據到02,但02不會同步到03,01也不會同步到03,也就是說03缺數據了。看源碼,服務的註冊信息不會被二次傳播,看PeerAwareInstanceRegistryImpl.java

clipboard.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/)看到

clipboard.png

api提供者

建立個普通的maven項目eureka-api,該api是個用戶服務提供者。採起spring boot開發模式

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

clipboard.png

Application就是文件中定義的spring.application.name=api-user-server,它會自動轉爲大寫

若是想免費學習Java工程化、高性能及分佈式、深刻淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友能夠加個人Java進階羣:478030634,羣裏有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給你們。

app消費者

在Spring Cloud Netflix中,使用Ribbon實現客戶端負載均衡,使用Feign實現聲明式HTTP客戶端調用——即寫得像本地函數調用同樣.

clipboard.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服務

clipboard.png

瀏覽器訪問http://127.0.0.1:7081/user/find

看到信息「張三 服務端端口:9081」,刷新瀏覽器看到「張三 服務端端口:9082」,說明的確是有負載均衡。

可是訪問外網的時候,http://127.0.0.1:7081/user/test,也就是域名不在eureka註冊過的,就不行了。

clipboard.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負載均衡策略選擇

clipboard.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同樣的反向代理功能,還提供了負載均衡、監控、過濾等功能,在後面學習zuul的時候,咱們再學習。

若是想免費學習Java工程化、高性能及分佈式、深刻淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友能夠加個人Java進階羣:478030634,羣裏有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給你們。

clipboard.png

docker+k8s實現的devOps平臺(paas平臺),構建好鏡像後,部署的時候,k8s負責調控資源,將docker分配到不一樣的節點服務器,同時將docker的ip相關信息更新到nginx。這是自動化的,不須要開發人員手動操做docker,nginx配置。

相關文章
相關標籤/搜索