SpringCloud整合php、python樣本
代碼已上傳至: https://github.com/KeoZmy/SpringCloudDemo.git ,部落格中沒有寫到網關 zuul,但是git中已上傳 前言
最近一直在花時間研究微服務,各種開源組件組合一個framework到最後決定用springcloud這樣成熟的framework。不得不說,springcloud確實很強大,還有Pivotal和Netfix是其強大的後盾與技術輸出。最後還是選用了springcloud的netfix作為核心的開發。
springcloud中的sidecar是出於netfix中prana的啟發,正如官方reference所說:
Do you have non-jvm languages you want to take advantage of Eureka, Ribbon and Config Server? The Spring Cloud Netflix Sidecar was inspired by Netflix Prana. It includes a simple http api to get all of the instances (ie host and port) for a given service. You can also proxy service calls through an embedded Zuul proxy which gets its route entries from Eureka. The Spring Cloud Config Server can be accessed directly via host lookup or through the Zuul Proxy. The non-jvm app should implement a health check so the Sidecar can report to eureka if the app is up or down
你是否有非jvm語言應用程式需要使用Eureka, Ribbon和Config Server的功能? Spring Cloud Netflix Sidecar 受 Netflix Prana 啟發. 它包含一個簡單的HTTP API去擷取所有註冊的執行個體資訊(包括host和port資訊). 你也可以通過依賴Eureka的嵌入式Zuul代理器代理服務調用. The Spring Cloud Config Server可以通過host尋找 或Zuul代理直接進入. 非JVM應用程式提供健全狀態檢查實現即可讓Sidecar向eureka同步應用程式up還是down.
簡單的說,一個非jvm程式,如:php、python等,想要註冊到eureka,但是應用都是一堆別的語言寫的,那我應該如何?呢。Sidecar的原理就是偵聽該應用所啟動並執行連接埠,然後檢測該程式的運行狀態,官方的描述會更形象一些:
實現
本文主要是參考官方給出結合python的例子,樣本了一個springcloud結合php、python的例子。 php準備
先準備一下php的環境,詳見:
使用WAMP快速搭建PHP Web開發環境
(ps:我沒有做過php的相關開發,只是最近參與公司項目的重構,裡面以java代碼為主但是也有python、php的模組,自己快速搭建了一個php的demo做測試,如果你是專業的php developer你當然可以選擇你自己的方式)
我的wamp伺服器www目錄:
health.json就是非JVM應用程式提供模仿SpringBoot健全狀態檢查介面的可訪問的uri. 它應該返回一個json文檔類似如下:
`{"status":"UP"}`
by the way,我把伺服器的連接埠改成了3000,預設的是80
如何修改wamp預設80連接埠 python準備(python大神請隨意)
這邊主要是寫了一個python程式類比web應用的運行,這個應用佔用的連接埠為5680
import httplibfrom twisted.web import server, resourcefrom twisted.internet import reactor, endpointsclass Health(resource.Resource): isLeaf = True def render_GET(self, request): request.setHeader("content-type", "application/json") return '{"status":"UP"}\n'class Fortune(resource.Resource): isLeaf = Truedef render_GET(self, request): conn = httplib.HTTPConnection('localhost', 5678) conn.request("GET", "/fortunes") res = conn.getresponse() fortune = res.read() request.setHeader("content-type", "text/plain") return fortuneroot = resource.Resource()root.putChild('health', Health()) root.putChild('', Fortune())endpoints.serverFromString(reactor, "tcp:5680").listen(server.Site(root))reactor.run()
Eureka
建立一個springboot程式,修改pom檔案如下:
<?xml version="1.0" encoding="UTF-8"?> <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>org.test</groupId><artifactId>eureka</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>eureka</name><description>Demo project for Spring Boot</description><parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.2.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --></parent><properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version></properties><dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-test</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>RELEASE</version> </dependency></dependencies><dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-parent</artifactId> <version>Angel.SR3</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設定檔
server.port=8761eureka.client.fetch-registry=falseeureka.client.register-with-eureka=false
最後,我們在EurekaApplication中添加註解@EnableEurekaServer,開啟服務的註冊中心
項目目錄結構如下:
Configserver
建立一個springboot程式,修改pom檔案如下:
<?xml version="1.0" encoding="UTF-8"?><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>org.test</groupId><artifactId>configserver</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>configserver</name><description>Demo project for Spring Boot</description><parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.2.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --></parent><properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version></properties><dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> <exclusions> <exclusion> <groupId>org.springframework.security</groupId> <artifactId>spring-security-rsa</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-test</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>RELEASE</version> </dependency></dependencies><dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-parent</artifactId> <version>Angel.SR3</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設定檔:
server.port=8888 spring.cloud.config.server.git.uri=https://github.com/spencergibb/oscon-config-repo
這裡還有一個設定檔bootstrap.properties:
server.port=5678sidecar.port=3000sidecar.health-uri=http://localhost:${sidecar.port}/phpTest/health.json
項目目錄如下:
sidecar for php
開始編寫一個為php應用對接的sidecar程式
同樣,這是一個springboot程式,我們先改寫pom.xml檔案
<?xml version="1.0" encoding="UTF-8"?><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>org.test</groupId><artifactId>sidecar</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>sidecar</name><description>Demo project for Spring Boot</description><parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.2.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --></parent><properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version></properties><dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-netflix-sidecar</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-test</artifactId> <version>RELEASE</version> </dependency></dependencies><dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-parent</artifactId> <version>Angel.SR3</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>
然後在程式中開啟@EnableSidecar
最後,關鍵性的一步,我們改寫application.properties檔案
server.port=5678 sidecar.port=3000sidecar.health-uri=http://localhost:${sidecar.port}/phpTest/health.json
server.port=5678 指定了這個sidecar運行時所佔用的連接埠
sidecar.port=3000 指定了sidecar監聽非jvm應用程式的連接埠,就是我們的php程式所掛載的伺服器,之前我已經把伺服器連接埠改成3000了
sidecar.health-uri=http://localhost:${sidecar.port}/phpTest/health.json指定了php程式返回給sidecar的健康指標狀態,我這裡是通過檔案的返回,當然你也可以通過RESTAPI,如果程式沒有正常掛起,sidecar自然不能進行健康監測訪問health.json(或者health方法),拿不到up,所以在註冊中心則會顯示一個douwn的狀態,表示程式沒有正常掛起,這就是sidecar的思想。
項目結構:
sidecar for python
建立一個為python對接的sidecar,步驟和上面建立為php的如出一轍,只是設定檔有些許的不同
server.port=5688sidecar.port=5680sidecar.health-uri=http://localhost:${sidecar.port}/health
開頭我們所準備的python應用佔用的就是5680連接埠,這裡拿到健康狀態的監測是通過RESTAPI
總體模組:
運行程式
只要php服務和python服務的開啟在兩個sidecar開啟之前就好
JAVA程式的啟動順序為(從左至右):
我們訪問http://localhost:8761/可以看到:
兩個非jvm語言的程式應用已經成功註冊到eureka,並且是up的狀態
我們關閉其中的一個python服務,可以看到:
php和python服務已經如同springboot程式一樣,關閉即down,可以在註冊中心看到它的運行狀態了。 總結
SideCar的設計很優雅,它完全不會去入侵其他應用的代碼。就像一個代理一樣,它始終觀察著應用的運行(它的健康狀態),本質上註冊到eureka的是sidecar,但是它所顯示的狀態卻是它所監測的應用。只要php、python..等為其提供一個health監測的介面即可。
代碼已上傳至: https://github.com/KeoZmy/SpringCloudDemo.git