首先,這篇文章參考的是http://blog.didispace.com/springcloud5/這位大牛的博客。本人是通過這篇博客來學習zuul的,現在寫的博客只是個人在學習時個人的一些感受和理解。
談到spring cloud,就要提及到其核心組件:zuul組件,這個組件其實功能很多,比如反向代理,負載均衡還有權限控制等功能,這篇博客主要寫的是zuul的反向代理和負載均衡。
首先是進行eureka的實現,代碼如下:
首先是pom.xml,添加依賴:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> <version>1.3.2.RELEASE</version> </dependency>
然后是application:
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer @SpringBootApplication public class EurekaApplication { public static void main(String[] args) { new SpringApplicationBuilder(EurekaApplication.class).web(true).run(args); } }
接着是配置文件:
server.port=1111 #eureka.instance.hostname=localhost eureka.client.register-with-eureka=false eureka.client.fetch-registry=false eureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/
創建好eureka后,則是實現zuul:
首先是添加pom.xml文件的依賴:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> <version>1.3.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> <version>1.3.2.RELEASE</version> </dependency>
然后是具體的實現,也非常簡單:
@EnableZuulProxy
@SpringCloudApplication
public class ZuulApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(ZuulApplication.class).web(true).run(args);
}
}
接下來是配置文件:
spring.application.name=api-gateway server.port=5555 # routes to serviceId 這里邊是通過serviceid來綁定地址,當在路徑后添加/api-a/ 則是訪問service-A對應的服務。 zuul.routes.api-a.path=/api-a/** zuul.routes.api-a.serviceId=service-A zuul.routes.api-b.path=/api-b/** zuul.routes.api-b.serviceId=service-B # routes to url 這里是綁定具體的ip地址 zuul.routes.api-a-url.path=/api-a-url/** zuul.routes.api-a-url.url=http://localhost:2222/ eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
那么,其實在配置完這個配置文件后,其實zuul已經實現了反向代理和負載均衡的兩個功能了,可能有人這時候就納悶了,這里不是只是反向代理了嗎?怎么實現負載均衡呢?其實zuul實現負載均衡很簡單,使用serviceId進行綁定后,如果有多個相同的serviceid,則會進行輪詢的方式進行訪問。這個在下文會有具體的結果截圖。
現在需要開啟建立兩個服務,具體的操作為實現a+b的操作,第一個為Service-A。
pom.xml中添加:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> <version>1.3.2.RELEASE</version> </dependency>
然后是配置文件:
spring.application.name=service-A
server.port=2224
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
然后是一個客戶端和一個controller:
package com.example; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @EnableDiscoveryClient @SpringBootApplication public class ControllerApplicationA { public static void main(String[] args) { new SpringApplicationBuilder(ControllerApplicationA.class).web(true).run(args); } }
package com.example.web; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.*; @RestController public class ComputeController { @Autowired private DiscoveryClient client; @RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.GET) public String add(@PathVariable Integer a,@PathVariable Integer b) { System.out.println("host:"+client.getLocalServiceInstance().getHost()+" -----port:"+client.getLocalServiceInstance().getPort()); return a+b+" ------ host:"+client.getLocalServiceInstance().getHost()+" -----port:"+client.getLocalServiceInstance().getPort(); } }
這個客戶端的代碼是用來進行具體的操作的,在這中間我們在返回值中添加具體的服務器地址和端口號。
以同樣的方式再建立一個服務Service-B。
然后先啟動兩個服務,截圖如下:
這時候先不要急着訪問Service-A和B,我們將service-A和B中的配置文件中的端口號修改后再啟動:
結果如下:
這時候我們看到了,serviceid為Service-A和B各有兩個,那么接下來則是實驗zuul負載均衡的時候了,我們在此只測試Service-A:
第一次訪問http://localhost:5555/api-a/add/1/2:
第二次訪問:
因此這就實現了負載均衡,但是這個負載均衡是屬於客戶端的負載均衡。在這我也就簡要的說下客戶端負載均衡。
客戶端負載均衡:
基於客戶端的負載均衡,簡單的說就是在客戶端程序里面,自己設定一個調度算法,在向服務器發起請求的時候,先執行調度算法計算出向哪台服務器發起請求,然后再發起請求給服務器。
特點:
- 由客戶端內部程序實現,不需要額外的負載均衡器軟硬件投入。
- 程序內部需要解決業務服務器不可用的問題,服務器故障對應用程序的透明度小。
- 程序內部需要解決業務服務器壓力過載的問題。
使用場景:
- 可以選擇為初期簡單的負載均衡方案,和DNS負載均衡一樣。
- 比較適合於客戶端具有成熟的調度庫函數,算法以及API等
- 畢竟適合對服務器入流量較大的業務,如HTTP POST文件上傳,FTP文件上傳,Memcache大流量寫入。
- 可以結合其他負載均衡方案進行架構。