线上应用SpringCloud实践

技术选型

首先讲下技术选型,在微服务领域两大巨头,Dubbo和SpringCloud,近期关注微服务的朋友们可能知道,例如Erueka,Hystrix,Zuul这些貌似都已经停止更新了,虽然他们官网上说,现有的版本已经满足现有的需求,但软件领域,睡一觉就是另一个样,但好在,Spring积极在解决这些问题,基本上也都有替代品,比如全套的阿里系微服务spring-cloud-alibaba。

为什么放弃dubbo这个微服务框架呢,首先第一点,dubbo基于RPC通信,类似thrift,用过thrift的朋友,都知道,虽然thrift这个框架非常厉害,它可以调用其他语言的服务,java调python啊,python调c啊这些,而且性能非常不错。但有一点,一旦你的接口有变动,那所有涉及到这个接口的实现服务,都需要重新生成一遍对应语言的接口并依赖新生成的接口完成实现,实在是非常麻烦

Dubbo没有thrift那么麻烦,但如果新加入了接口类,就一定要在提供方和调用方同时配置一堆东西,如果分组开发,由此产生的沟通成本将非常昂贵,我们项目要求快速迭代,因此,放弃Dubbo的RPC协议,使用基于Http的Sping Cloud体系,而且由业务推倒,后期服务可能不会过于复杂,因此,服务降级显得不那么重要,如果后期涉及相关问题,可以采用阿里套餐中[Sentinel]组建,以资源的方式来帮助我们处理服务降级相关的问题。

构建

为了践行OpsDev快速迭代,必然是要采用自动化部署的,选用的是老牌自动化部署工具[Jenkins],但也由此产生了一个小问题,Jenkins是从git上获取代码,本地编译后通过脚本部署的,但git无法拉取某个路径下的代码,所以只能吧项目分开,使用多个git仓库管理,原本项目是使用svn进行托管,微服务项目可以放在一个工程下,同时打开整个微服务工程,但现在看来没办法这么做了。

分享一下部署脚本

#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/local/jdk1.8.0_191/bin:/usr/local/elasticsearch-6.5.4/bin:/root/bin
PATH=.:$PATH
export PATH

JENKINS_NAME=$1
ARTIFACT_ID=$2
SPRING_PROFILE=$3

echo $JENKINS_NAME $ARTIFACT_ID $SPRING_PROFILE

if [ ! -d "/data/webapp/$JENKINS_NAME" ]; then
  mkdir /data/webapp/$JENKINS_NAME
fi

SING_STR="\$\\"
cd /data/webapp/deployScript
mv $JENKINS_NAME-0.0.1-SNAPSHOT.jar $JENKINS_NAME-0.0.1-SNAPSHOT_bak.jar

scp -P22  xxxx@xxx.xxx.xxx.xxx:"/data/webapp/.jenkins/jobs/$JENKINS_NAME/modules/com.thinkerjet$SING_STR$ARTIFACT_ID/lastSuccessful/archive/com.thinkerjet/$ARTIFACT_ID/0.0.1-SNAPSHOT/$ARTIFACT_ID-0.0.1-SNAPSHOT.jar" ./$JENKINS_NAME-0.0.1-SNAPSHOT.jar

spring_pid=`ps -ef | grep $JENKINS_NAME | grep -v grep | grep -v deploy_lexin_boot.sh| awk '{print $2}'`
[ -n "$spring_pid" ] && kill -9 $spring_pid

cp $JENKINS_NAME-0.0.1-SNAPSHOT.jar /data/webapp/$JENKINS_NAME/$JENKINS_NAME-0.0.1-SNAPSHOT.jar
cd /data/webapp/$JENKINS_NAME
/usr/bin/nohup java -jar $JENKINS_NAME-0.0.1-SNAPSHOT.jar --spring.profiles.active=${SPRING_PROFILE} > /data/webapp/$JENKINS_NAME/catalina.out 2>&1 &

jenkins来执行远程脚本,通过scp命令获取打包好的文件,然后执行一下就OK了,另外,不要用lsof -i 这个天杀的命令
它会把所有跟那个端口有通讯的进程都查出来,比如,你如果用lsof -i:eureka端口,那么你部署在这台机器上的其他微服务,全被kill了

开发

基于Greenwich.SR1版本开发
未完待续

遇到的坑

  1. 使用OpenFeign时,使用@FeignClient注解,会在Bean容器中生成Bean对象,如多个@FeignClient注释的类使用相同服务,无法启动

    • 解决方法:@FeignClient(name = “服务名称”, contextId = “类名”)
  2. 使用OpenFeign时,服务间调用默认1秒失败,会出现服务调用成功,但响应超时 - ReadTimeOut,使数据不一致

    • 解决方法:设置ribbon超时时间 (OpenFeign底层调用ribbon以及Hystrix),高版本中默认Hystrix不开启
    	ribbon:
    	  ReadTimeout: 60000
    	  ConnectTimeout: 60000
    
  3. 微服务部署时,需要先让路由getway停止路由到被部署服务,以防请求过程中服务重启

    • 解决方法:使用spring-boot-starter-actuator优雅关闭服务
    • 添加spring-boot-starter-actuator,默认shutdown等端点为关闭状态,启动shutdown端点,访问http:localhost:xxxx/actuator/shutdown
    	management:
    	  endpoint:
    	    shutdown:
    	      enabled: true
    	  endpoints:
    	    web:
    	      exposure:
    	        include: shutdown
    	      base-path: /
    
  4. 配置拦截器无法Autowired

    • 解决方法:使用WebApplicationContextUtils.getRequiredWebApplicationContext方法获取bean工厂,后加载
    	private Foo foo;
    	...
    	if (foo == null) {
    		BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
    		foo = factory.getBean(Foo.class);
    	}
    
  5. 日志输出

    • 方法:使用SpringBoot内置文件输出,注:该配置只应在生产环境中使用
    	logging:
    		path: 此处建议设置为服务器中jar路径下,新建工程同名文件夹,用来保存该项目日志
    
  6. 接口保护

    • 方法:在getway中配置2级路径,如不希望外界路由该接口,则在第一级路径区分,内部服务使用/provider,提供给外部的服务使用/api
    	spring:
    	  application:
    	    name: gateway-service
    	  profiles:
    	    active: dev
    	  cloud:
    	    gateway:
    	      routes:
    	        - id:  xxxx
    	          uri: lb://business
    	          predicates:
    	            - Path=/business/**
    	          filters:
    	            - StripPrefix=1		//该配置表示如访问该服务,则不传递/business/路径
    	            				//例如前台访问/businsess/foo, 则服务真实控制器路径为/foo
    	        - id:  interface
    	          uri: lb://interface
    	          predicates:
    	            - Path=/api/**		//表示只有/api/为一级路径的控制器才可以被路由访问
    
  7. 生产环境Eureka高可用,及unavailable-replicas问题

    • eureka.instance.appname必须与spring.application.name相同
    • eureka.instance.hostname必须使用hosts名称映射,修改hosts文件
    • eureka.client.fetch-registryeureka.client.register-with-eureka要么不写,要么必须为true
    	server:
    	  port: 8761
    	eureka:
    	  instance:
    	    leaseRenewalIntervalInSeconds: 5
    	    leaseExpirationDurationInSeconds: 10
    	  server:
    	    enable-self-preservation: true
    	    evictionIntervalTimerInMs: 5000
    	    useReadOnlyResponseCache: false
    	  client:
    	    fetch-registry: true
    	    register-with-eureka: true
    	spring:
    	  application:
    	    name: xxx
    	  profiles:
    	    active: prod-1
    	logging:
    	  level:
    	    com.netflix: INFO
    	---
    	server:
    	  port: 8761
    	spring:
    	  profiles: prod-1
    	eureka:
    	  instance:
    	    hostname: service-eureka-01
    	    appname: xxx
    	  client:
    	    serviceUrl:
    	      defaultZone: http://service-eureka-02:8762/eureka
    	---
    	server:
    	  port: 8762
    	spring:
    	  profiles: prod-2
    	eureka:
    	  instance:
    	    hostname: service-eureka-02
    	    appname: xxx
    	  client:
    	    serviceUrl:
    	      defaultZone: http://service-eureka-01:8761/eureka
    

总结

以上是我个人线上用Spring cloud踩到的一些坑,记录一下
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你向着阳光奔跑的背影

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值