Kafka是基于消息发布/订阅模式实现的消息系统,其主要设计⽬标如下:
Kafka中涉及的⼀些基本概念:
oauth2 定义了下面四种授权方式:
授权码常见参数:
* response_type:表示授权类型,必选项,此处的值固定为"code"
* client_id:表示客户端的ID,必选项
* redirect_uri:表示重定向URI,可选项
* scope:表示申请的权限范围,可选项
* state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。
开发分布式系统如果还是各个服务配置文件单独配置肯定是不行的,springcloud使用的解决方案是搭建配置中心将并指定一个配置文件路径如git项目对配置文件进行统一管理。 在Spring Cloud中,提供了分布式配置中心组件spring cloud config ,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程Git仓库中。 在实现cloud config中,主要有两个角色:作为配置中心连接配置路径的 config server,连接配置中心读取配置的config client。
1、引入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</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>
2、开启配置服务器
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
拆分方式:按照不同服务功能进行拆分 拆分要点:高内聚,低耦合。一个服务尽量完成一个功能,减少服务间的频繁调用。
前端专注页面展示,布局以及多场景集成。后端提供统一的数据和模型供前端访问。
如果一个数据需要被多个服务共享,才能完成一笔交易,那么这个数据被称为状态。进而依赖这个“状态”数据的服务被称为有状态服务,反之称为无状态服务。简单点说就是,应该把缓存的数据迁移到分布式缓存中存储,让业务服务变成一个无状态的计算节点
如果系统处于高并发的场景下,某一服务依赖于另外一服务,而另外一服务意外挂掉了,就需要用到Hystrix断路器。比如,购买商品的订单服务,当订单生成成功之后需要调用积分服务增加用户积分。如果积分服务挂了,我们可以暂时不更新积分,但是订单服务任要保证它可以正常工作,所以我们需要设定一个断路器(超时断开),保证订单服务正常运行,这个过程也称为降级。
添加依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker #开启断路器功能
public class RibbonApplication {
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(RibbonApplication.class, args);
}
}
每个微服务有自己私有的数据库持久化业务数据。 每个微服务只能访问自己的数据库,而不能访问其它服务的数据库。 某些业务场景下,需要在一个事务中更新多个数据库。这种情况也不能直接访问其它微服务的数据库,而是通过对于微服务进行操作。 数据的去中心化,进一步降低了微服务之间的耦合度,不同服务可以采用不同的数据库技术(SQL、NoSQL等)。在复杂的业务场景下,如果包含多个微服务,通常在客户端或者中间层(网关)处理。
将应用拆分成为一个一个的单个服务,应用Docker技术,不依赖任何服务器和数据模型,是一个全栈应用,可以通过自动化方式独立部署,每个服务运行在自己的进程中,通过轻量的通讯机制联系,经常是基于HTTP资源API(RestFul API),这些服务基于业务能力构建,能实现集中化管理)。
参考:https://blog.csdn.net/tianyaleixiaowu/article/details/77893822
在服务网关中定义过滤器只需要继承ZuulFilter抽象类实现其定义的四个抽象函数就可对请求进行拦截与过滤。
例子:定义了一个Zuul过滤器,实现了在请求被路由之前检查请求中是否有accessToken参数,若有就进行路由,若没有就拒绝访问,返回401 Unauthorized错误。
public class AccessFilter extends ZuulFilter {
private static Logger log = LoggerFactory.getLogger(AccessFilter.class);
@Override
public String filterType() {
return "pre";
//枚举值:pre(请求被路由之前调⽤), routing(请求时候被调⽤), post(在routing和error过滤器之后被调⽤), error(发⽣错误时被调⽤)
}
@Override
public int filterOrder() {
//通过int值来定义过滤器的执⾏顺序
return 0; //优先级, 0是最高优先级即最先执行
}
@Override
public boolean shouldFilter() {
//过滤器开关
return true; //写逻辑,是否需要执行过滤。true会执行run函数,false不执行run函数
}
@Override
public Object run() {
//过滤器的具体逻辑
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
log.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
Object accessToken = request.getParameter("accessToken");
if(accessToken == null) {
log.warn("access token is empty");
//过滤该请求,不往下级服务去转发请求,到此结束
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
ctx.setResponseBody("{\"result\":\"accessToken为空!\"}");
ctx.getResponse().setContentType("text/html;charset=UTF-8");
return null;
}
//如果有token,则进行路由转发
log.info("access token ok");
//这里return的值没有意义,zuul框架没有使用该返回值
return null;
}
}