JoyLau's Blog

JoyLau 的技术学习与思考

问题

brew update 遇到错误, 错误信息如下:

script
1
2
3
4
5
6
7
Updating Homebrew...
Warning: You are using macOS 10.15.
We do not provide support for this pre-release version.
You will encounter build failures with some formulae.
Please create pull requests instead of asking for help on Homebrew's GitHub,
Discourse, Twitter or IRC. You are responsible for resolving any issues you
experience, as you are running this pre-release version.

解决方式

  1. brew doctor

运行后发现源为科大的源, 于是切换回原来的官方的 brew 源

script
1
2
cd "$(brew --repo)"
git remote set-url origin https://github.com/Homebrew/brew.git

有其他问题,建议按照提示一一解决掉

  1. brew update

更新成功

  1. brew config

查看配置

错误

MacOS 升级到 10.15 版本时,预览文件出现下面的提示

qlPlugin-not-work

解决方式 1

删除 ~/Library/QuickLook 目录下的隔离属性 (quarantine attribute)

运行下面命令查看属性:

script
1
xattr -r ~/Library/QuickLook

运行下列命令移除这些属性:

script
1
xattr -d -r com.apple.quarantine ~/Library/QuickLook

解决方式 2

  1. 空格预览文件出现下列提示,点击 取消
qlPlugin-not-work
  1. 转到系统设置里
qlPlugin-solution-1

点击 “Allow Anyway”

  1. 使用下列命令打开刚才需要预览的文件
script
1
qlmanage -p /path/to/any/file.js
  1. 此时弹出提示,点击 “open”
qlPlugin-solution-2
  1. 然后就可以预览该后缀名的所有文件了
qlPlugin-solution-3
  1. 如果需要预览其他类型的文件,则将上述步骤重新操作一遍, 换个后缀名即可

最后推荐

推荐下自己使用的预览插件

script
1
brew cask reinstall qlcolorcode qlstephen qlmarkdown quicklook-json qlimagesize suspicious-package quicklookase qlvideo

需要注意的是 qlcolorcode 需要 highlight 库来显示高亮效果, 需要安装: brew install highlight

背景

在一次生产环境部署 elasticsearch 节点时 docker 容器设置了 –restart always,
此时 elasticsearch 的一个节点发生了 java.lang.OutOfMemoryError: Java heap space
容器并没有重启

elasticsearch 已经设置了 -Xms -Xmx

解释

JVM堆内存超出xmx限制,并抛java.lang.OutOfMemoryError: Java heap space异常。堆内存爆了之后,JVM和java进程会继续运行,并不会crash

解决

当JVM出现 OutOfMemoryError,要让 JVM 自行退出, 这样容器就会触发重启

添加新的 jvm 配置: ExitOnOutOfMemoryError and CrashOnOutOfMemoryError

该配置支持 jdk8u92 版本及其之后的版本

地址: https://www.oracle.com/technetwork/java/javase/8u92-relnotes-2949471.html

oracle 官网的原话:

New JVM Options added: ExitOnOutOfMemoryError and CrashOnOutOfMemoryError
Two new JVM flags have been added:

ExitOnOutOfMemoryError - When you enable this option, the JVM exits on the first occurrence of an out-of-memory error. It can be used if you prefer restarting an instance of the JVM rather than handling out of memory errors.

CrashOnOutOfMemoryError - If this option is enabled, when an out-of-memory error occurs, the JVM crashes and produces text and binary crash files (if core files are enabled).

ExitOnOutOfMemoryError: 启用此选项时,JVM在第一次出现内存不足错误时退出。如果您希望重新启动JVM实例而不是处理内存不足错误,则可以使用它。
CrashOnOutOfMemoryError: 如果启用此选项,则在发生内存不足错误时,JVM崩溃并生成文本和二进制崩溃文件(如果启用了核心文件)。

加上配置

ES_JAVA_OPTS = “-XX:+ExitOnOutOfMemoryError”

git 命令显示中文

直接在终端中执行下面的命令
git config –global core.quotepath false

文件回滚

  1. 工作区尚未暂存的文件: git checkout – 文件名
  2. 已添加到暂存区: git reset HEAD 文件名 && git checkout – 文件名
  3. 已提交到本地库, 想要撤销提交,并恢复到之前的文件内容: git reset –hard HEAD^

其中:
git reset 有三种参数:

  • Soft:这个模式仅仅撤销 commit 记录而已,不影响本地的任何文件,即本地修改的文件内容还会存在,也不影响(index)缓存区的任何文件。
  • Hard:不仅撤销 commit 记录,还将本地的文件指向 commit 前的版本,同时 index 也会指向 commit 前的版本。
  • Mixed:回滚 index ,其余的保持不变。

另外 HEAD 后面加上 ~1 代表回滚一次 commit 记录, HEAD^ 代表全部 commit 记录

git fetch 和 git pull

  1. git fetch : 将本地仓库指向的 remote 提交记录更新为和远端一致,即最新,其他的不做任何改变
  2. git pull : 将本地仓库和将本地仓库指向的 remote 都更新为最新, 相当于 fetch + merge

参看: https://blog.csdn.net/qq_37420939/article/details/89736567

git merge 和 git rebase

merge 和 rebase 都是 git pull 时的策略

git rebase 有以下几种使用场景:

  1. 合并本地的多次提交记录

合并最近的 4 次提交纪录

1
2

git rebase -i HEAD~4

在 idea 中可以在 Version Control 中选择最早时间的提交记录, 然后选择 Interactively Rebase from Here
然后除了第一个为pick外,其他选择squash,点击start rebasing,接着输入提交信息就可以把多次commit合并为一次了

  1. 分支合并,可以把本地未push的分叉提交历史整理成直线

将提交合并到其他分支上

有时候我们在某一个分支上提交了一些代码, 需要将这次提交合并到其他分支上, 这时的做法是:

这当前分支上使用 git log 查看需要进行合并的提交记录的 ID

切换到需要合并的分支上: git checkout 分支名

进行合并: git cherry-pick commitId

推送到到上游分支: git push

spring boot 后台的配置

这里记录一些坑
使用 gradle 配置, 其中移除了 Tomcat , 使用的是 Undertow
先引入依赖

implementation ('org.springframework.boot:spring-boot-starter-websocket')

提示报错 web 容器没有实现 JSR356
undertow 肯定是实现了 JSR356, 在 undertow-websockets-jsr 这个依赖里
判断肯定是由于移除 Tomcat 的问题,查看依赖发现 spring-boot-starter-websocket 依赖了 web , 而 web 默认使用的就是 Tomcat
于是移除 web 依赖即可

1
2
3
implementation ('org.springframework.boot:spring-boot-starter-websocket'){
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-web'
}

代码部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Configuration
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
// config.enableSimpleBroker("/topic");
}

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.setAllowedOrigins("*")
.withSockJS();
}

}

注意在启动类上加入: @EnableWebSocketMessageBroker

这里使用的是 stomp 协议, 于是也要前端使用 stomp 配合

发送消息可以加入 @SendTo 注解, 还有一种方式, 就是使用 SimpMessagingTemplate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RestController
@RequestMapping("ws")
public class PushMessage {

private final SimpMessagingTemplate template;

public PushMessage(SimpMessagingTemplate template) {
this.template = template;
}

@GetMapping("/config")
public void configMessage() {
template.convertAndSend("/topic/public", MessageBody.success());
}
}

React 配置

安装组件 npm install react-stomp
自行封装一个组件,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import React, {Component} from 'react';
import SockJsClient from "react-stomp";
import {message} from "antd";

class Websocket extends Component {

render() {
return (
<div>
<SockJsClient
url={'ws'}
topics={[]}
onMessage={(payload) => {
console.info(payload)
}}
onConnect={() => {
console.info("websocket connect success")
}}
onConnectFailure={() => {
message.error("websocket 连接失败!")
}}
onDisconnect={() => {
console.info("websocket disconnect")
}}
debug={false}
{...this.props}
/>
</div>
);
}
}

export default Websocket;

子组件使用:

1
2
3
4
5
6
7
<Websocket
topics={['/topic/public']}
debug={false}
onMessage={(payload) => {
// do somthing
}}
/>

遇坑解决

以上方式看起来使用没有问题,但是现实情况往往开发时前后端分离,请求后端接口往往在 node 项目里配置代理, 这里涉及到 websocket 的代理

之前的配置都是在 package.json 配置, 比如:

1
"proxy": "http://localhost:8098"

但是这种方式对 websocket 的代理失败,会发现 websocket 连接不上

解决方式:
在新版的 customize-cra 的使用方式里:
先安装 http-proxy-middleware : npm install http-proxy-middleware
在 src 目录下新建文件 setupProxy.js, 名字不可改,一定要是这个文件名

1
2
3
4
5
6
7
8
9
10
11
12
const proxy = require("http-proxy-middleware");
const pck = require('../package');

module.exports = app => {
app.use(
proxy("/ws",
{
target: pck.proxy,
ws: true
})
)
};

这里开启 ws: true 即可完成 websocket 的代理.

添加多页面配置

之前写过一篇 npm eject 之后的多页面配置,可以往前翻阅 , 现在不想 eject, 该怎么配置多页面?

  1. npm install react-app-rewire-multiple-entry –save-dev

  2. 在 config-overrides.js 中添加配置
    现在 public 里复制一个 html 页面, 在 src 目录下再新增一个目录,里面的文件拷贝 index 的稍微改动下,
    大致目录如下:

-serviceWorker.js
-metadata.js
-metadata.css
-logo.svg
-App.test.js
-App.js
-App.css

基本使用:

1
2
3
4
5
6
7
8
9
10
11
12
const multipleEntry = require('react-app-rewire-multiple-entry')([{
entry: 'src/metadata/metadata.js',
template: 'public/metadata.html',
outPath: '/metadata',
}]);

module.exports = {
webpack: function(config, env) {
multipleEntry.addMultiEntry(config);
return config;
}
};

在 customize-cra 使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const multipleEntry = require('react-app-rewire-multiple-entry')([
{
entry: 'src/entry/landing.js',
template: 'public/landing.html',
outPath: '/landing.html'
}
]);

const {
override,
overrideDevServer
} = require('customize-cra');

module.exports = {
webpack: override(
multipleEntry.addMultiEntry
)
};

结合 ant-design 使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const {override, fixBabelImports, addLessLoader} = require('customize-cra');

const multipleEntry = require('react-app-rewire-multiple-entry')([{
entry: 'src/metadata/metadata.js',
template: 'public/metadata.html',
outPath: '/metadata',
}]);


module.exports = override(
multipleEntry.addMultiEntry,
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: true,
}),
addLessLoader({
javascriptEnabled: true,
modifyVars: { '@primary-color': '#1890ff' },
}),
);

注意,这样配置的话, 请求的 uri 是 /metadata, 在 build 后会生成 metadata 文件, 将打包后的文件拷贝到服务器上运行效果不好
一般我都注释掉 template, 再将 outPath 写成 /metadata.html

打包不生成 source-map 文件

在 配置文件 config-overrides.js 添加 process.env.GENERATE_SOURCEMAP = "false";
或者

在项目更目录下创建文件 .env, 写入: GENERATE_SOURCEMAP=false 即可.

背景

Nested 类型的数据不多说了,
先看 mapping:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
"metaArray": {
"type": "nested",
"properties": {
"key": {
"type": "text",
"analyzer": "ik_max_word",
"fields": {
"full": {
"type": "keyword"
}
}
},
"value": {
"type": "text",
"analyzer": "ik_max_word",
"fields": {
"full": {
"type": "keyword"
}
}
}
}
},

再看数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
"_index":"category_libs_v1.x",
"_type":"category_info",
"_id":"526",
"_version":1,
"_score":1,
"_source":{
"categoryName":"投标文件",
"createTime":"2019-12-23 00:07:15",
"id":"526",
"metaArray":[
{
"value":"Joy",
"key":"作者"
},
{
"value":"txt",
"key":"文件类型"
}
],
"pathName":"企业空间导航/业务条块",
"pids":"|1|525|",
"status":0,
"updateTime":"2019-12-23 00:07:15"
}
}

目的

想查作者是 Joy 并且文件类型是 txt 的记录

方式

使用 nestedQuery + queryStringQuery

语句:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
"from":0,
"size":10,
"query":{
"bool":{
"must":[
{
"nested":{
"query":{
"query_string":{
"query":"metaArray.key.full:作者 AND metaArray.value.full:Joy"
}
},
"path":"metaArray",
"score_mode":"max"
}
},
{
"nested":{
"query":{
"query_string":{
"query":"metaArray.key.full:文件类型 AND metaArray.value.full:txt"
}
},
"path":"metaArray",
"score_mode":"max"
}
}
]
}
}
}

代码:

1
2
3
String key = xxxx
String value = xxxx
nestedQuery("metaArray", queryStringQuery("metaArray.key.full:" + key + " AND metaArray.value.full:" + value), ScoreMode.Max);

背景

之前一直用我弟弟的学生证申请的 license,可惜今年毕业了,无法在续费申请了
早期已经听说 JetBrains 可以使用自己的开源项目进行申请免费的 license
正好使用我的这个博客来申请一波

步骤

  1. 前往 JetBrains 官方提供的申请链接 (https://www.jetbrains.com/shop/eform/opensource?product=ALL)
  2. 填写资料,其中注意,需要在项目的根目录下创建 License 文件,类型没有差别,我使用的是 MIT LICENSE,还有就是邮箱地址和 github profile 页面的邮箱地址一致
  3. 等待了 2 天,收到了 JetBrains 工作人员的回复
  4. 点击邮件中的 Take me to my license(s)
  5. 使用申请的邮箱地址登录已有的账号或者创建新的账号
  6. 登录成功后点击 license tab 页面,会看到你填的项目名
  7. 点击 Active subscriptions, 激活,在点击 Assign分配使用
  8. 看到一些提示成功信息,就说明没有问题了,直接在 IDEA 的激活页面登录账户使用即可

小插曲

我这里因为之前使用 QQ 邮箱创建过 JetBrains 的账号,这次不想使用新的邮箱再次创建账号
于是在第四步点击 Take me to my license(s) 后,我选择授权其他邮箱,填写邮箱地址,之后你的邮箱会收到邮件,点击接受授权的链接
之后的操作都一致了,成功使用我原来的邮箱获取到了 license.

0%