• SpringCloud搭建应用


    springcloud:成熟的微服务框架,定位为开发人员提供工具,以快速构建分布式系统

    项目搭建流程:

    1、新建多模块项目,开发

    2、服务注册与发现Eureka,注册服务方便引用

    3、利用Fegin实现服务间调用

    4、服务调用正常,考虑服务的负载均衡,使用Ribbon

    5、服务宕机,容灾,避免大面积服务瘫痪,使用熔断器Hystrix

    6、整体系统发布统一ip端口,使用网关Zuul,也可对请求进行过滤器的编写

    其他:

    1、Session共享机制

    2、微服务应用开发重难点环节

    3、微服务子模块通过网关访问文件,需配置地址映射

    4、缓存的配置类

    一、Eureka服务端搭建(注册中心)

    1. 一、Eureka服务端搭建(引依赖、加配置、使用注解)
    2. // 新建子模块pom引入依赖
    3. org.springframework.cloud
    4. spring-cloud-starter-netflix-eureka-server
    5. //application.properties加配置
    6. spring.application.name=eureka-server 服务名
    7. server.port=8000 服务端口
    8. eureka.instance.hostname=localhost 主机名称
    9. eureka.client.fetch-registry=false fetch-registry获取注册表,不需要同步其他节点数据
    10. eureka.client.register-with-eureka=false register-with-eureka代表是否将自己注册到eureka-server,默认是true
    11. eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/ 服务对外所提供的地址
    12. //启动类加注解@EnableEurekaServer
    13. @EnableEurekaServer
    14. @SpringBootApplication
    15. public class EurekaServerApplication {
    16. public static void main(String[] args) {
    17. SpringApplication.run(EurekaServerApplication.class, args);
    18. }
    19. }
    20. ====eureka-server配置完成,访问地址http://localhost:8000/查看服务注册情况

    二、Eureka客户端搭建(子模块服务注册)

    1. 二、Eureka客户端搭建(引入pom依赖,配置文件编写)
    2. //引入pom依赖
    3. org.springframework.cloud
    4. spring-cloud-starter-netflix-eureka-client
    5. //application.properties配置文件修改
    6. //增加服务端注册中心地址
    7. eureka.client.service-url.defaultZone=http://localhost:8000/eureka/
    8. =====先启动server,再启动子模块客户端服务,查看服务端网页注册情况,注册成功

    三、利用Fegin实现服务间调用(子模块业务间调用,不经过网关,需要携带网关的Session信息,只用RequestInterceptor请求拦截器)

    1. 三、利用Fegin实现服务间调用(pom引入依赖、加配置、引注解)
    2. //引入pom
    3. org.springframework.cloud
    4. spring-cloud-starter-openfeign
    5. //启动类加注解@EnableFeignClients,拥有调用Feign的能力
    6. @SpringBootApplication
    7. @EnableFeignClients
    8. public class CoursePriceApplication {
    9. public static void main(String[] args) {
    10. SpringApplication.run(CoursePriceApplication.class, args);
    11. }
    12. }
    13. //代码新增其他模块提供的服务接口用作Feign客户端
    14. @FeignClient(value="course-list") value一般为要调用的子模块的服务名,接口为对外提供的接口,引用的实体可依赖其他模块
    15. public interface CourseListClient {
    16. @GetMapping("/courses")
    17. List courseList();
    18. }
    19. //使用注解在其他方法内直接调用
    20. //子模块调用携带网关的Session信息
    21. /**
    22. * 描述: Feign请求拦截器
    23. */
    24. @EnableFeignClients
    25. @Configuration
    26. public class FeignRequestInterceptor implements RequestInterceptor {
    27. @Override
    28. public void apply(RequestTemplate requestTemplate) {
    29. //通过RequestContextHolder获取到请求
    30. RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
    31. if (requestAttributes == null) {
    32. return;
    33. }
    34. HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
    35. Enumeration headerNames = request.getHeaderNames();
    36. if (headerNames != null) {
    37. while (headerNames.hasMoreElements()) {
    38. String name = headerNames.nextElement();
    39. Enumeration values = request.getHeaders(name);
    40. while (values.hasMoreElements()) {
    41. String value = values.nextElement();
    42. requestTemplate.header(name, value);
    43. }
    44. }
    45. }
    46. }
    47. }

    四、使用Ribbon实现负载均衡

    1. //四、指定对应服务使用ribbon负载均衡(加配置)
    2. course-list.ribbon.NFLoadBanlancerRuleClassName=com.netflix.loadbalancer.RoundRobinRule
    3. 要调用的服务名.ribbon.NFLoadBanlancerRuleClassName=负载均衡策略

    五、 使用熔断器Hystrix

    1. //五、使用断路器(加依赖、加配置,加注解,代码引入)
    2. //在调用方加入断路器
    3. //加入pom依赖
    4. org.springframework.cloud
    5. spring-cloud-starter-netflix-hystrix
    6. //application.properties配置文件修改
    7. feign.hystrix.enabled=true 开启断路器配置,默认不开启
    8. //启动类加入断路器注解@EnableCircuitBreaker
    9. @SpringBootApplication
    10. @EnableFeignClients
    11. @EnableCircuitBreaker
    12. public class CoursePriceApplication {
    13. public static void main(String[] args) {
    14. SpringApplication.run(CoursePriceApplication.class, args);
    15. }
    16. }
    17. //编码引入,断路后如何进行处理
    18. //新建断路器实现类,针对要调用的类接口进行断路后处理实现
    19. @Component
    20. public class CourseListClientHystrix implements CourseListClient {
    21. @Override
    22. public List courseList() {
    23. return Collections.emptyList();
    24. }
    25. }
    26. //之前的Feign客户端进行断路器配置,增加fallback指定发生错误要调用的类
    27. @FeignClient(value = "course-list", fallback = CourseListClientHystrix.class)
    28. @Primary
    29. public interface CourseListClient {
    30. @GetMapping("/courses")
    31. List courseList();
    32. }
    33. ===测试,要调用的服务停止,访问接口不会报错

    六、使用网关Zuul实现路由功能

    1. //六、使用网关Zuul实现路由功能(Zuul服务注册,引入依赖,配置路由地址)
    2. //新建独立子模块Zuul
    3. //引入pom依赖(客户端,网关依赖)
    4. org.springframework.cloud
    5. spring-cloud-starter-netflix-eureka-client
    6. org.springframework.cloud
    7. spring-cloud-starter-netflix-zuul
    8. //新建启动类(加注解@EnableZuulProxy,@SpringCloudApplication)
    9. @EnableZuulProxy
    10. @SpringCloudApplication
    11. public class ZuulGatewayApplication {
    12. public static void main(String[] args) {
    13. SpringApplication.run(ZuulGatewayApplication.class, args);
    14. }
    15. }
    16. //application.properties加配置
    17. spring.application.name=course-gateway
    18. server.port=9000
    19. 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}
    20. mybatis.configuration.map-underscore-to-camel-case=true
    21. eureka.client.service-url.defaultZone=http://localhost:8000/eureka/ //服务注册地址
    22. //配置路由地址(可不加使用默认配置,直接ip端口加注册中心子模块服务名+方法名)
    23. zuul.prefix=/imooc //前缀
    24. zuul.routes.course-list.path=/list/** //子模块路径别名
    25. zuul.routes.course-list.service-id=course-list //与path搭配使用,指定子服务名
    26. zuul.routes.course-price.path=/price/** //同上
    27. zuul.routes.course-price.service-id=course-price
    28. //配置完成 使用ip端口加配置前缀+子服务路径别名+方法名

    七、使用Zuul网关实现过滤器功能

    如下:

    1. /**
    2. * 描述: 前置过滤器
    3. */
    4. @Component
    5. public class PreRequestFilter extends ZuulFilter {
    6. @Override
    7. public String filterType() {
    8. //请求之前过滤
    9. return FilterConstants.PRE_TYPE;
    10. }
    11. //排序,该值越小,filter越早执行
    12. @Override
    13. public int filterOrder() {
    14. return 5;
    15. }
    16. //开关,表示是否需要执行该filter
    17. @Override
    18. public boolean shouldFilter() {
    19. //return true;
    20. //如:过滤部分请求
    21. RequestContext ctx = RequestContext.getCurrentContext();
    22. HttpServletRequest request = ctx.getRequest();
    23. String requestURI = request.getRequestURI();
    24. if (requestURI.contains("images") || requestURI.contains("pay")) {
    25. return false;
    26. }
    27. if (requestURI.contains("cart") || requestURI.contains("order")) {
    28. return true;
    29. }
    30. return false;
    31. }
    32. //filter具体的功能方法
    33. @Override
    34. public Object run() throws ZuulException {
    35. //打印请求链接
    36. //RequestContext currentContext = RequestContext.getCurrentContext();
    37. //System.out.println("URI:" + currentContext.getRequest().getRequestURI());
    38. //return null;
    39. //鉴定用户是否存在
    40. RequestContext currentContext = RequestContext.getCurrentContext();
    41. HttpServletRequest request = currentContext.getRequest();
    42. HttpSession session = request.getSession();
    43. User currentUser = (User)session.getAttribute(Constant.IMOOC_MALL_USER);
    44. if (currentUser == null) {
    45. currentContext.setSendZuulResponse(false);
    46. currentContext.setResponseBody("{\n"
    47. + " \"status\": 10007,\n"
    48. + " \"msg\": \"NEED_LOGIN\",\n"
    49. + " \"data\": null\n"
    50. + "}");
    51. currentContext.setResponseStatusCode(200);
    52. }
    53. return null;
    54. }
    55. }
    56. /**
    57. * 描述: 后置过滤器
    58. */
    59. @Component
    60. public class PostRequestFilter extends ZuulFilter {
    61. @Override
    62. public String filterType() {
    63. return FilterConstants.POST_TYPE;
    64. }
    65. @Override
    66. public int filterOrder() {
    67. return FilterConstants.SEND_RESPONSE_FILTER_ORDER - 1;
    68. }
    69. @Override
    70. public boolean shouldFilter() {
    71. return true;
    72. }
    73. @Override
    74. public Object run() throws ZuulException {
    75. RequestContext currentContext = RequestContext.getCurrentContext();
    76. int status = currentContext.getResponse().getStatus();
    77. System.out.println("response status:" + status);
    78. return null;
    79. }
    80. }

    其他:

    一、多模块Session共享机制(使用Redis)

    1. 使用redis实现多服务session共享
    2. //修改application.properties配置,增加redis配置
    3. //各业务模块增加session配置
    4. spring.session.store-type=redis session方案指定为redis
    5. spring.redis.host=localhost
    6. spring.redis.port=6379
    7. spring.redis.password=
    8. //网关模块增加redis配置
    9. spring.session.store-type=redis
    10. spring.redis.host=localhost
    11. spring.redis.port=6379
    12. spring.redis.password=
    13. zuul.sensitive-headers= 为空,无需要过滤的headers
    14. zuul.host.connect-timeout-millis=15000 网关超时时间15s
    15. //启动类增加注解@EnableRedisHttpSession

    二、微服务应用开发重难点环节

    重难点:模块拆分设计、公共模块、Zuul过滤器、Session处理、Feign调用

    常见错误:模块粒度不合适、无公共模块、各接口独立校验、session无法共享、HTTP手动调用

    三、微服务子模块通过网关访问文件,需配置地址映射 

    1. /**
    2. * 描述: 配置地址映射
    3. */
    4. @Configuration
    5. public class ImoocMallWebMvcConfig implements WebMvcConfigurer {
    6. @Override
    7. public void addResourceHandlers(ResourceHandlerRegistry registry) {
    8. registry.addResourceHandler("/images/**")
    9. .addResourceLocations("file:" + ProductConstant.FILE_UPLOAD_DIR);
    10. registry.addResourceHandler("swagger-ui.html").addResourceLocations(
    11. "classpath:/META-INF/resources/");
    12. registry.addResourceHandler("/webjars/**").addResourceLocations(
    13. "classpath:/META-INF/resources/webjars/");
    14. }
    15. }

    四、缓存的配置类

    1. /**
    2. * 描述: 缓存的配置类
    3. */
    4. @Configuration
    5. @EnableCaching
    6. public class CachingConfig {
    7. @Bean
    8. public RedisCacheManager redisCacheManager(RedisConnectionFactory connectionFactory) {
    9. RedisCacheWriter redisCacheWriter = RedisCacheWriter
    10. .lockingRedisCacheWriter(connectionFactory);
    11. RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
    12. cacheConfiguration = cacheConfiguration.entryTtl(Duration.ofSeconds(30));
    13. RedisCacheManager redisCacheManager = new RedisCacheManager(redisCacheWriter,
    14. cacheConfiguration);
    15. return redisCacheManager;
    16. }
    17. }

  • 相关阅读:
    企业单位公众号如何上传附件(如Word,Excel,PPT等)
    目录授予777权限却还是无法进入的解决方案
    Rust交互式编程环境搭建
    StorageReview公布浪潮固态硬盘与浪潮服务器性能测试报告
    Echart基础入门、知识点全总结、自适应,在 Vue项目中使用
    深度学习推理框架汇总
    JSP介绍及常用方法
    11.MMD 人物模型修改:换头换装改模
    奥密克戎 (Omicron) 知多少m?| MedCheExpress
    瞄准镜-第12届蓝桥杯Scratch选拔赛真题精选
  • 原文地址:https://blog.csdn.net/TurboAnho/article/details/127691110