代码已上传至: 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的环境,详见:
使用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程序模拟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()
创建一个springboot程序,修改pom文件如下:
4.0.0
org.test
eureka
0.0.1-SNAPSHOT
jar
eureka
Demo project for Spring Boot
org.springframework.boot
spring-boot-starter-parent
1.2.5.RELEASE
UTF-8
1.8
org.springframework.boot
spring-boot-starter-actuator
org.springframework.cloud
spring-cloud-starter-eureka-server
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-test
RELEASE
org.springframework
spring-test
RELEASE
org.springframework.cloud
spring-cloud-starter-parent
Angel.SR3
pom
import
org.springframework.boot
spring-boot-maven-plugin
修改application.properties配置文件
server.port=8761
eureka.client.fetch-registry=false
eureka.client.register-with-eureka=false
最后,我们在EurekaApplication中添加注解@EnableEurekaServer
,开启服务的注册中心
项目目录结构如下:
创建一个springboot程序,修改pom文件如下:
4.0.0
org.test
configserver
0.0.1-SNAPSHOT
jar
configserver
Demo project for Spring Boot
org.springframework.boot
spring-boot-starter-parent
1.2.5.RELEASE
UTF-8
1.8
org.springframework.boot
spring-boot-starter-actuator
org.springframework.cloud
spring-cloud-config-server
org.springframework.security
spring-security-rsa
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-eureka
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-test
RELEASE
org.springframework
spring-test
RELEASE
org.springframework.cloud
spring-cloud-starter-parent
Angel.SR3
pom
import
org.springframework.boot
spring-boot-maven-plugin
修改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
项目目录如下:
开始编写一个为php应用对接的sidecar程序
同样,这是一个springboot程序,我们先改写pom.xml文件
4.0.0
org.test
sidecar
0.0.1-SNAPSHOT
jar
sidecar
Demo project for Spring Boot
org.springframework.boot
spring-boot-starter-parent
1.2.5.RELEASE
UTF-8
1.8
org.springframework.boot
spring-boot-starter-actuator
org.springframework.cloud
spring-cloud-starter-config
org.springframework.cloud
spring-cloud-starter-eureka
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-netflix-sidecar
org.springframework.boot
spring-boot-starter-test
test
org.springframework
spring-test
RELEASE
org.springframework.boot
spring-boot-test
RELEASE
org.springframework.cloud
spring-cloud-starter-parent
Angel.SR3
pom
import
org.springframework.boot
spring-boot-maven-plugin
然后在程序中开启@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的思想。
项目结构:
创建一个为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