1、概念:Hystrix 熔断机制

2、具体内容

所谓的熔断机制和日常生活中见到电路保险丝是非常相似的,当出现了问题之后,保险丝会自动烧断,以保护我们的电器, 那么如果换到了程序之中呢?

当现在服务的提供方出现了问题之后整个的程序将出现错误的信息显示,而这个时候如果不想出现这样的错误信息,而希望替换为一个错误时的内容。

一个服务挂了后续的服务跟着不能用了,这就是雪崩效应

对于熔断技术的实现需要考虑以下几种情况:

· 出现错误之后可以 fallback 错误的处理信息;

· 如果要结合 Feign 一起使用的时候还需要在 Feign(客户端)进行熔断的配置。

 2.1、Hystrix 基本配置

1、 【microcloud-provider-dept-hystrix-8001】修改 pom.xml 配置文件,追加 Hystrix 配置类:

        <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

2、 【microcloud-provider-dept-hystrix-8001】修改 DeptRest 程序

package cn.study.microcloud.rest;

import javax.annotation.Resource;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import cn.study.microcloud.service.IDeptService;
import cn.study.vo.Dept; @RestController
public class DeptRest {
@Resource
private IDeptService deptService;
@RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET)
@HystrixCommand(fallbackMethod="getFallback") // 如果当前调用的get()方法出现了错误,则执行fallback
public Object get(@PathVariable("id") long id) {
Dept vo = this.deptService.get(id) ; // 接收数据库的查询结果
if (vo == null) { // 数据不存在,假设让它抛出个错误
throw new RuntimeException("部门信息不存在!") ;
}
return vo ;
}
public Object getFallback(@PathVariable("id") long id) { // 此时方法的参数 与get()一致
Dept vo = new Dept() ;
vo.setDeptno(999999L);
vo.setDname("【ERROR】Microcloud-Dept-Hystrix"); // 错误的提示
vo.setLoc("DEPT-Provider");
return vo ;
} }

一旦 get()方法上抛出了错误的信息,那么就认为该服务有问题,会默认使用“@HystrixCommand”注解之中配置好的 fallbackMethod 调用类中的指定方法,返回相应数据。

3、 【microcloud-provider-dept-hystrix-8001】在主类之中启动熔断处理

package cn.study.microcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
@EnableDiscoveryClient
public class Dept_8001_StartSpringCloudApplication {
public static void main(String[] args) {
SpringApplication.run(Dept_8001_StartSpringCloudApplication.class, args);
}
}

 现在的处理情况是:服务器出现了错误(但并不表示提供方关闭),那么此时会调用指定方法的 fallback 处理。

 2.2、服务降级(服务回退)

所有的 RPC 技术里面服务降级是一个最为重要的话题,所谓的降级指的是当服务的提供方不可使用的时候,程序不会出现异常,而会出现本地的操作调用。

例如:在每年年底 12306 都是最繁忙的时候,那么在这个情况会发现有一些神奇的情况:当到了指定的时间大家开始抢票的 时候,如果你不抢,而后查询一些冷门的车次,票有可能查询不出来。因为这个时候会将所有的系统资源给抢票调度了,而其它的 服务由于其暂时不受到过多的关注,这个时候可以考虑将服务降级(服务暂停)。

服务的降级处理是在客户端实现的,与你的服务器端没有关系。

1、 【microcloud-service】扩充一个 IDeptService 的失败调用(服务降级)处理:

package cn.study.service.fallback;
import java.util.List;
import org.springframework.stereotype.Component;
import cn.study.service.IDeptClientService;
import cn.study.vo.Dept;
import feign.hystrix.FallbackFactory;
@Component
public class IDeptClientServiceFallbackFactory
implements
FallbackFactory<IDeptClientService> { @Override
public IDeptClientService create(Throwable cause) {
return new IDeptClientService() {
@Override
public Dept get(long id) {
Dept vo = new Dept();
vo.setDeptno(888888L);
vo.setDname("【ERROR】Feign-Hystrix"); // 错误的提示
vo.setLoc("Consumer客户端提供");
return vo;
} @Override
public List<Dept> list() {
return null;
} @Override
public boolean add(Dept dept) {
return false;
}
};
} }

2、 【microcloud-service】修改 IDeptClientService 接口,追加本地的 Fallback 配置。

package cn.study.service;

import java.util.List;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import cn.study.commons.config.FeignClientConfig;
import cn.study.service.fallback.IDeptClientServiceFallbackFactory;
import cn.study.vo.Dept;
@FeignClient(value = "MICROCLOUD-PROVIDER-DEPT", configuration = FeignClientConfig.class, fallbackFactory = IDeptClientServiceFallbackFactory.class)
public interface IDeptClientService {
@RequestMapping(method = RequestMethod.GET, value = "/dept/get/{id}")
public Dept get(@PathVariable("id") long id);
@RequestMapping(method = RequestMethod.GET, value = "/dept/list")
public List<Dept> list();
@RequestMapping(method = RequestMethod.POST, value = "/dept/add")
public boolean add(Dept dept);
}

此时当服务不可用的时候就会执行“IDeptClientServiceFallbackFactory”类中返回的 IDeptClientService 接口的匿名对象信息。

3、 【microcloud-consumer-hystrix】修改 application.yml 配置文件,追加 feign 配置启用。

feign:
hystrix:
enabled: true

4、 【microcloud-consumer-hystrix】修改程序启动主类:

package cn.study.microcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@EnableEurekaClient
@ComponentScan("cn.study.service,cn.study.microcloud")
@EnableFeignClients(basePackages={"cn.study.service"})
public class Consumer_80_StartSpringCloudApplication {
public static void main(String[] args) {
SpringApplication.run(Consumer_80_StartSpringCloudApplication.class,
args);
}
}

当追加上了“@ComponentScan("cn.mldn.service")”注解之后才可以进行包的扫描配置。

此时即使服务端无法继续提供服务了,由于存在有服务降级机制,也会保证服务不可用时可以得到一些固定的提示信息。

2.3、HystrixDashboard服务监控

在 Hystrix 里面提供有一种监控的功能,那么这个功能就是“Hystrix Dashboard”,可以利用它来进行整体微服务的监控操作。

1、 首先为了方便监控,将建立一个新的监控项目:microcloud-consumer-hystrix-dashboard;

2、 【microcloud-consumer-hystrix-dashboard】修改项目中的 pom.xml 配置文件:

        <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>

3、 【microcloud-provider-*】所有的服务提供者之中都一定要提供有监控服务依赖库:

        <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

4、 【microcloud-consumer-hystrix-dashboard】修改 application.yml 配置文件,主要进行端口的配置:

server:
port: 9001

5、 【microcloud-consumer-hystrix-dashboard】创建一个监控的主类:

package cn.study.microcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardApplication_9001 {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboardApplication_9001.class, args);
}
}

6、 修改 hosts 主机文件,增加主机列表:

127.0.0.1 dashboard.com

服务运行地址:http://dashboard.com:9001/hystrix;

7、 得到 microcloud-provider-dept 的监控信息:http://studyjava:hello@dept-8001.com:8001/hystrix.stream;

· 如果此时要想获取监控信息必须去运行微服务;

8、 将之前的监控的路径http://studyjava:hello@dept-8001.com:8001/hystrix.stream填写到之前启动好的 dashboard 程序页面之中;

监控效果如下图所示:

2.4、Turbine 聚合监控

HystrixDashboard 主要的功能是可以针对于某一项微服务进行监控,但是如果说现在有许多的微服务需要进行整体的监控,那 么这种情况下就可以利用 turbine 技术来实现。

1、 下面准备出一个新的微服务:Company,这个微服务不打算使用 SpringSecurity 安全处理以及 Mybatis 数据库连接,只是做一 个简单的数据信息。通过一个已有的 microcloud-provider-hystrix-8001 复制一个新的项目:microcloud-provider-company-8101;

2、 【microcloud-provider-company-8101】修改项目中的 pom.xml 配置文件,将与安全有关的依赖包删除掉以及与数据库连接池、MyBatis 的相关的程序类或接口全部删除掉,只保留有用的包;

    <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>cn.study</groupId>
<artifactId>microcloud-api</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>

3、 【microcloud-api】追加一个新的 VO 类:Company。

package cn.study.vo;

import java.io.Serializable;

@SuppressWarnings("serial")
public class Company implements Serializable {
private String title ;
private String note ;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
@Override
public String toString() {
return "Company [title=" + title + ", note=" + note + "]";
}
}

4、 【microcloud-provider-company-8101】建立一个新的微服务的程序类:CompanyRest

package cn.study.microcloud.rest;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import cn.study.vo.Company; @RestController
public class CompanyRest {
@RequestMapping(value = "/company/get/{title}", method = RequestMethod.GET)
@HystrixCommand // 如果需要进行性能监控,那么必须要有此注解
public Object get(@PathVariable("title") String title) {
Company vo = new Company() ;
vo.setTitle(title);
vo.setNote("www.study.cn");
return vo ;
}
}

5、 【microcloud-provider-company-8101】修改程序的启动主类:

package cn.study.microcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
@EnableDiscoveryClient
public class Company_8101_StartSpringCloudApplication {
public static void main(String[] args) {
SpringApplication.run(Company_8101_StartSpringCloudApplication.class, args);
}
}

6、 【microcloud-provider-company-8101】修改 application.yml 配置文件:

server:
port: 8101
eureka:
client: # 客户端进行Eureka注册的配置
service-url:
defaultZone: http://edmin:studyjava@eureka-7001.com:7001/eureka,http://edmin:studyjava@eureka-7002.com:7002/eureka,http://edmin:studyjava@eureka-7003.com:7003/eureka
instance:
lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
instance-id: dept-8001.com # 在信息列表时显示主机名称
prefer-ip-address: true # 访问的路径变为IP地址
info:
app.name: study-microcloud
company.name: www.study.cn
build.artifactId: $project.artifactId$
build.version: $project.verson$
spring:
application:
name: microcloud-provider-company

7、 【microcloud-provider-company-8101】启动微服务,随后取得监控信息:

· 在 hosts 配置文件之中追加有一个映射路径:

127.0.0.1 company-8101.com

· 访问地址:http://company-8101.com:8101/company/get/hello;

· hystrix 监控地址:http://company-8101.com:8101/hystrix.stream;

8、 如 果 要 想 实 现 trubine 的 配 置 , 则需要建立一个 turbine项目模块 , 这个项目可以直接通过之前的 microcloud-consumer-hystrix-dashboard 模块进行复制为“microcloud-consumer-turbine”模块;

9、 【microcloud-consumer-turbine】修改 pom.xml 配置文件,追加 turbine 的依赖程序包:

        <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-turbine</artifactId>
</dependency>

10、 【microcloud-consumer-turbine】修改 application.yml 配置文件:

server:
port: 9101 # turbine的监听端口为9101
eureka:
client: # 客户端进行Eureka注册的配置
service-url:
defaultZone: http://edmin:studyjava@eureka-7001.com:7001/eureka,http://edmin:studyjava@eureka-7002.com:7002/eureka,http://edmin:studyjava@eureka-7003.com:7003/eureka
instance:
lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
instance-id: dept-8001.com # 在信息列表时显示主机名称
prefer-ip-address: true # 访问的路径变为IP地址
turbine:
app-config: MICROCLOUD-PROVIDER-COMPANY,MICROCLOUD-PROVIDER-DEPT # 定义所有要监控的微服务信息
cluster-name-expression: new String("default") # 设置监控的表达式,通过此表达式表示要获取监控信息名称

11、 【microcloud-consumer-turbine】建立一个 turbine 的使用主类信息

package cn.study.microcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.netflix.turbine.EnableTurbine;
@SpringBootApplication
@EnableHystrixDashboard
@EnableTurbine
public class TurbineApplication_9101 {
public static void main(String[] args) {
SpringApplication.run(TurbineApplication_9101.class, args);
}
}

12、 【microcloud-consumer-hystrix-dashboard】运行 hystrix-dashboard 监控程序;

13、 【microcloud-consumer-turbine】运行 trubine 聚合监控程序;

· 但是在正常启动 trubine 的时候出现了以下的错误提示信息,这是因为没有对有安全认证的微服务MICROCLOUD-PROVIDER-DEPT进行安全认证

· 修改 hosts 配置文件,追加一个映射路径:

127.0.0.1 turbine.com

· trubine 访问路径:http://turbine.com:9101/turbine.stream

14、 运行 HystrixDashboard 监控程序:http://dashboard.com:9001/hystrix.stream;

· 在监控的位置上填写之前设置好的 turbine 的访问地址看到的效果如下:

15、 【microcloud-security】如果现在需要 turbine 进行加密的微服务的访问操作,只能够采取一种折衷方案,就是要去修改整个项目中的安全策略,追加 WEB 安全策略配置:

package cn.study.microcloud.config;

import javax.annotation.Resource;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/hystrix.stream","/turbine.stream") ;
} @Resource
public void configGlobal(AuthenticationManagerBuilder auth)
throws Exception {
auth.inMemoryAuthentication().withUser("studyjava").password("hello")
.roles("USER").and().withUser("admin").password("hello")
.roles("USER", "ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 表示所有的访问都必须进行认证处理后才可以正常进行
http.httpBasic().and().authorizeRequests().anyRequest()
.fullyAuthenticated();
// 所有的Rest服务一定要设置为无状态,以提升操作性能
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}

现在所有的安全策略会自动抛开以上的两个访问路径,这种是基于 Bean 配置,如果要是你现在基于的是 application.yml 文件的配置,则就必须修改 application.yml 配置文件,追加如下内容:

security:
ignored:
- /hystrix.stream
- /turbine.stream

这个时候如果启动之后没有出现任何的错误提示,那么就表示现在已经可以绕过了 Security 的配置而直接进行服务的访问了。

SpringCloud系列七:Hystrix 熔断机制(Hystrix基本配置、服务降级、HystrixDashboard服务监控、Turbine聚合监控)的更多相关文章

  1. SpringCloud系列三:SpringSecurity 安全访问(配置安全验证、服务消费端处理、无状态 Session 配置、定义公共安全配置程序类)

    1.概念:SpringSecurity 安全访问 2.具体内容 所有的 Rest 服务最终都是暴露在公网上的,也就是说如果你的 Rest 服务属于一些你自己公司的私人业务,这样的结果会直接 导致你信息 ...

  2. spring cloud 2.x版本 Ribbon服务发现教程(内含集成Hystrix熔断机制)

    本文采用Spring cloud本文为2.1.8RELEASE,version=Greenwich.SR3 前言 本文基于前两篇文章eureka-server和eureka-client的实现. 参考 ...

  3. spring cloud 2.x版本 Feign服务发现教程(内含集成Hystrix熔断机制)

    前言 本文采用Spring cloud本文为2.1.8RELEASE,version=Greenwich.SR3 本文基于前两篇文章eureka-server和eureka-client的实现. 参考 ...

  4. Hystrix 熔断机制

    熔断机制相当于电路的跳闸功能,即在一定时间内,错误比例达到一定数目时业务从原来流程转移到另外的流程处理.在一段时间后,恢复到原业务逻辑. 测试代码如下 /** * @author zimu * @de ...

  5. 熔断机制hystrix

    一.问题产生 雪崩效应:是一种因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过程 正常情况下的服务: 某一服务出现异常,拖垮整个服务链路,消耗整个线程队列,造成服务不可用,资源耗尽: ...

  6. Hystrix熔断机制原理剖析

    一.前言 在分布式系统架构中多个系统之间通常是通过远程RPC调用进行通信,也就是 A 系统调用 B 系统服务,B 系统调用 C 系统的服务.当尾部应用 C 发生故障而系统 B 没有服务降级时候可能会导 ...

  7. 网关中加入熔断机制(Hystrix)

    网关中加入熔断机制 在网关中加入熔断机制 添加依赖项 spring-cloud-gateway项目POM文件加入spring-cloud-starter-netflix-hystrix <dep ...

  8. 跟我学SpringCloud | 第七篇:Spring Cloud Config 配置中心高可用和refresh

    SpringCloud系列教程 | 第七篇:Spring Cloud Config 配置中心高可用和refresh Springboot: 2.1.6.RELEASE SpringCloud: Gre ...

  9. SpringCloud(七):springcloud-config统一管理配置中心

    前言: Spring Cloud Config组件是独立的,不需要注册到eureka.config工作原理是把读取目标到配置拉取到本地缓存一份然后供给其他客户端使用,所以一旦config启动成功,可以 ...

随机推荐

  1. 学习笔记CB010:递归神经网络、LSTM、自动抓取字幕

    递归神经网络可存储记忆神经网络,LSTM是其中一种,在NLP领域应用效果不错. 递归神经网络(RNN),时间递归神经网络(recurrent neural network),结构递归神经网络(recu ...

  2. Python 斗地主发牌

    #coding = utf-8 import random def Creat_Card(): card_type = ['♥','♠','♦','♣'] card_values= ['A', '2' ...

  3. slb

    第一章 弹性负载均衡slb概要介绍 第一讲什么是弹性负载均衡slb 互联网应用的服务扩展   负载均衡诞生 slb的引出 slb产品介绍 负载均衡 server load balancer 是对多台云 ...

  4. js 中逻辑为 false 的8种情况

    如果对象无初始值或者其值为 数字0.-0.null."".false.undefined 或者 NaN,那么对象的逻辑值为 false. 注意:字符串 '0',值为 true ty ...

  5. 【申嵌视频】基于VMWare虚拟机下安装ubuntu操作系统的详细步骤

    [申嵌视频]基于VMWare虚拟机下安装ubuntu操作系统 适合搭建mini2440, Tiny6410, smart210,Tiny4412, NanoPC-T2, NanoPC-T3, Nano ...

  6. JS将/Date(1446704778000)/转换成str

    JS将/Date(1446704778000)/转换成str:var dateStr = eval(ele.add_time.replace(/\/Date\((\d+)\)\//gi, " ...

  7. lnmp一件安装包 搭建laravel 环境(lnmp1.4)(报错500)

    https://blog.csdn.net/huangyuxin_/article/details/78998486

  8. ABBYY FineReader 14OCR解锁

    ABBYY FineReader 14是2017年新推的文字处理编辑软件,能够将图像扫描转换成文档处理.不论是在使用群体方面还是功能特性方面都是极好的. •确保扫描仪正确地连接到电脑,并将其打开.查阅 ...

  9. [UE4]引用Grabbable接口

    一.当前:可抓取对象的类型是GrabTargetActor 二.修改目标:可抓取对象的类型改成Grabbable. 1.Fand Grab Target的返回值改成Grabbale(变量的数据类型可以 ...

  10. 知识点:tuple 元素真的不可变吗

    tuple 元素真的不可变吗 有一种有序列表叫元组:tuple. tuple和list非常类似,但是tuple一旦初始化就不能修改,比如同样是列出单位或同学的名字: >>> clas ...