写写吧,这个项目配置搞的我着实有点火大,折腾了2天时间配置maven的pom文件。
背景:基于springboot技术,没有使用spring cloud全家桶,而是使用的grpc+consul的方式进行开发,原因是经过实测,grpc性能好于spring cloud全家桶,另外spring cloud全家桶开发的时候微服务调用代码编写比较麻烦,不如grpc可以直接一键自动生成,除了性能、开发麻烦,还有grpc支持异构语言,后期不管是用go语言开发服务供java调用,还是java开发服务供go等进行调用都很方便。
既然选择了不用spring cloud全家桶,服务发现与注册、健康检查、负载均衡这些就都需要找到对应的处理方法,这里使用的是国人开发的grpc-spring-boot-starter,项目地址为https://github.com/yidongnan/grpc-spring-boot-starter 。
项目使用IDEA进行创建,分别建立了几个子项目,基础项目的maven配置参数如下:
4.0.0
XXXX
XXXX
1.0-SNAPSHOT
xxx_rpc
xxx_service
xxx_web
xxx_client
org.springframework.boot
spring-boot-starter-parent
2.1.6.RELEASE
pom
XXXX
UTF-8
1.7
1.7
1.7.16
1.23.0
org.slf4j
slf4j-api
${slf4j.version}
io.grpc
grpc-all
${grpc.version}
io.grpc
grpc-netty
${grpc.version}
io.grpc
grpc-api
${grpc.version}
io.grpc
grpc-stub
${grpc.version}
io.grpc
grpc-auth
${grpc.version}
io.grpc
grpc-context
${grpc.version}
io.grpc
grpc-core
${grpc.version}
io.grpc
grpc-protobuf
${grpc.version}
io.grpc
grpc-services
${grpc.version}
io.grpc
grpc-protobuf-lite
${grpc.version}
io.grpc
grpc-protobuf-services
${grpc.version}
io.grpc
grpc-protobuf-stub
${grpc.version}
io.grpc
grpc-netty-shaded
${grpc.version}
com.google.protobuf
protobuf-java
3.9.1
net.devh
grpc-spring-boot-starter
2.5.1.RELEASE
io.grpc
grpc-netty-shaded
net.devh
grpc-server-spring-boot-starter
2.5.1.RELEASE
io.grpc
grpc-netty-shaded
com.google.guava
guava
20.0
io.netty
netty-all
4.1.39.Final
io.netty
netty-tcnative-boringssl-static
2.0.25.Final
junit
junit
4.11
test
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
com.alibaba
fastjson
1.2.58
javax.servlet
javax.servlet-api
provided
javax.servlet
jstl
org.apache.poi
poi
3.12
org.apache.poi
poi-ooxml
3.12
com.belerweb
pinyin4j
2.5.0
org.apache.httpcomponents
httpclient
4.5.3
commons-collections
commons-collections
3.2.1
XXXX
maven-clean-plugin
3.1.0
maven-resources-plugin
3.0.2
maven-compiler-plugin
3.8.0
maven-surefire-plugin
2.22.1
maven-war-plugin
3.2.2
maven-install-plugin
2.5.2
maven-deploy-plugin
2.8.2
基础父项目配置内容就是上面这些,看上去稀松平常,这可是跳了数个坑才得到的结果,具体包括:grpc-spring-boot-starter这个项目,2.5.1版本引用的是grpc的1.22.2版本,然后grpc 1.22.2版本会自动加载一个叫做grpc-netty-shaded.jar的文件,不知道什么原因,只要类搜索路径里面有这个文件,一启动项目就报错,这玩意好像是想在它的所在路径下面找一堆jar依赖,这是第一个坑。第二个坑是com.google.guava这个包,最新版有些类已经移除掉了,也不知道是哪个jar依赖了这个东西,经过反复试验,grpc 1.23.0配合这个20.0版本是没有问题的。
其他还有找不到grpc-Channel之类的坑,后面慢慢说吧。
下面是grpc接口proto文件所在的项目,这些.proto文件需要经过protobuf插件编译以后才能使用,所以这个子项目的配置内容如下:
XXXX
XXXX
1.0-SNAPSHOT
../pom.xml
4.0.0
xxx_rpc
1.0-SNAPSHOT
jar
shinow_rpc
UTF-8
1.8
1.8
junit
junit
4.11
test
io.grpc
grpc-all
xxx_rpc
org.apache.maven.plugins
maven-surefire-plugin
true
org.xolstice.maven.plugins
protobuf-maven-plugin
0.6.1
com.google.protobuf:protoc:3.9.1:exe:${os.detected.classifier}
grpc-java
io.grpc:protoc-gen-grpc-java:1.23.0:exe:${os.detected.classifier}
${project.basedir}/src/main/proto
${project.basedir}/src/main/java
false
compile
compile
compile-custom
kr.motd.maven
os-maven-plugin
1.6.0
这个子项目没有什么坑,要说有的话就是项目路径不能有中文,必须把项目建到英文路径下面才能正常执行。
然后是提供微服务的项目,项目pom.xml文件内容如下:
XXXX
XXXX
1.0-SNAPSHOT
../pom.xml
4.0.0
xxx_service
xxx_service
${project.packaging}
UTF-8
1.7
1.7
true
dev
true
jar
release
war
org.springframework.boot
spring-boot-starter-web
spring-boot-starter-tomcat
org.springframework.boot
javax.servlet
javax.servlet-api
3.1.0
provided
org.apache.tomcat.embed
tomcat-embed-jasper
provided
javax.servlet
javax.servlet-api
provided
javax.servlet.jsp
javax.servlet.jsp-api
2.3.1
provided
javax.servlet
jstl
provided
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-jdbc
org.springframework.boot
spring-boot-starter-actuator
junit
junit
4.11
test
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.0.0
tk.mybatis
mapper-spring-boot-starter
2.1.5
com.github.pagehelper
pagehelper-spring-boot-starter
1.2.10
org.mybatis.spring.boot
mybatis-spring-boot-starter
org.postgresql
postgresql
42.2.6
com.alibaba
druid
1.1.0
org.springframework.cloud
spring-cloud-starter-consul-discovery
2.1.2.RELEASE
net.devh
grpc-server-spring-boot-starter
io.grpc
grpc-netty-shaded
net.devh
grpc-spring-boot-starter
io.grpc
grpc-netty-shaded
XXXX
xxx_rpc
1.0-SNAPSHOT
XXXX
xxx_utils
1.0-SNAPSHOT
XXXX
xxx_common
1.0-SNAPSHOT
com.github.pagehelper
pagehelper-spring-boot-starter
1.2.10
org.springframework.boot
spring-boot-devtools
true
true
org.apache.tomcat.embed
tomcat-embed-jasper
javax.servlet
javax.servlet-api
javax.servlet.jsp
javax.servlet.jsp-api
2.3.1
javax.servlet
jstl
io.grpc
grpc-all
io.grpc
grpc-services
io.grpc
grpc-netty
xxx_service
org.springframework.boot
spring-boot-maven-plugin
maven-clean-plugin
3.1.0
maven-resources-plugin
3.0.2
maven-compiler-plugin
3.8.0
-Xlint:-path
maven-surefire-plugin
2.22.1
maven-war-plugin
3.2.2
maven-install-plugin
2.5.2
maven-deploy-plugin
2.8.2
src/main/webapp
META-INF/resources
**/**
src/main/resources
**/*.*
src/main/java
**/*.xml
配置文件内容没有太特殊的,然后是springboot的项目启动配置文件参数文件,内容如下:
#开发配置
spring.output.ansi.enabled: always
spring:
jmx:
default-domain: xxx_service
application:
name: xxx_service
sleuth:
sampler:
probability: 1
cloud:
consul:
host: 127.0.0.1
port: 8500
discovery:
prefer-ip-address: true
healthCheckPath: /actuator/health
healthCheckInterval: 10s
instance-id: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
serviceName: xxx-${spring.application.name}
logging:
config: classpath:logback-dev.xml
server:
port: 8082
grpc:
server:
port: 9090
看到最后那个grpc.server.port=9090没有,你要是不写,项目启动的时候它也会去9090端口进行监听,但是,微服务的调用端是无法知道到哪个端口去进行grpc调用的,必须把上面那个配置参数写上以后微服务的调用端才能知道去9090端口找微服务,巨坑!因为这个差点就放弃grpc+consul的方案了,因为consul去检查服务健康状态是基于8082端口去检测的,当时就特别纳闷,grpc的调用端怎么才能知道去到9090端口找微服务进行调用呢,写上这个参数以后再去consul里面看,会多出来一个TAG,里面注明了grpc服务端口在9090。
然后是调用端,这边就比较简单了,子项目pom.xml文件内容如下:
XXXX
XXXX
1.0-SNAPSHOT
../pom.xml
4.0.0
1.0-SNAPSHOT
xxx_web
${project.packaging}
xxx_web
UTF-8
1.8
1.8
1.3.1
true
dev
true
jar
release
war
org.springframework.boot
spring-boot-starter-web
spring-boot-starter-tomcat
org.springframework.boot
javax.servlet
javax.servlet-api
3.1.0
provided
org.apache.tomcat.embed
tomcat-embed-jasper
provided
javax.servlet
javax.servlet-api
provided
javax.servlet.jsp
javax.servlet.jsp-api
2.3.1
provided
javax.servlet
jstl
provided
junit
junit
4.11
test
org.springframework.cloud
spring-cloud-starter-consul-discovery
2.1.1.RELEASE
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
2.1.6.RELEASE
commons-fileupload
commons-fileupload
${commons.fileupload.version}
XXXX
xxx_rpc
1.0-SNAPSHOT
XXXX
xxx_common
1.0-SNAPSHOT
XXXX
xxx_utils
1.0-SNAPSHOT
XXXX
xxx_power
1.0-SNAPSHOT
XXXX
xxx_client
1.0-SNAPSHOT
org.springframework.boot
spring-boot-starter-tomcat
provided
javax.servlet
jstl
org.apache.tomcat.embed
tomcat-embed-jasper
org.sitemesh
sitemesh
3.0.1
org.springframework.boot
spring-boot-devtools
true
true
commons-collections
commons-collections
3.2.2
org.springframework.boot
spring-boot-starter-data-redis
net.devh
grpc-client-spring-boot-starter
2.5.1.RELEASE
io.grpc
grpc-netty-shaded
com.google.guava
guava
io.netty
netty-all
io.netty
netty-tcnative-boringssl-static
io.grpc
grpc-all
io.grpc
grpc-netty
io.grpc
grpc-api
io.grpc
grpc-stub
io.grpc
grpc-auth
io.grpc
grpc-context
io.grpc
grpc-core
io.grpc
grpc-protobuf
io.grpc
grpc-services
io.grpc
grpc-protobuf-lite
io.grpc
grpc-protobuf-services
io.grpc
grpc-protobuf-stub
xxx_web
maven-clean-plugin
3.1.0
maven-resources-plugin
3.1.0
copy-resources
compile
copy-resources
${project.parent.basedir}/target/classes
src/main/webapp
META-INF/resources
**/**
src/main/resources
true
**/*
maven-compiler-plugin
3.8.0
maven-surefire-plugin
2.22.1
maven-war-plugin
3.2.2
maven-install-plugin
2.5.2
maven-deploy-plugin
2.8.2
org.springframework.boot
spring-boot-maven-plugin
true
src/main/webapp
META-INF/resources
**/**
src/main/resources
**/*
然后项目的application.yml文件内容如下:
server:
port: 8081
jsp-servlet:
servlet:
context-path: /xxxx
jsp:
class-name: org.apache.jasper.servlet.JspServlet
spring:
jmx:
default-domain: xxx_web
application:
name: xxx_web
mvc:
view:
prefix: /WEB-INF/views/
suffix: .jsp
resources:
static-locations: classpath:/static/
sleuth:
sampler:
probability: 1
#cloud配置
cloud:
consul:
host: 127.0.0.1
port: 8500
discovery:
prefer-ip-address: true
#热部署配置
devtools:
restart:
enabled: true
exclude: WEB-INF/**
additional-paths: src/main/java
#上传文件大小配置
servlet:
multipart:
enabled: true
#单个文件最大
max-file-size: 30MB
#上传数据总大小
max-request-size: 10GB
redis:
host: 127.0.0.1
port: 6379
password:
jedis:
pool:
max-active: 8
max-idle: 0
max-wait: -1
logging:
config: classpath:logback-dev.xml
# Grpc配置
grpc:
client:
xxx-xxx-service: #这个名称需要和consul里面的服务名称一致
enableKeepAlive: true
keepAliveWithoutCalls: true
negotiationType: plaintext
#springboot自动装配控制台输出级别设置为error
logging.level.org.springframework.boot: DEBUG
logging.level.org.springframework.boot.autoconfigure: DEBUG
项目跑起来以后访问consul,里面可以看到注册的微服务名称及提供服务的IP地址,可以看到健康检查的情况,客户端需要访问微服务时,会自动从可用的微服务里面进行负载均衡调用,客户端会每隔10秒自动检测服务的可用性,发现服务不可用时就通过其他服务进行微服务调用。