背景:
这两天实践了一下springcloud,springcloud作为最流行的JAVA分布式微服务的开发框架,生态很棒,整理了几个springcloud的重要组件,记录一下。
枯燥的概念
1、eureka
官方的解释:提供完成的服务注册和服务发现实现、与spirngcloud无缝集成、采用AP而非CP
2、Feign
feign是声明式的web service客户端,它让微服务之间的调用变得更简单了,类似controller调用service。Spring Cloud集成了Ribbon和Eureka,可在使用Feign时提供负载均衡的http客户端。
3、Ribbon
简单地说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单地说,就是在配置文件中列出Load Balancer(简称LB)后面所有机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器
4、Hystrix熔断器
解决了多模块的微服务框架中,某个服务异常,提供降级处理或返回默认值的能力,为服务稳定运行做兜底处理。
5、zuul 网关
提供一个统一的网关,来处理模块间需要公共的拦截如登录或日志打印的能力。还可自定义网关路由
重要的一些配置文件示例
eureka-server的示例配置文件
application.properties
spring.application.name=euraka-server
server.port=8000
eureka.instance.hostname=localhost
#获取注册表,不需要同步其他节点数据
eureka.client.fetch-registry=false
#是否将自己注册到euraka-server
eureka.client.register-with-eureka=false
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
注册服务配置
application.properties
server.port=8082
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/course_practice?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
spring.datasource.username=root
spring.datasource.password=wangqiang6
spring.application.name=course-price
mybatis.configuration.map-underscore-to-camel-case=true
eureka.client.service-url.defaultZone=http://localhost:8000/eureka/
course-list.ribbon.NFLoadBanlancerRuleClassName=com.netflix.loadbalancer.RoundRobinRule
feign.hystrix.enabled=true
logging.pattern.console=%clr(%d{${LOG_DATEFORMAT_PATTERN:HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}
zuul服务配置
application.properties
server.port=9000
spring.application.name=course-gateway
eureka.client.service-url.defaultZone=http://localhost:8000/eureka/
logging.pattern.console=%clr(%d{${LOG_DATEFORMAT_PATTERN:HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}
zuul.prefix=/aweb
zuul.routes.course-list.path=/list/**
zuul.routes.course-list.service-id=course-list
zuul.routes.course-price.path=/price/**
zuul.routes.course-price.service-id=course-price
多模块间调用需要创建eureka客户端
示例CourseListClient
package wang.aweb.course.client;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.annotation.Primary;
import org.springframework.web.bind.annotation.GetMapping;
import wang.aweb.course.entity.Course;
import java.util.List;
/**
* 课程列表的feign客户端
*/
@FeignClient(value = "course-list",fallback = CourseListClientHystrix.class)
@Primary
public interface CourseListClient {
@GetMapping("courseList")
public List<Course> courseList();
}
异常处理的熔断器实现类CourseListHystrix
package wang.aweb.course.client;
import org.springframework.stereotype.Component;
import wang.aweb.course.entity.Course;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 断路器实现类
*/
@Component
public class CourseListClientHystrix implements CourseListClient{
@Override
public List<Course> courseList() {
List<Course> defaultCourses= new ArrayList<>();
Course course=new Course();
course.setId(1);
course.setCourseId(1);
course.setCourseName("默认课程");
course.setValid(1);
defaultCourses.add(course);
return defaultCourses;
//return Collections.emptyList();
}
}
两种在zuul网关中常用的过滤器
示例PreRequestFilter
package wang.aweb.course.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
/**
* 前置过滤器
*/
@Component
public class PreRequestFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
/**
* 调整顺序
* @return
*/
@Override
public int filterOrder() {
return 5;
}
/**
* 开关(满足什么条件可开启)
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext currentRequest=RequestContext.getCurrentContext();
System.out.println("URI:"+currentRequest.getRequest().getRequestURI());
return null;
}
}
后置过滤器PostRequestFilter
package wang.aweb.course.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
/**
* 后置过滤器
*/
@Component
public class PostRequestFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.POST_TYPE;
}
/**
* 调整顺序
* @return
*/
@Override
public int filterOrder() {
return FilterConstants.SEND_RESPONSE_FILTER_ORDER-1;
}
/**
* 开关(满足什么条件可开启)
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext currentRequest=RequestContext.getCurrentContext();
System.out.println("response status:"+currentRequest.getResponse().getStatus());
return null;
}
}
相关依赖:
<!--eureka客户端依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--eureka服务端依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!--zuul网关依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
评论