最近决定搭建的自己的技术中台,之前想短平快,只用本地jar包,工具类,通用代码之类的。

发现,有些场景复用不太方便。

为了长远打算,也需要搭建自己的技术中台,提供RPC和HTTP各种通用基础服务,比如内容管理等等。

也可能用本地jar包模式,直接访问数据库。

看情况吧。

 

------------------

搭建整合项目的过程中,遇到了太多的问题,真是累坏了。

晚饭还没吃。

不太喜欢直接照搬复制别人的代码,再修改。

第1次,不花时间,不交学费,今后遇到问题了,同样花时间。

第1次,从0开始,不断参考网友的思路,可以更全面逐步低学习。

在解决各种各样的问题中,还是有很大进步的。

有个问题值得说下,包括本文在内的文章,再总结的时候,很难面面俱到,注意到每一个细节。代码可以运行,但是懒得上传到Github上,因此参考别人的思路时,需要注意 不同文章的不同点。

 

每一个细节都注意到了,才学得更全面。

今后遇到各种问题都能解决。

通用问题,大家都会遇到。

一个问题可以有多种解决办法,根据自己的习惯做选择。

 

--------------------

 

核心过程

1、3个项目

公共接口实体jar包,比较简单,没技术难题

服务提供方,比较关键

服务启动方,注册消费就行

2、一些核心配置,供参考

application.yml
spring:
   profiles:
     active: dev
   dubbo:
     application.name: provider    
     registry.address: redis://47.05.919.4:6379
     registry.username: 1
     registry.password: jtn222d21
     protocol.name: dubbo 
     protocol.port: 20880
     scan: com.j.techplatform.rpc.service@Configuration
 @ComponentScan(basePackages="com.j.common.web.crud.manager.content")
 public class JtnConfig {    @Autowired
     private Environment env;    @Bean(name = "dataSource")
     public DataSource getDataSource() throws Exception {
         Properties props = new Properties();
         props.put("driverClassName", env.getProperty("spring.datasource.driverClassName"));
         props.put("url", env.getProperty("spring.datasource.url"));
         props.put("username", env.getProperty("spring.datasource.username"));
         props.put("password", env.getProperty("spring.datasource.password"));
         return DruidDataSourceFactory.createDataSource(props);
     }}
自己在学习研究MybatisPlus,整合进去了
import java.io.IOException;
import javax.sql.DataSource;
import org.apache.commons.lang3.StringUtils;
 import org.apache.ibatis.logging.stdout.StdOutImpl;
 import org.apache.ibatis.mapping.DatabaseIdProvider;
 import org.apache.ibatis.plugin.Interceptor;
 import org.mybatis.spring.annotation.MapperScan;
 import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.core.io.DefaultResourceLoader;
 import org.springframework.core.io.Resource;
 import org.springframework.core.io.ResourceLoader;
 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
 import org.springframework.core.io.support.ResourcePatternResolver;import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties;
 import com.baomidou.mybatisplus.core.MybatisConfiguration;
 import com.baomidou.mybatisplus.core.MybatisXMLLanguageDriver;
 import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
 import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
 import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;@Configuration
 @MapperScan(basePackages = "com.j.common.web.crud.mapper.content")
 public class MybatisPlusConfig {
     @Autowired
     private DataSource dataSource;    @Autowired
     private MybatisPlusProperties properties;    @Autowired
     private ResourceLoader resourceLoader = new DefaultResourceLoader();    @Autowired(required = false)
     private Interceptor[] interceptors;    @Autowired(required = false)
     private DatabaseIdProvider databaseIdProvider;    /**
      * mybatis-plus分页插件
      */
     @Bean
     public PaginationInterceptor paginationInterceptor() {
         PaginationInterceptor page = new PaginationInterceptor();
         page.setDialectType("mysql");
         return page;
     }    /**
      * 乐观锁插件
      */
     @Bean
     public OptimisticLockerInterceptor optimisticLockerInterceptor() {
         return new OptimisticLockerInterceptor();
     }
     
     
     /**
      * 这里全部使用mybatis-autoconfigure 已经自动加载的资源。不手动指定 配置文件和mybatis-boot的配置文件同步
      */
     @Bean
     public MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean() throws IOException {
         MybatisSqlSessionFactoryBean mybatisPlus = new MybatisSqlSessionFactoryBean();
         mybatisPlus.setDataSource(dataSource);
         mybatisPlus.setVfs(SpringBootVFS.class);
         String configLocation = this.properties.getConfigLocation();
         if (StringUtils.isNotBlank(configLocation)) {
             mybatisPlus.setConfigLocation(this.resourceLoader.getResource(configLocation));
         }
         mybatisPlus.setConfiguration(properties.getConfiguration());
         mybatisPlus.setPlugins(this.interceptors);
         MybatisConfiguration mc = new MybatisConfiguration();
         mc.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
         // 数据库和java都是驼峰,就不需要
         mc.setMapUnderscoreToCamelCase(false);
         //开发环境打印sql
         mc.setLogImpl(StdOutImpl.class);
         mybatisPlus.setConfiguration(mc);
         
         if (this.databaseIdProvider != null) {
             mybatisPlus.setDatabaseIdProvider(this.databaseIdProvider);
         }
         mybatisPlus.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
         mybatisPlus.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
         mybatisPlus.setMapperLocations(this.properties.resolveMapperLocations());
         // 设置mapper.xml文件的路径
         ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
         Resource[] resource = resolver.getResources("classpath:mapper/*.xml");
         mybatisPlus.setMapperLocations(resource);
         return mybatisPlus;
     }
 }
  pom.xml
<parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
         <version>1.5.4.RELEASE</version>
         <relativePath /> <!-- lookup parent from repository -->
     </parent><!--springboot集成dubbo起步依赖-->
 <dependency>
     <groupId>com.alibaba.spring.boot</groupId>
     <artifactId>dubbo-spring-boot-starter</artifactId>
     <version>2.0.0</version>
     </dependency>
              <!-- mvn spring-boot:run 热部署启动 -->
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>springloaded</artifactId>
         </dependency>
     
         <!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
         <dependency>
             <groupId>redis.clients</groupId>
             <artifactId>jedis</artifactId>
         </dependency>
             <!-- https://mvnrepository.com/artifact/commons-pool/commons-pool -->
         <!-- <dependency>
             <groupId>commons-pool</groupId>
             <artifactId>commons-pool</artifactId>
         </dependency> -->
         
         <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
         <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-pool2</artifactId>
         </dependency> 
4、服务提供方先启动,注意扫描到包
@Slf4j
 @SpringBootApplication(scanBasePackages="com.j")
 //@ServletComponentScan
 //@EnableScheduling
 @EnableDubboConfiguration
 public class JtnTechPlatformApplication {    public static void main(String[] args) {
         Stopwatch stopwatch = Stopwatch.createStarted();
         log.info("JtnApplication starting ...");
         SpringApplication.run(JtnTechPlatformApplication.class, args);
         log.info("JtnApplication started. 共耗时{}", stopwatch.stop().toString());
     }
 }

 

遇到的几个问题

1、使用Redis作为注册中心,而非ZooKeeper

自己的阿里云上有现成的Redis服务,也作为缓存在用。

ZooKeeper一般作为标准的注册中心,但是自己这个整合项目,目前主要是能跑起来运行就行,非生产项目。

再搭建维护1个ZooKeeper太麻烦了。

不过话说回来,解决Redis的问题,足够搭建ZooKeeper了。

2、Redis需要使用密码和用户名

(仅供参考)

本地连不上阿里云ECS部署的Redis,提示 超时,超时不可能是密码不对的问题。

查询资料,Redis默认绑定127.0.0.1,注释掉。

设置Redis没密码。

项目能够连上了。

网友有指出Redis作为注册中心,需要设置 用户名。

有网友直接 定制源码,比如 使用1个同名的 类源码 放到自己的目录,再修改。

也有网友指出,用户名可以随便配置,我就随便写了1个,ok。

结论:Redis配置密码,取消bind 本地。

项目中配置 Redis密码,随便配置1个用户名。

3、RPC提供方正常启动,RPC消费方无法消费,提示没用可用的provider.

尝试本地运行dubbo-admin,网上下载了dubbo-admin-2.5.4。

报错,提示 用户名不能为空之类的。

参考网友资料,dubbo-admin-2.6.0之后修复了这个bug。

没用再试了,因为想起来了 RPC提供方应该有问题。

本地日志没用提到Dubbo成功注册 服务到 注册中心。

 

4、@EnableDubboConfiguration  dubbo的注解很关键

5、JtnPostService 是接口定义

JtnPostServiceImpl是接口实现类。

很关键,Spring的@Service和Dubbo的@Service重名了,以为只需要1个。

实际上都需要,但为了方便使用,用Dubbo的@Service,用Spring的@Component  代替Spring自己的@Service、

import org.springframework.stereotype.Component;

com.alibaba.dubbo.config.annotation.Service;

@Service
@Component 
public class JtnPostServiceImpl implements JtnPostService {

 

}

 

6、扫描包

@SpringBootApplication(scanBasePackages="com.j")

可能会有问题,手动执行,比较清晰

7、消费方,用@Reference注解。

public class PostController {

    @Reference
    //@Autowired
    private JtnPostService postService;

}

8. dubbo生产者和消费者的配置,name应该不同,没具体研究。

scan记得扫描,配置自己的包路径。

spring:
   profiles:
     active: dev
   dubbo:
     application.name: consumer    
     registry.address: redis://47.15.9.4:6379
     registry.username: 1
     registry.password: jn2213
     protocol.name: dubbo 
     protocol.port: 20880
     scan: com.j 
spring:
   profiles:
     active: dev
   dubbo:
     application.name: provider    
     registry.address: redis://47.1125.99.4:6379
     registry.username: 1
     registry.password: ssdssafd
     protocol.name: dubbo 
     protocol.port: 20880
     scan: com.j.techplatform.rpc.service


 

 

参考资料

Spring-boot:5分钟整合Dubbo构建分布式服务

 

springboot+mybatis+dubbo+redis简单整合

spring boot + Dubbo + Redis注册中心 实现RPC调用

SpringBoot+dubbo 注解方式实现入门

 

dubbo整合使用有密码的redis作注册中心,并且使用指定的redis库

 

阿里云部署redis服务器,以及远程访问

 

6.记录安装dubbo2.6.0的admin控制台

Dubbo后台管理和监控中心部署