SpringCloud整合php、python示例

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 httplib

from twisted.web import server, resource
from twisted.internet import reactor, endpoints

class 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 = True

def 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 fortune


root = 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=8761
eureka.client.fetch-registry=false
eureka.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=5678
sidecar.port=3000
sidecar.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=3000
sidecar.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=5688
sidecar.port=5680
sidecar.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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章