SpringBoot 回顾(下)

SpringSecurity(/sɪˈkjʊrəti/ 安全)

在web开发中,安全第一位! 过滤器,拦截器 大量原生代码 太冗余了

  • 漏洞,隐私泄露
  • shiro 和 SpringSecurity 很相像 一个做认证 一个做授权
  • shiro认证: 账号密码登陆
  • SpringSecurity: vip1 vip2 vip8 权限不同

SpringSecurity简介:

Spring Security是针对Spring项目的安全框架,也是Spring Boot底层安全模块默认的技术选型,他可以实现强大的Web安全控制,我们仅需要引入 spring-boot-starter-security 模块,进行少量的配置,即可实现强大的安全管理!

记住几个类:

  • WebSecurityConfigurerAdapter(Web安全配置程序适配器): 自定义Security
  • AuthenticationManagerBuilder(身份验证管理器): 自定义认证策略
  • @EnableWebSecurity(启动网络安全): 开启WebSecurity模式

Spring Security的两个主要目标是"认证"和授权(访问控制)

“认证”(Authentication) /ɔːˌθentɪˈkeɪʃn/ a 凡提

“授权”(Authorization) /ˌɔːθərəˈzeɪʃn/

这个概念是通用的,而不是只在Spring Security中存在

//AOP
@EnableWebSecurity
public class SecurityController extends WebSecurityConfigurerAdapter {

    //授权
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //首页所有人可以访问,功能页对应的人能访问
        //请求授权的规则
        http.authorizeRequests()
            .antMatchers("/").permitAll()
            .antMatchers("/level1/**").hasRole("vip1")
            .antMatchers("/level2/**").hasRole("vip2")
            .antMatchers("/level3/**").hasRole("vip3");
        //没有权限,默认到登陆页,可自定义前端接收url,username,password
        http.formLogin().loginPage("/login");
        //开启注销功能,注销成功去首页 http.csrf().disable();测试中,关闭了跨站请求防护,不然注销404
        http.logout().logoutSuccessUrl("/");
        //开启记住我功能 cookie默认保存两周,自定义接收前端参数
        http.rememberMe().rememberMeParameter("remember");
    }
    //认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //这些数据正常应该从数据库获取 auth.jdbcAuthentication(); passwordEncoder 加密密码 明文无效
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
            .withUser("zjt").password(new BCryptPasswordEncoder().encode("1")).roles("vip1")
            .and()
            .withUser("admin").password(new BCryptPasswordEncoder().encode("1")).roles("vip1","vip2")
            .and()
            .withUser("root").password(new BCryptPasswordEncoder().encode("1")).roles("vip1","vip2","vip3");
    }
}

Shiro

  • Apache shiro 是一个java的安全(权限)框架
  • Shiro 可以非常容易的开发出足够好的应用,其不仅可以用在JavaEE环境,也可以用在JavaSE环境
  • Shiro可以完成,认证,授权,加密,会话管理,Web集成,缓存等
  • Shiro三大对象: Subject 用户; SecurityManager 管理所有用户 ; Realm 连接数据
  • 工作流程简易:
  • subject 封装信息: 框架提供的接口, 是与程序进行交互的对象,可以是人也可以是服务或者其他,通常就理解为用户。 接口中定义了很多认证授相关的方法,外部程序通过subject进行认证授,而subject是通过SecurityManager安全管理器进行认证授权, 所有Subject 实例都必须绑定到一个SecurityManager上。我们与一个 Subject 交互,运行时shiro会自动转化为与 SecurityManager交互的特定 subject的交互。
  • SecurityManager 安全管理器: SecurityManager即安全管理器, 对全部的subject进行安全管理,它是shiro的核心,负责对所有的subject进行安全管理。通过SecurityManager可以完成subject的认证、授权等
  • realm: Realm即领域,相当于datasource数据源,securityManager进行安全认证需要通过Realm获取用户权限数据,比如:如果用户身份数据在数据库那么realm就需要从数据库获取用户身份信息,相等于shiro和应用程序安全数据之间的 连接器. 他获取安全数据来判断subject是否能够登录,subject拥有什么权限。他有点类似DAO。常见的数据源有 ini文件数据源的IniRealm,properties文件数据源的PropertiesRealm Realms也是由SecurityManager控制

在这里插入图片描述
在这里插入图片描述

  1. 导入依赖
  2. 配置文件 int log4j
/**
 * Simple Quickstart application showing how to use Shiro's API.
 * 简单的快速启动应用程序显示如何使用Shiro的API。
 * @since 0.9 RC2
 */
public class Quickstart {
    private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);
    public static void main(String[] args) {

        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        SecurityManager securityManager = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);

        // 获取当前用户对象 Subject 安全工具.获得主题
        Subject currentUser = SecurityUtils.getSubject();

        // 通过当前用户拿到Session(shiro)
        Session session = currentUser.getSession();
        // 实现了存值取值
        session.setAttribute("someKey", "aValue");
        String value = (String) session.getAttribute("someKey");
        if (value.equals("aValue")) {
            log.info("---> Retrieved the correct value! [" + value + "]");
        }

        // 判断当前的用户是否已经被认证, 即是否已经登录,调用 Subject 的 isAuthenticated()
        if (!currentUser.isAuthenticated()) {
            // 把用户名和密码封装为 UsernamePasswordToken 对象, 得到一个token(令牌)
            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
            // 设置记住我 rememberme
            token.setRememberMe(true);
            try {
                // 执行登录.
                currentUser.login(token);
            }
            // 若没有指定的账户
            catch (UnknownAccountException uae) {
                log.info("未知账户异常+令牌.委托人 " + token.getPrincipal());
                return;
            }
            // 若账户存在,但密码不匹配
            catch (IncorrectCredentialsException ice) {
                log.info("错误的凭证异常+令牌.委托人 " + token.getPrincipal());
                return;
            }
            // 用户被锁定的异常 LockedAccountException
            catch (LockedAccountException lae) {
                log.info("锁定账户异常+令牌.委托人 " + token.getPrincipal());
            }
            // 所有认证时异常的父类.
            catch (AuthenticationException ae) {
            }
        }

        //say who they are:
        //print their identifying principal (in this case, a username):
        log.info("----> User [" + currentUser.getPrincipal() + "] logged in successfully.");

        //test a role: 测试是否有某一个角色. 调用 Subject 的 hasRole 方法.
        if (currentUser.hasRole("schwartz")) {
            log.info("----> May the Schwartz be with you!");
        } else {
            log.info("----> Hello, mere mortal.");
            return;
        }

        // 测试用户是否具备某一个权限. 调用 Subject 的 isPermitted() 方法。
        if (currentUser.isPermitted("lightsaber:weild")) {
            log.info("----> You may use a lightsaber ring.  Use it wisely.");
        } else {
            log.info("Sorry, lightsaber rings are for schwartz masters only.");
        }

        // 测试用户是否具备某一个行为,更有力度的检测
        if (currentUser.isPermitted("winnebago:drive:eagle5")) {
            log.info("你通过了更有力的检查");
        } else {
            log.info("Sorry, 你不被允许");
        }

        // 检测当前用户是否认证
        System.out.println("---->" + currentUser.isAuthenticated());
        // all done - log out! 全部完成-注销 调用 Subject 的 Logout() 方法.
        currentUser.logout();
        // 检测当前用户是否认证
        System.out.println("---->" + currentUser.isAuthenticated());
        // 退出系统
        System.exit(0);
    }
}

搭建springboot shiro

依赖:

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.5.1</version>
</dependency>

controller:

@Controller
public class MyController {

    // 从前端接收用户和密码
    @RequestMapping("/login")
    public String login(String username, String password, Model model) {
        // 获取当前的用户
        Subject subject = SecurityUtils.getSubject();
        // 封装用户的登陆数据
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try {
            subject.login(token);// 执行登陆方法,如果没有异常就说明ok
            return "index";
        } catch (UnknownAccountException e) {
            model.addAttribute("msg", "账号错误,未知用户异常");
            return "login";
        } catch (IncorrectCredentialsException e) {
            model.addAttribute("msg", "密码错误,错误凭证异常");
            return "login";
        }
    }

    // 未授权用户给予提示
    @RequestMapping("/noauth")
    @ResponseBody
    public String unauthorized() {
        return "未经授权无法访问此页面";
    }
}

shiroConfig:

@Configuration
public class ShiroConfig {

    @Bean // 创建 Realm范围 对象,需要自定义类 : 步骤1
    public UserRealm userRealm() {
        return new UserRealm();
    }

    @Bean // DefaultWebSecurityManager 默认网站安全管理 : 步骤2
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 关联 Realm
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    @Bean // ShiroFilterFactoryBean shiro过滤器工厂bean : 步骤3
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) {

        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        // 设置安全管理器
        bean.setSecurityManager(defaultWebSecurityManager);
        // 添加shiro内置过滤器
        /*
         * anon : 无需认证就可以访问
         * authc: 必须认证才能访问
         * user : 必须拥有记住我功能,才能访问
         * perms: 拥有某个资源的权限才能访问
         * role : 拥有某个角色才可访问
         */
        // 拦截,认证,验证
        Map<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("/add", "authc");
        filterMap.put("/update", "authc");

        // 授权,正常情况下,未经授权会跳转到未授权页面
        filterMap.put("/add", "perms[user:add]");
        filterMap.put("/update", "perms[user:update]");
        bean.setFilterChainDefinitionMap(filterMap);
        // 设置登陆的请求
        bean.setLoginUrl("/toLogin");
        // 设置未授权路径
        bean.setUnauthorizedUrl("/noauth");

        return bean;
    }
}

自定义realm:

// 自定义授权范围 AuthorizingRealm
public class UserRealm extends AuthorizingRealm {

    @Autowired
    IUserService service;

    // 认证,验证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("执行了认证");

        // 调用 MyController 的 UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        // 假设输入的密码跟数据库的不一样
        User user = service.queryUserByName(userToken.getUsername());
        if (user == null) {
            return null; // 自动抛出 UnknownAccountException 未知用户异常
        }
        // 密码认证 shiro做了加密 默认 SimpleCredentialsMatcher 简单密码加密
        // 还可以MD5 e10adc3949ba59abbe56e057f20f883e MD5盐值加密
        return new SimpleAuthenticationInfo(user, user.getPwd(), "");
    }

    // 授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("执行了授权");

        // 固定代码,简单验证信息()
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        // 拿到当前登录的这个对象
        Subject subject = SecurityUtils.getSubject();
        // 获取 return new SimpleAuthenticationInfo(user,user.getPwd(),"");中的 Principal:user对象
        User currentUser = (User) subject.getPrincipal();
        // 设置当前用户权限:增加字符串许可
        info.addStringPermission(currentUser.getPerms());

        return info;
    }
}

Swagger

  • 号称世界上最流行的Api框架
  • RestFul 风格Api 文档在线自动生成工具=>Api文档与API定义同步更新
  • 直接运行,可以在线测试API接口(controller,resultMapping)
  • 支持多种语言:(Java.php.Python….)
  1. 新建springboot web项目
  2. 导入依赖
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>
  1. 编写一个Hello工程
  2. 配置Swagger==>Config
@Configuration
@EnableSwagger2 //开启Swagger2
public class SwaggerConfig {}
  5.测试运行:http://localhost:8080/swagger-ui.html

配置Swagger

​ Swagger的bean实例 Docket(摘要)

//配置 Docket 的bean实例
@Bean
public Docket docket(){
    return new Docket(DocumentationType.SWAGGER_2)
        .apiInfo(apiInfo())
        .enable(true) //默认为true 如果为false 则Swagger在浏览器不能访问
        .groupName("君不妄")
        .select()
        .apis(RequestHandlerSelectors.basePackage("com.zjt.controller"))
        .build();
}
//配置swagger信息=apiInfo
private ApiInfo apiInfo(){
    //作者信息 name,url,email
    Contact CONTACT = new Contact("zjt", "www.123.com", "[email protected]");
    return new ApiInfo(
        "title:标题API",
        "description:Api文档",
        "version:2.0",
        "termsOfServiceUrl:服务条款网址",
        CONTACT,
        "license:许可 Apache 2.0",
        "licenseUrl: 许可链接http://www.apache.org/licenses/LICENSE-2.0",
        new ArrayList());

}

Swagger配置扫描接口

配置扫描的接口

//配置 Docket 的bean实例
@Bean
public Docket docket(){
    return new Docket(DocumentationType.SWAGGER_2)
        .apiInfo(apiInfo())
        .select()
        /*配置要扫描接口的方式
          basePackage():指定扫描的包
          any():扫描全部
          none():不扫描的
          withClassAnnotation():扫描类上的注解,参数是一个注解的反射对象
          withMethodAnnotation():扫描方法上的注解
        */
        .apis(RequestHandlerSelectors.basePackage("com.zjt.controller"))
        //paths 过滤条件 
        .paths(PathSelectors.ant("/zjt/**"))
        .build();
}

配置是否启动Swagger

//配置 Docket 的bean实例
@Bean
public Docket docket(){
    return new Docket(DocumentationType.SWAGGER_2)
        .apiInfo(apiInfo())
        .enable(false) //默认为true 如果为false 则Swagger在浏览器不能访问
        .select()
        .apis(RequestHandlerSelectors.basePackage("com.zjt.controller"))
        .build();
}

配置API文档的分组

.groupName("君不妄")

如何配置多个分组,多个Docket实例即可

@Bean
public Docket docket1(){
    return new Docket(DocumentationType.SWAGGER_2).groupName("A");
}
@Bean
public Docket docket2(){
    return new Docket(DocumentationType.SWAGGER_2).groupName("B");
}

在这里插入图片描述

常用注解说明

  • @Api()用于类;
    表示标识这个类是swagger的资源
  • @ApiOperation()用于方法;
    表示一个http请求的操作
  • @ApiParam()用于方法,参数,字段说明;
    表示对参数的添加元数据(说明或是否必填等)
  • @ApiModel()用于类
    表示对类进行说明,用于参数用实体类接收
  • @ApiModelProperty()用于方法,字段
    表示对model属性的说明或者数据操作更改
  • @ApiIgnore()用于类,方法,方法参数
    表示这个方法或者类被忽略
  • @ApiImplicitParam() 用于方法
    表示单独的请求参数
  • @ApiImplicitParams() 用于方法,包含多个 @ApiImplicitParam

详细地址

总结

  1. 我们可以通过Swagger给一些比较难理解的属性或者接口增加注释信息
  2. 接口文档实时更新,更高效的协调开发
  3. 可以在线测试,详细明了
  4. 正式发布项目时要关闭Swagger

异步任务

为避免后端任务调度时间过久,导致前端页面无法展示内容,陷入加载或转圈或白屏,造成不好的用户体验,可以使用开启异步方法

在springboot入口类添加注解

@EnableAsync

在需要持久化超时的方法上

@Async

在这里插入图片描述

邮件发送

生成邮箱授权码:

在这里插入图片描述

在这里插入图片描述

配置application.properties

spring.mail.username=11567*****@qq.com
# 授权码
spring.mail.password=rvpijmeuycizfhjh
spring.mail.host=smtp.qq.com
# qq独有 开启加密验证
spring.mail.properties.mail.smtp.ssl.enable=true

代码实现:

//引入一个java邮件发送 实现类
@Autowired 
JavaMailSenderImpl mailSender;

@Test
void test() {
    //简单的邮件
    SimpleMailMessage message = new SimpleMailMessage();
    
    //正文
    message.setSubject("君不妄"); //主题
    message.setText("这是一封java测试邮件"); //内容
    message.setTo("134****@qq.com"); //收件人
    message.setFrom("1156****@qq.com"); //发件人
	//邮件发送
    mailSender.send(message);
}

@Test
void test2() throws MessagingException {
    //一个复杂的邮件
    MimeMessage mimeMessage = mailSender.createMimeMessage();
    //组装 开启多文件 multipart:true
    MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
    
    //正文
    helper.setSubject("这是一个测试主题");
    // 开启html功能 html:true
    helper.setText("<p style='color:red'>这是一封java测试邮件</p>",true);
    helper.setTo("1156****@qq.com");
    helper.setFrom("11*****@qq.com");
    //添加一个附件
    helper.addAttachment("1.jpg",new File("C:\\Users\\Administrator\\Desktop\\鬼刀 (48).jpg"));
    helper.addAttachment("2.jpg",new File("C:\\Users\\Administrator\\Desktop\\鬼刀 (49).jpg"));
	//邮件发送
    mailSender.send(mimeMessage);
}

在这里插入图片描述

定时器

@EnableScheduling 开启时程安排 : 在springboot入口类开启定时功能
@Scheduled 预定的: 什么时候执行

/*在一个特定时间执行这个方法
cron 表达式 秒 分 时 日 月 周几
"10 10 12 L * ?" 没有最后一天L 的12点,10分,10秒执行一次
"10 0/5 12,14 * * ?" 每天的12和14点,每隔5分钟,10秒执行一次
"0 0 0 27 10 ? *" 我的生日的零点祝福 
cron:计时程序
*/
@Scheduled(cron = "0 0 0 27 10 ? *")
public void hello(){
System.out.println("生日快乐");
  

分布式Dubbo+Zookeeper+SpringBoot

什么是分布式系统:

在《分布式系统原理与范型》一书中有如下定义:”分布式系统是若干独立计算机的集合, 这些计算机对于用户来说就像单个相关系统"
分布式系统是由一-组通过网络进行通信、 为了完成共同的任务而协调工作的计算机节点组成的系统。分布式系统的出现是为了用廉价的、普通的机器完成单个计算机无法完成的计算、存储任务。其目的是利用更多的机器,处理更多的数据。
分布式系统(distributed system)是建立在网络之上的软件系统。
首先需要明确的是,只有当单个节点的处理能力无法满足日益增长的计算、存储任务的时候,且硬件的提升(加内存、加磁盘、使用更好的CPU)高昂到得不偿失的时候,应用程序也不能进一步优化的时候,我们才需要考虑分布式系统。因为,分布式系统要解决的问题本身就是和单机系统一样的, 而由于分布式系统多节点、通过网络通信的拓扑结构,会引入很多单机系统没有的问题,为了解决这些问题又会引入更多的机制、协议,带来更多的问题。。。

Dubbo是什么:

Apache Dubbo |是一款高性能、轻量级的开源Java;RPC框架, 它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。

Dubbo是一个分布式服务框架,RPC远程服务调用方案(RPC 解决通讯和序列化),以及SOA服务治理方案。简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需要用的,只有在分布式的时候,才有dubbo这样的分布式服务框架的需求,并且本质上是个服务调用的东东,说白了就是个远程服务调用的分布式框架

在这里插入图片描述

节点角色说明:

Provider: 暴露服务的服务提供方。

Consumer: 调用远程服务的服务消费方。

Registry: 服务注册与发现的注册中心。

Monitor: 统计服务的调用次调和调用时间的监控中心。

Container: 服务运行容器。

调用关系说明:

  1. 服务容器负责启动,加载,运行服务提供者。
  2. 服务提供者在启动时,向注册中心注册自己提供的服务。
  3. 服务消费者在启动时,向注册中心订阅自己所需的服务。
  4. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
  5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
  6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

Zookeeper

默认端口节点:2181

ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

dubbo-admin:

是一个监控管理后台~查看我们注册了那些服务,管理调优

在这里插入图片描述

步骤:

前提: zookeeper服务已开启!

  1. 提供者提供服务

    1. 导入依赖

    2. 配置注册中心的地址,以及服务发现名,和要扫描的包

     # 服务应用name
     dubbo.application.name=provider-service
     # 注册中心地址
     dubbo.registry.address=zookeeper://127.0.0.1:2181
     # 要被注册服务的包路径
     dubbo.scan.base-packages=com.zjt.service
    
    1. 在想要被注册的服务上面~增加一个注解 dubbo的@Service
    import org.apache.dubbo.config.annotation.Service;
    import org.springframework.stereotype.Component;
    
    //zookeeper:服务注册与发现
    @Service    //可以被扫描到,项目一启动就自动注册到注册中心
    @Component //使用了dubbo之后尽量不适用@Service注解,重名
    public class FuwuServiceImpl implements FuwuService {
        @Override
        public String test() {
            return "服务 提供者 ";
        }
    }
    
  2. 消费者如何消费

    1. 导入依赖
    2. 配置注册中心的地址,配置自己的服务名
    3. 从远程注入服务 @Reference

    在这里插入图片描述
    Dubbo实现服务调用是通过RPC的方式,即客户端和服务端共用一个接口(将接口打成一个jar包,在客户端和服务端引入这个jar包),客户端面向接口写调用,服务端面向接口写实现,中间的网络通信交给框架去实现


聊聊现在和未来

三层架构 + MVC

架构 —> 解耦

开发框架Spring IOC AOP

IOC :控制反转
租房子以前需要自己一个一个跑,现在找中介,他那有房源,让中介帮我们完成租房子,原来我们都是自己一步步操作,现在交给容器了!我们需要什么就去拿就可以了
AOP :切面(本质,动态代理)
为了解决什么?不影响业务本来的情况下,实现动态增加功能,大量应用在日志,事务…等等方面

Spring是一个轻量级的J ava开源框架,容器
目的:解决企业开发的复杂性问题
Spring是春天,觉得他是春天,也十分复杂,配置文件!

SpringBoot
SpringBoot并不是新东西,就是Spring的升级版!
新一代JavaEE的开发标准,开箱即用! ->拿过来就可以用! 它自动帮我们配置了非常多的东西,我们拿来即用!
特性:约定大于配置!
随着公司体系越来越大,用户越来越多!

微服务架构—>新架构
模块化,功能化! 用户,支付,签到,娱乐,… ;
人多余多:一台服务器解决不了;在增加服务器 ! 横向
假设A服务器占用98%资源,B服务器只占用了10% 。一 负载均衡;
将原来的整体项目,分成模块化,用户就是一个单独的项目,签到也是一个单独的项目,项目和项目之前需要通信,如何通信?
用户非常多,而签到十分少! 给用户多一点服务器,给签到少一点服务器!

微服务架构问题?
分布式架构会遇到的四个核心问题?

  1. 这么多服务,客户端该如何去访问?
  2. 这么多服务,服务之间如何进行通信?
  3. 这么多服务,如何治理呢?
  4. 服务挂了,怎么办?

解决方案:
SpringCloud,是一套生态,就是来解决以上分布式架构的4个问题
想使用SpringCloud,必须要掌握SpringBoot,因为SpringCloud是基于SpringBoot;

  1. Spring Cloud NetFlix ,出来了一套解决方案! 一站式解决方案。我们都可以直接去这里拿?
    (1). Api网关,zuu1组件
    (2). Feign --> HttpClient —> HTTP的通信方式,同步并阻塞
    (3). 服务注册与发现,Eureka
    (4). 熔断机制,Hystrix
    2018年年底,NetFlix宣布无限期停止维护。生态不再维护,就会脱节。

  2. Apache Dubbo zookeeper,第二套解决系统
    (1). API :没有! 要么找第三方组件,要么自己实现
    (2). Dubbo是一个高性能的基于Java实现的RPC通信框架! 2.6.x
    (3). 服务注册与发现,zookeeper: 动物园管理者(Hadoop ,Hive)
    (4). 没有: 借助了Hystrix
    不完善,Dubbo 他们3.0融合了阿里的长处 推出后可能很强

  3. SpringCloud Alibaba一站式解决方案 !还没成熟
    目前,又提出了一种方案:
    服务网格:下一代微服务标准,Service Mesh
    代表解决方案: istio (你们未来可能需要掌握! )

  • 万变不离其宗,一通百通!
    1. API网关,服务路由
    2. HTTP,RPC框架,异步调用
    3. 服务注册与发现,高可用
    4. 熔断机制,服务降级

为什么要解决这个问题? 本质:网络是不可靠的!

不要停止学习的脚步

猜你喜欢

转载自blog.csdn.net/weixin_44905070/article/details/105191385
今日推荐